source map exposed analyzed
https://4njbets.us.betfair.com/static/bslp/js/common-betslip.4cecc041.js
map: https://4njbets.us.betfair.com/static/bslp/js/common-betslip.4cecc041.js.map
124 source files 6.6 MB map size 39 endpoints found 3 secrets found discovered 5 hours, 21 minutes ago
124
source files
6.6 MB
map size
3
secrets
39
endpoints

secrets from source map (3)

gcpKey {'key': 'AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU'} 0.9
Source: vendors/tvg-configuration/configurationMod.min.js
internal_url if (process.env.NODE_ENV !== 'test' && typeof window !== 'undefined' && window.XDomainRequest && !('withCredentials' in request) && !isURLSameOrigin(config.url)) { 0.8
Source map: ../node_modules/@tvg/deposit-gtm/build/bundle.js
    // Only supports POST and GET calls and doesn't returns the response headers.
    // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest.
    if (process.env.NODE_ENV !== 'test' && typeof window !== 'undefined' && window.XDomainRequest && !('withCredentials' in request) && !isURLSameOrigin(config.url)) {
      request = new window.XDomainRequest();
      loadEvent = 'onload';
internal_url if (process.env.NODE_ENV !== 'test') { 0.8
Source map: ../node_modules/@tvg/graph/dist/tvg-graph.mod.umd.js
        if (!haveWarned) {
            console.warn("You're using fragments in your queries, but don't have the addTypename:\ntrue option set in Apollo Client. Please turn on that option so that we can accurately\nmatch fragments.");
            if (process.env.NODE_ENV !== 'test') {
                haveWarned = true;
            }

endpoints from source map (39)

GET /featureToggles/legacy/
GET https://maps.googleapis.com/maps/api/js?key=
GET //cdn.optimizely.com/js/3131590850.js
GET uib/template/accordion/accordion.html
GET uib/template/accordion/accordion-group.html
GET uib/template/alert/alert.html
GET uib/template/carousel/carousel.html
GET uib/template/carousel/slide.html
GET uib/template/datepicker/datepicker.html
GET uib/template/datepicker/day.html
GET uib/template/datepicker/month.html
GET uib/template/datepicker/year.html
GET uib/template/datepickerPopup/popup.html
GET uib/template/modal/window.html
GET uib/template/pager/pager.html
GET uib/template/pagination/pagination.html
GET uib/template/tooltip/tooltip-popup.html
GET uib/template/tooltip/tooltip-template-popup.html
GET uib/template/tooltip/tooltip-html-popup.html
GET uib/template/popover/popover-template.html
GET uib/template/popover/popover-html.html
GET uib/template/popover/popover.html
GET uib/template/progressbar/progress.html
GET uib/template/progressbar/bar.html
GET uib/template/progressbar/progressbar.html
GET uib/template/rating/rating.html
GET uib/template/tabs/tabset.html
GET uib/template/tabs/tab.html
GET uib/template/timepicker/timepicker.html
GET uib/template/typeahead/typeahead-popup.html
GET uib/template/typeahead/typeahead-match.html
GET pending-withdraw-element.html
GET manage-payment-methods.html
GET new-payment-method.html
GET payment-method-on-file-list.html
GET deposit-limits.html
GET payment-methods-type-selector.html
GET payment-method-on-file-option.html
GET transfer-source-destination.html

source file tree (124)

124 files with original source
../node_modules/almond/almond.js
/**
 * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
 * Available via the MIT or new BSD license.
 * see: http://github.com/jrburke/almond for details
 */
//Going sloppy to avoid 'use strict' string cost, but strict practices should
//be followed.
/*jslint sloppy: true */
/*global setTimeout: false */

var requirejs, require, define;
(function (undef) {
    var main, req, makeMap, handlers,
        defined = {},
        waiting = {},
        config = {},
        defining = {},
        hasOwn = Object.prototype.hasOwnProperty,
        aps = [].slice,
        jsSuffixRegExp = /\.js$/;

    function hasProp(obj, prop) {
        return hasOwn.call(obj, prop);
    }

    /**
     * Given a relative module name, like ./something, normalize it to
     * a real name that can be mapped to a path.
     * @param {String} name the relative name
     * @param {String} baseName a real name that the name arg is relative
     * to.
     * @returns {String} normalized name
     */
    function normalize(name, baseName) {
        var nameParts, nameSegment, mapValue, foundMap, lastIndex,
            foundI, foundStarMap, starI, i, j, part,
            baseParts = baseName && baseName.split("/"),
            map = config.map,
            starMap = (map && map['*']) || {};

        //Adjust any relative paths.
        if (name && name.charAt(0) === ".") {
            //If have a base name, try to normalize against it,
            //otherwise, assume it is a top-level require that will
            //be relative to baseUrl in the end.
            if (baseName) {
                //Convert baseName to array, and lop off the last part,
                //so that . matches that "directory" and not name of the baseName's
                //module. For instance, baseName of "one/two/three", maps to
                //"one/two/three.js", but we want the directory, "one/two" for
                //this normalization.
                baseParts = baseParts.slice(0, baseParts.length - 1);
                name = name.split('/');
                lastIndex = name.length - 1;

                // Node .js allowance:
                if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
                    name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
                }

                name = baseParts.concat(name);

                //start trimDots
                for (i = 0; i < name.length; i += 1) {
                    part = name[i];
                    if (part === ".") {
                        name.splice(i, 1);
                        i -= 1;
                    } else if (part === "..") {
                        if (i === 1 && (name[2] === '..' || name[0] === '..')) {
                            //End of the line. Keep at least one non-dot
                            //path segment at the front so it can be mapped
                            //correctly to disk. Otherwise, there is likely
                            //no path mapping for a path starting with '..'.
                            //This can still fail, but catches the most reasonable
                            //uses of ..
                            break;
                        } else if (i > 0) {
                            name.splice(i - 1, 2);
                            i -= 2;
                        }
                    }
                }
                //end trimDots

                name = name.join("/");
            } else if (name.indexOf('./') === 0) {
                // No baseName, so this is ID is resolved relative
                // to baseUrl, pull off the leading dot.
                name = name.substring(2);
            }
        }

        //Apply map config if available.
        if ((baseParts || starMap) && map) {
            nameParts = name.split('/');

            for (i = nameParts.length; i > 0; i -= 1) {
                nameSegment = nameParts.slice(0, i).join("/");

                if (baseParts) {
                    //Find the longest baseName segment match in the config.
                    //So, do joins on the biggest to smallest lengths of baseParts.
                    for (j = baseParts.length; j > 0; j -= 1) {
                        mapValue = map[baseParts.slice(0, j).join('/')];

                        //baseName segment has  config, find if it has one for
                        //this name.
                        if (mapValue) {
                            mapValue = mapValue[nameSegment];
                            if (mapValue) {
                                //Match, update name to the new value.
                                foundMap = mapValue;
                                foundI = i;
                                break;
                            }
                        }
                    }
                }

                if (foundMap) {
                    break;
                }

                //Check for a star map match, but just hold on to it,
                //if there is a shorter segment match later in a matching
                //config, then favor over this star map.
                if (!foundStarMap && starMap && starMap[nameSegment]) {
                    foundStarMap = starMap[nameSegment];
                    starI = i;
                }
            }

            if (!foundMap && foundStarMap) {
                foundMap = foundStarMap;
                foundI = starI;
            }

            if (foundMap) {
                nameParts.splice(0, foundI, foundMap);
                name = nameParts.join('/');
            }
        }

        return name;
    }

    function makeRequire(relName, forceSync) {
        return function () {
            //A version of a require function that passes a moduleName
            //value for items that may need to
            //look up paths relative to the moduleName
            return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));
        };
    }

    function makeNormalize(relName) {
        return function (name) {
            return normalize(name, relName);
        };
    }

    function makeLoad(depName) {
        return function (value) {
            defined[depName] = value;
        };
    }

    function callDep(name) {
        if (hasProp(waiting, name)) {
            var args = waiting[name];
            delete waiting[name];
            defining[name] = true;
            main.apply(undef, args);
        }

        if (!hasProp(defined, name) && !hasProp(defining, name)) {
            throw new Error('No ' + name);
        }
        return defined[name];
    }

    //Turns a plugin!resource to [plugin, resource]
    //with the plugin being undefined if the name
    //did not have a plugin prefix.
    function splitPrefix(name) {
        var prefix,
            index = name ? name.indexOf('!') : -1;
        if (index > -1) {
            prefix = name.substring(0, index);
            name = name.substring(index + 1, name.length);
        }
        return [prefix, name];
    }

    /**
     * Makes a name map, normalizing the name, and using a plugin
     * for normalization if necessary. Grabs a ref to plugin
     * too, as an optimization.
     */
    makeMap = function (name, relName) {
        var plugin,
            parts = splitPrefix(name),
            prefix = parts[0];

        name = parts[1];

        if (prefix) {
            prefix = normalize(prefix, relName);
            plugin = callDep(prefix);
        }

        //Normalize according
        if (prefix) {
            if (plugin && plugin.normalize) {
                name = plugin.normalize(name, makeNormalize(relName));
            } else {
                name = normalize(name, relName);
            }
        } else {
            name = normalize(name, relName);
            parts = splitPrefix(name);
            prefix = parts[0];
            name = parts[1];
            if (prefix) {
                plugin = callDep(prefix);
            }
        }

        //Using ridiculous property names for space reasons
        return {
            f: prefix ? prefix + '!' + name : name, //fullName
            n: name,
            pr: prefix,
            p: plugin
        };
    };

    function makeConfig(name) {
        return function () {
            return (config && config.config && config.config[name]) || {};
        };
    }

    handlers = {
        require: function (name) {
            return makeRequire(name);
        },
        exports: function (name) {
            var e = defined[name];
            if (typeof e !== 'undefined') {
                return e;
            } else {
                return (defined[name] = {});
            }
        },
        module: function (name) {
            return {
                id: name,
                uri: '',
                exports: defined[name],
                config: makeConfig(name)
            };
        }
    };

    main = function (name, deps, callback, relName) {
        var cjsModule, depName, ret, map, i,
            args = [],
            callbackType = typeof callback,
            usingExports;

        //Use name if no relName
        relName = relName || name;

        //Call the callback to define the module, if necessary.
        if (callbackType === 'undefined' || callbackType === 'function') {
            //Pull out the defined dependencies and pass the ordered
            //values to the callback.
            //Default to [require, exports, module] if no deps
            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
            for (i = 0; i < deps.length; i += 1) {
                map = makeMap(deps[i], relName);
                depName = map.f;

                //Fast path CommonJS standard dependencies.
                if (depName === "require") {
                    args[i] = handlers.require(name);
                } else if (depName === "exports") {
                    //CommonJS module spec 1.1
                    args[i] = handlers.exports(name);
                    usingExports = true;
                } else if (depName === "module") {
                    //CommonJS module spec 1.1
                    cjsModule = args[i] = handlers.module(name);
                } else if (hasProp(defined, depName) ||
                           hasProp(waiting, depName) ||
                           hasProp(defining, depName)) {
                    args[i] = callDep(depName);
                } else if (map.p) {
                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
                    args[i] = defined[depName];
                } else {
                    throw new Error(name + ' missing ' + depName);
                }
            }

            ret = callback ? callback.apply(defined[name], args) : undefined;

            if (name) {
                //If setting exports via "module" is in play,
                //favor that over return value and exports. After that,
                //favor a non-undefined return value over exports use.
                if (cjsModule && cjsModule.exports !== undef &&
                        cjsModule.exports !== defined[name]) {
                    defined[name] = cjsModule.exports;
                } else if (ret !== undef || !usingExports) {
                    //Use the return value from the function.
                    defined[name] = ret;
                }
            }
        } else if (name) {
            //May just be an object definition for the module. Only
            //worry about defining if have a module name.
            defined[name] = callback;
        }
    };

    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
        if (typeof deps === "string") {
            if (handlers[deps]) {
                //callback in this case is really relName
                return handlers[deps](callback);
            }
            //Just return the module wanted. In this scenario, the
            //deps arg is the module name, and second arg (if passed)
            //is just the relName.
            //Normalize module name, if it contains . or ..
            return callDep(makeMap(deps, callback).f);
        } else if (!deps.splice) {
            //deps is a config object, not an array.
            config = deps;
            if (config.deps) {
                req(config.deps, config.callback);
            }
            if (!callback) {
                return;
            }

            if (callback.splice) {
                //callback is an array, which means it is a dependency list.
                //Adjust args if there are dependencies
                deps = callback;
                callback = relName;
                relName = null;
            } else {
                deps = undef;
            }
        }

        //Support require(['a'])
        callback = callback || function () {};

        //If relName is a function, it is an errback handler,
        //so remove it.
        if (typeof relName === 'function') {
            relName = forceSync;
            forceSync = alt;
        }

        //Simulate async callback;
        if (forceSync) {
            main(undef, deps, callback, relName);
        } else {
            //Using a non-zero value because of concern for what old browsers
            //do, and latest browsers "upgrade" to 4 if lower value is used:
            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
            //If want a value immediately, use require('id') instead -- something
            //that works in almond on the global level, but not guaranteed and
            //unlikely to work in other AMD implementations.
            setTimeout(function () {
                main(undef, deps, callback, relName);
            }, 4);
        }

        return req;
    };

    /**
     * Just drops the config on the floor, but returns req in case
     * the config return value is used.
     */
    req.config = function (cfg) {
        return req(cfg);
    };

    /**
     * Expose module registry for debugging and tooling
     */
    requirejs._defined = defined;

    define = function (name, deps, callback) {

        //This module may not have dependencies
        if (!deps.splice) {
            //deps is not an array, so probably means
            //an object literal or factory function for
            //the value. Adjust args.
            callback = deps;
            deps = [];
        }

        if (!hasProp(defined, name) && !hasProp(waiting, name)) {
            waiting[name] = [name, deps, callback];
        }
    };

    define.amd = {
        jQuery: true
    };
}());

define("almond", function(){});

initData.js
var namespaceList = [
    'BetTicket'
];

var cmsCache = {};
var __METADATA = null;

function propertyIsDefined() {
    return function (prop) {
        return !_.isUndefined(prop);
    };
}

function omitAllProperties() {
    return function (feature) {
        return _.omit(feature, propertyIsDefined);
    };
}

function getCMSContent(initInjector, $q, $http) {

    var ContentFac = initInjector.get('ContentFac');
    var ConfigurationFac = initInjector.get('ConfigurationFac');
    var deferred = $q.defer();

    if (clientApp == "tvg4") {
        productContext = "tvg4";
        applicationContext = "desktop";

        ConfigurationFac.setApplicationContextItem('device', 'desktop');
    }

    ConfigurationFac.setApplicationContextItem('product', productContext);
    ConfigurationFac.setApplicationContextItem('application', applicationContext);
    ConfigurationFac.setApplicationContextItem('location', locationContext);

    ContentFac.fetchAllDataFromCMS(namespaceList, false)
        .then(function (data) {
            var requestFeatures = false;
            if (data._featureToggle) {
                var filteredFeatures = _.mapValues(defaultFeatures, omitAllProperties);
                __FEATURES = _.merge(filteredFeatures, sanitiseCmsFeaturesResponse(data._featureToggle));
                delete data._featureToggle;
            } else {
                if(typeof __TVG_GLOBALS__ === 'undefined' || !__TVG_GLOBALS__.FEATURES || !parseData(__TVG_GLOBALS__.FEATURES)) {
                    requestFeatures = true;
                    //request directly to capi
                    var url = ConfigurationFac.getServiceApiUrl('capi');
                    var brand =  locationContext == 'all' ? 'tvg' : locationContext;
                    url = url + '/featureToggles/legacy/' + productContext + '/' + applicationContext + '/' + brand;
                    $http.get(url, {headers: {Accept: 'application/json'}, timeout: 5000})
                        .success(function (response) {
                            __FEATURES = response.response;
                            deferred.resolve(data);
                        })
                }
                else{
                    __FEATURES = parseData(__TVG_GLOBALS__.FEATURES).response;
                }
            }

            if(!requestFeatures) {
                deferred.resolve(data);
            }
        }, function () {
            __FEATURES = defaultFeatures;

            deferred.resolve({});
        });

    return deferred.promise;
}

function sanitiseCmsFeaturesResponse(rawFeatures) {
    var sanitisedFeatures = {};
    _.forEach(rawFeatures, function (rawFeature, key) {
        var obj = {};
        _.attempt(function () {
            obj[key] = JSON.parse(rawFeature);
        });
        _.merge(sanitisedFeatures, obj);
    });
    return sanitisedFeatures;
}

function parseData(data) {
    var object;
    try {
        _.attempt(function () {
            object = JSON.parse(decodeURIComponent(data));
        });
    }
    catch (e) {
    }
    return object;
}

function _validateCMSContent(cmscontent) {
    var valid = false;

    if (typeof(cmscontent) === 'string') {
        var cmsObject = parseData(cmscontent);

        if (typeof cmsObject === 'object' && cmsObject.hasOwnProperty('response')) {
            Object.keys(cmsObject.response).forEach(function (namespace) {
                cmsCache[namespace] = cmsObject.response[namespace];
            });
            valid = true;
        }
    }

    return valid;
}


/**
 * Load script
 *
 * @param  {Promise} Promise              Promise class
 * @param  {String}  src                  File source
 * @param  {Object}  [opts]               Loading options
 * @param  {Object}  [opts.ignoreErrors]  Loading errors will be treated with success
 *                                        to prevent breaking the app startup when
 *                                        third-parties are blocked by addblocker
 *
 * @return {Promise}  Loading script promise
 */
function loadScript(Promise, src, opts) {

    return new Promise(function (resolve, reject) {
        var script = document.createElement('script');

        /**
         * Reject error or ignore them (using resolver)
         * @param  {Object} [err]  Error
         */
        var ignoreOrReject = function (err) {
            return (opts || {}).ignoreErrors ?
                resolve() : reject(err);
        };

        /**
         * Script loading error (e.g. blocked by addblocker)
         */
        script.onerror = function (err) {
            return ignoreOrReject(err);
        };

        /**
         * Bind to script "state change" to check when file is loaded
         */
        script.onload = script.onreadystatechange = function () {
            if (!this.readyState || this.readyState == 'complete') {
                return resolve();
            }

            return ignoreOrReject();
        };

        script.async = true;
        script.src = src;

        document.getElementsByTagName('head')[0].appendChild(script);
    });
}

function _createGoogleMapsAPI(Promise, apiKey) {
    return loadScript(Promise, 'https://maps.googleapis.com/maps/api/js?key=' + apiKey + '&libraries=places', {
        ignoreErrors: true
    });
}

function _loadOptimizely(Promise) {
    // ignore (don't know why?...)
    if (window.opener) {
        Promise.resolve();
    }

    return loadScript(Promise, '//cdn.optimizely.com/js/3131590850.js', {
        ignoreErrors: true
    });
}

/*
 Method to get all information needed to load bootstrap app
 */
function initializeApp() {

    /* Angular app initialization */
    var initInjector = angular.injector(['ng', 'ngCookies', 'TVG.Content', 'TVG.Configuration']);
    var $http = initInjector.get('$http');
    var $q = initInjector.get('$q');
    var $cookies = initInjector.get('$cookies');
    var ConfigurationFac = initInjector.get('ConfigurationFac');

    var ContentFac = initInjector.get('ContentFac');

    $http.defaults.headers.common = {'X-ClientApp': clientApp};

    var promisesList = [];

    // Parse or request CMSCONTENT
    if (typeof __TVG_GLOBALS__ !== 'undefined' && __TVG_GLOBALS__.MESSAGES && _validateCMSContent(__TVG_GLOBALS__.MESSAGES)) {
        ContentFac.restoreCache(cmsCache);
    }

    // CMSContent call should be always made but it will be returned from cache if __CMSCONTENT is valid
    promisesList.push(getCMSContent(initInjector, $q, $http));

    $q.all(promisesList)
        .then(function (data) {
            if (data) {
                __CMSCONTENT = data[0];
                cmsCache = ContentFac.retrieveCache();
            }
        })
        .then(function () {
            var scripts = [
                _createGoogleMapsAPI($q, ConfigurationFac.getGoogleAPIKey('apikey'))
            ];

            if (_.get(__FEATURES, 'enableOptimizely.toggle')) {
                scripts.push(_loadOptimizely($q));
            }

            return $q.all(scripts);
        })
        .then(function () {
            bootApplication();
        }).catch(function (err) {
        console.error(err);
    });
}
;
define("initData", function(){});

defaultFeatures.js
var defaultFeatures = {
    featureOverridesEnabled: {
        description: 'Allow overriding features on local browsers'
    },
    transfersToggle: {
        description: 'Transfers (deposits)'
    },
    tvg4PlaceHolders: {
        description: 'This toggle should be removed'
    },
    raceInfoFullPhones: {
        description: 'TVG4: Shows full phone information on account info'
    },
    tvg4V1: {
        description: 'TVG4: Enables/disables desktop version'
    },
    contentApi: {
        description: 'Consuming Content API instead of using CMS directly'
    },
    neulionScript: {
        description: 'Loading Neulion script asynchronously'
    },
    showRunnerReplays: {
        description: 'TVG4: Runner video replays'
    },
    rewardsInfo: {
        description: 'TVG4: Desktop Rewards Info'
    },
    wagerRewardsHistory: {
        description: 'TVG4: Desktop promotions - Wager Rewards History'
    },
    promoPageTab: {
        description: 'TVG4: Desktop promotions - Live Promos'
    },
    raceReplaysViewResults: {
        description: 'TVG4: Race replays on results page'
    },
    showAddToMyStable: {
        description: 'TVG4: add entities to My Stable'
    },
    userPreferences: {
        description: 'TVG4: Manage user preferences'
    },
    myTracks: {
        description: 'TVG4: Manage My Tracks'
    },
    popOutWindowVideo: {
        description: 'TVG4: Pop out new Window Video player'
    },
    showRaceDescriptionOption: {
        description: 'TVG4: Show race description on race program page'
    },
    raceReplaysOnResultsPage: {
        description: 'TVG4: Race replays on program page'
    },
    raceTimeformPredicts: {
        description: 'TVG4: Show Timeform Predicts on program page table'
    },
    helpTutorial: {
        description: 'Touch: Show tutorial videos'
    },
    showRaceChanges: {
        description: 'TVG4: Show race changes on race program page'
    },
    showBalanceBetSlip: {
        description: 'Show the balance of the client on the BetSlip window'
    },
    betSlipRepeatBet: {
        description: 'TVG4: Repeat bet on betslip'
    },
    openBetWindowsInGrid: {
        description: 'Open betSlip in grid mode'
    },
    newStreamToggle: {
        description: 'Touch: new live video stream format'
    },
    tutorialVideos: {
        description: 'Tutorials Videos'
    },
    currentBetsOnProgramPage: {
        description: 'TVG4: Show list of my bets placed for the current track and race selected in the program page.'
    },
    carryOverPools: {
        description: 'Carry Over Pools'
    },
    useNewFeaturedTracks: {
        description: 'Use the new featured tracks on home page'
    },
    tooltipHandicapping: {
        description: 'Show tooltip for handicapping'
    },
    additionalVideoPlayers: {
        description: 'TVG4: Ability to add additional video players'
    },
    useNewFullSchedule: {
        description: 'Use the new full schedule page layout and components'
    },
    storeStateOnLogin: {
        description: 'Store the user\'s chosen US State in the login process'
    },
    showPendingWithdrawals: {
        description: 'TVG4: Show pending withdrawals'
    },
    useTVG3handicappingStoreUrl: {
        description: 'Use handicapping store url get method from TVG3'
    },
    tvgPickProgramPageResults: {
        description: 'TVG Pick for Program Page and Results Page'
    },
    talentPicksViewRaceAndResultsButtons: {
        description: 'Display expert picks for today\'s program with three buttons: Create this Bet Ticket, View Race and Results'
    },
    passwordRecoveryPreflow: {
        description: 'Display the password recovery pre flow'
    },
    enableComingSoonHomepage: {
        description: 'Enable the coomming soon features slider on homepage'
    },
    enableComingSoonPage: {
        description: 'Enable coming soon page'
    },
    equibaseBet: {
        description: 'Enable equibase bet'
    },
    videoPopupFix: {
        description: "this toogle serve to test a video fix"
    },
    videoPlayFix: {
        description: "fix video playing the wrong video"
    },
    enableAccountSummaryWagersInline: {
        description: 'Enable account summary wager details'
    },
    videoTimeZoneCorrect: {
        description: 'Test video timezone'
    },
    enableTVGLiveButton: {
        description: 'Enables TVG Live button on the main menu bar'
    },
    passwordRecoveryMicroApp: {
        description: 'Replace the password recovery preflow by the password recovery micro app'
    },
    defaultDepositAmount: {
        description: 'Change the default amount of the deposits'
    },
    enableNextRacesFilter: {
        description: 'Manage filters for next races bar'
    },
    newProgramPageRaceSelector: {
        description: 'new behaviour for program page race selector'
    },
    programPageHeaderRevamp: {
        description: 'Enables the new layout for the program page header'
    },
    userSessionOnly: {
        description: 'For some cases, it replaces the current session request to a new one that does not retrieve the user profile'
    },
    raceReplaysHideResults: {
        description: 'hide and show results in race replays'
    },
    raceReplaysByDate: {
        description: 'toggle for race replay by date on handicapping menu'
    },
    pastResultsOnMainNavigation: {
        description: 'Changes main menu Race Replays to Past Results and Results opens Past Results'
    },
    geoComply: {
        description: 'use geoComply on login'
    },
    enableOptimizely: {
        description: 'enable optimizely on the site'
    },
    seoPageMetaInfo: {
        description: 'toggle the new page title and meta key'
    },
    handicappingWithRoutes: {
        description: 'toggle new handicapping with routes instead of hash'
    },
    specificCMSMessages: {
        description: 'toggle the cms endpoint to get specific cms keys'
    },
    promotionsWithRoutes: {
        description: 'toggle new handicapping with routes instead of hash'
    },
    addBlogLink: {
        description: 'add blog link in handicapping menu'
    },
    trackListPage: {
        description: 'add a track list page with all tracks and their details'
    },
    videoProviderRCN: {
        description: 'Switch to RCN video provider'
    },
    showLeftBar: {
        description: 'New left bar to navigate in races'
    },
    addCarryoverPoolsLink: {
        description: 'add Todays Carryover Pools link to race'
    },
    changeSSNTooltipMessagePosition: {
        description: 'Changes the position of the helper message in the SSN tooltip'
    },
    globalMtpRefreshSystem: {
        description: 'A system to control the MTP displayed in every place where it is needed'
    },
    showLeftNavFeatured: {
        description: 'Add template for Featured Races and services'
    },
    graphqlVolatileData: {
        description: 'Updates program page data from graphQL'
    },
    graphqlVolatileDataBetslip: {
        description: 'Updates bet slip data from graphQL'
    },
    newWagerEndpoint: {
        description: 'Uses the new wager endpoint on the wtx microservice'
    },
    leftBarLiveIcon: {
        description: 'Show live icon when race is off'
    },
    leftBarOnTvgVideo: {
        description: 'Show live video on tvg on left bar'
    },
    leftBarOnTvg2Video: {
        description: 'Show live video on tvg 2 on left bar'
    },
    addTabsLeftBar: {
        description: 'Add tabs at left races bar'
    },
    graphqlBetslipRunners: {
        description: 'Updates bet slip data from graphQL'
    },
    myStableRaceToday: {
        description: 'Show Race Today tab on My Stable'
    },
    showMoreFeatured: {
        description: 'showMoreFeatures'
    },
    showLeftNavAdditionalVideos: {
        description: 'Show more live streams'
    },
    showLeftNavFull: {
        description: 'Show nav full'
    },
    enableTooltip: {
        description: 'Enables tooltip.io script'
    },
    cancelBetWtx: {
        description: 'Cancels a bet using the wtx service'
    },
    showEquibasePastPerformanceOnProgramPage: {
        description: 'Shows the purchase PP on the tvg4 program page for usa tracks'
    },
    loginRequiredOnEquibaseTrackPastPerformanceButton: {
        description: 'Enables the login step on the purchase PP button'
    },
    showGrandSlamInfo: {
        description: 'Show info about the Grand Slam wager type'
    },
    signalProviderModal: {
        description: 'Opens a modal to update the signal provider'
    },
    asyncPlaceWagerHandler: {
        description: 'Handles async bet placing'
    },
    gkeAccountSummary: {
        description: 'Activates account summary via new gke UAS endpoint'
    },
    gkeMyBets: {
        description: 'Activates my bets via new gke WRO endpoint'
    },
    uarStatesList: {
        description: 'Get the list of states from uar micro service'
    },
    qaConsumingStagingGraph: {
        description: 'Consumes graph through staging to populate qa feeds'
    }
};

define("defaultFeatures", function(){});

vendors/angular/angular.min.js
/*
 AngularJS v1.5.7
 (c) 2010-2016 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(E){'use strict';function O(a){return function(){var b=arguments[0],d;d="["+(a?a+":":"")+b+"] http://errors.angularjs.org/1.5.7/"+(a?a+"/":"")+b;for(b=1;b<arguments.length;b++){d=d+(1==b?"?":"&")+"p"+(b-1)+"=";var c=encodeURIComponent,e;e=arguments[b];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;d+=c(e)}return Error(d)}}function oa(a){if(null==a||Wa(a))return!1;if(J(a)||F(a)||B&&a instanceof B)return!0;
var b="length"in Object(a)&&a.length;return S(b)&&(0<=b&&(b-1 in a||a instanceof Array)||"function"==typeof a.item)}function r(a,b,d){var c,e;if(a)if(z(a))for(c in a)"prototype"==c||"length"==c||"name"==c||a.hasOwnProperty&&!a.hasOwnProperty(c)||b.call(d,a[c],c,a);else if(J(a)||oa(a)){var f="object"!==typeof a;c=0;for(e=a.length;c<e;c++)(f||c in a)&&b.call(d,a[c],c,a)}else if(a.forEach&&a.forEach!==r)a.forEach(b,d,a);else if(sc(a))for(c in a)b.call(d,a[c],c,a);else if("function"===typeof a.hasOwnProperty)for(c in a)a.hasOwnProperty(c)&&
b.call(d,a[c],c,a);else for(c in a)sa.call(a,c)&&b.call(d,a[c],c,a);return a}function tc(a,b,d){for(var c=Object.keys(a).sort(),e=0;e<c.length;e++)b.call(d,a[c[e]],c[e]);return c}function uc(a){return function(b,d){a(d,b)}}function Zd(){return++pb}function Pb(a,b,d){for(var c=a.$$hashKey,e=0,f=b.length;e<f;++e){var g=b[e];if(H(g)||z(g))for(var h=Object.keys(g),k=0,l=h.length;k<l;k++){var m=h[k],n=g[m];d&&H(n)?ia(n)?a[m]=new Date(n.valueOf()):Xa(n)?a[m]=new RegExp(n):n.nodeName?a[m]=n.cloneNode(!0):
Qb(n)?a[m]=n.clone():(H(a[m])||(a[m]=J(n)?[]:{}),Pb(a[m],[n],!0)):a[m]=n}}c?a.$$hashKey=c:delete a.$$hashKey;return a}function R(a){return Pb(a,ta.call(arguments,1),!1)}function $d(a){return Pb(a,ta.call(arguments,1),!0)}function aa(a){return parseInt(a,10)}function Rb(a,b){return R(Object.create(a),b)}function A(){}function Ya(a){return a}function da(a){return function(){return a}}function vc(a){return z(a.toString)&&a.toString!==ka}function w(a){return"undefined"===typeof a}function x(a){return"undefined"!==
typeof a}function H(a){return null!==a&&"object"===typeof a}function sc(a){return null!==a&&"object"===typeof a&&!wc(a)}function F(a){return"string"===typeof a}function S(a){return"number"===typeof a}function ia(a){return"[object Date]"===ka.call(a)}function z(a){return"function"===typeof a}function Xa(a){return"[object RegExp]"===ka.call(a)}function Wa(a){return a&&a.window===a}function Za(a){return a&&a.$evalAsync&&a.$watch}function Ea(a){return"boolean"===typeof a}function ae(a){return a&&S(a.length)&&
be.test(ka.call(a))}function Qb(a){return!(!a||!(a.nodeName||a.prop&&a.attr&&a.find))}function ce(a){var b={};a=a.split(",");var d;for(d=0;d<a.length;d++)b[a[d]]=!0;return b}function ua(a){return M(a.nodeName||a[0]&&a[0].nodeName)}function $a(a,b){var d=a.indexOf(b);0<=d&&a.splice(d,1);return d}function Z(a,b){function d(a,b){var d=b.$$hashKey,e;if(J(a)){e=0;for(var f=a.length;e<f;e++)b.push(c(a[e]))}else if(sc(a))for(e in a)b[e]=c(a[e]);else if(a&&"function"===typeof a.hasOwnProperty)for(e in a)a.hasOwnProperty(e)&&
(b[e]=c(a[e]));else for(e in a)sa.call(a,e)&&(b[e]=c(a[e]));d?b.$$hashKey=d:delete b.$$hashKey;return b}function c(a){if(!H(a))return a;var b=f.indexOf(a);if(-1!==b)return g[b];if(Wa(a)||Za(a))throw za("cpws");var b=!1,c=e(a);void 0===c&&(c=J(a)?[]:Object.create(wc(a)),b=!0);f.push(a);g.push(c);return b?d(a,c):c}function e(a){switch(ka.call(a)){case "[object Int8Array]":case "[object Int16Array]":case "[object Int32Array]":case "[object Float32Array]":case "[object Float64Array]":case "[object Uint8Array]":case "[object Uint8ClampedArray]":case "[object Uint16Array]":case "[object Uint32Array]":return new a.constructor(c(a.buffer));
case "[object ArrayBuffer]":if(!a.slice){var b=new ArrayBuffer(a.byteLength);(new Uint8Array(b)).set(new Uint8Array(a));return b}return a.slice(0);case "[object Boolean]":case "[object Number]":case "[object String]":case "[object Date]":return new a.constructor(a.valueOf());case "[object RegExp]":return b=new RegExp(a.source,a.toString().match(/[^\/]*$/)[0]),b.lastIndex=a.lastIndex,b;case "[object Blob]":return new a.constructor([a],{type:a.type})}if(z(a.cloneNode))return a.cloneNode(!0)}var f=[],
g=[];if(b){if(ae(b)||"[object ArrayBuffer]"===ka.call(b))throw za("cpta");if(a===b)throw za("cpi");J(b)?b.length=0:r(b,function(a,d){"$$hashKey"!==d&&delete b[d]});f.push(a);g.push(b);return d(a,b)}return c(a)}function na(a,b){if(a===b)return!0;if(null===a||null===b)return!1;if(a!==a&&b!==b)return!0;var d=typeof a,c;if(d==typeof b&&"object"==d)if(J(a)){if(!J(b))return!1;if((d=a.length)==b.length){for(c=0;c<d;c++)if(!na(a[c],b[c]))return!1;return!0}}else{if(ia(a))return ia(b)?na(a.getTime(),b.getTime()):
!1;if(Xa(a))return Xa(b)?a.toString()==b.toString():!1;if(Za(a)||Za(b)||Wa(a)||Wa(b)||J(b)||ia(b)||Xa(b))return!1;d=T();for(c in a)if("$"!==c.charAt(0)&&!z(a[c])){if(!na(a[c],b[c]))return!1;d[c]=!0}for(c in b)if(!(c in d)&&"$"!==c.charAt(0)&&x(b[c])&&!z(b[c]))return!1;return!0}return!1}function ab(a,b,d){return a.concat(ta.call(b,d))}function bb(a,b){var d=2<arguments.length?ta.call(arguments,2):[];return!z(b)||b instanceof RegExp?b:d.length?function(){return arguments.length?b.apply(a,ab(d,arguments,
0)):b.apply(a,d)}:function(){return arguments.length?b.apply(a,arguments):b.call(a)}}function de(a,b){var d=b;"string"===typeof a&&"$"===a.charAt(0)&&"$"===a.charAt(1)?d=void 0:Wa(b)?d="$WINDOW":b&&E.document===b?d="$DOCUMENT":Za(b)&&(d="$SCOPE");return d}function cb(a,b){if(!w(a))return S(b)||(b=b?2:null),JSON.stringify(a,de,b)}function xc(a){return F(a)?JSON.parse(a):a}function yc(a,b){a=a.replace(ee,"");var d=Date.parse("Jan 01, 1970 00:00:00 "+a)/6E4;return isNaN(d)?b:d}function Sb(a,b,d){d=d?
-1:1;var c=a.getTimezoneOffset();b=yc(b,c);d*=b-c;a=new Date(a.getTime());a.setMinutes(a.getMinutes()+d);return a}function va(a){a=B(a).clone();try{a.empty()}catch(b){}var d=B("<div>").append(a).html();try{return a[0].nodeType===Na?M(d):d.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+M(b)})}catch(c){return M(d)}}function zc(a){try{return decodeURIComponent(a)}catch(b){}}function Ac(a){var b={};r((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,"%20"),c=a.indexOf("="),
-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=zc(e),x(e)&&(f=x(f)?zc(f):!0,sa.call(b,e)?J(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function Tb(a){var b=[];r(a,function(a,c){J(a)?r(a,function(a){b.push(ja(c,!0)+(!0===a?"":"="+ja(a,!0)))}):b.push(ja(c,!0)+(!0===a?"":"="+ja(a,!0)))});return b.length?b.join("&"):""}function qb(a){return ja(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ja(a,b){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,
":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,b?"%20":"+")}function fe(a,b){var d,c,e=Oa.length;for(c=0;c<e;++c)if(d=Oa[c]+b,F(d=a.getAttribute(d)))return d;return null}function ge(a,b){var d,c,e={};r(Oa,function(b){b+="app";!d&&a.hasAttribute&&a.hasAttribute(b)&&(d=a,c=a.getAttribute(b))});r(Oa,function(b){b+="app";var e;!d&&(e=a.querySelector("["+b.replace(":","\\:")+"]"))&&(d=e,c=e.getAttribute(b))});d&&(e.strictDi=null!==fe(d,"strict-di"),b(d,c?[c]:[],e))}function Bc(a,
b,d){H(d)||(d={});d=R({strictDi:!1},d);var c=function(){a=B(a);if(a.injector()){var c=a[0]===E.document?"document":va(a);throw za("btstrpd",c.replace(/</,"&lt;").replace(/>/,"&gt;"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);b.unshift("ng");c=db(b,d.strictDi);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,d,c){a.$apply(function(){b.data("$injector",c);d(b)(a)})}]);
return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;E&&e.test(E.name)&&(d.debugInfoEnabled=!0,E.name=E.name.replace(e,""));if(E&&!f.test(E.name))return c();E.name=E.name.replace(f,"");ea.resumeBootstrap=function(a){r(a,function(a){b.push(a)});return c()};z(ea.resumeDeferredBootstrap)&&ea.resumeDeferredBootstrap()}function he(){E.name="NG_ENABLE_DEBUG_INFO!"+E.name;E.location.reload()}function ie(a){a=ea.element(a).injector();if(!a)throw za("test");return a.get("$$testability")}function Cc(a,
b){b=b||"_";return a.replace(je,function(a,c){return(c?b:"")+a.toLowerCase()})}function ke(){var a;if(!Dc){var b=rb();(pa=w(b)?E.jQuery:b?E[b]:void 0)&&pa.fn.on?(B=pa,R(pa.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),a=pa.cleanData,pa.cleanData=function(b){for(var c,e=0,f;null!=(f=b[e]);e++)(c=pa._data(f,"events"))&&c.$destroy&&pa(f).triggerHandler("$destroy");a(b)}):B=U;ea.element=B;Dc=!0}}function sb(a,b,d){if(!a)throw za("areq",
b||"?",d||"required");return a}function Qa(a,b,d){d&&J(a)&&(a=a[a.length-1]);sb(z(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Ra(a,b){if("hasOwnProperty"===a)throw za("badname",b);}function Ec(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g<f;g++)c=b[g],a&&(a=(e=a)[c]);return!d&&z(a)?bb(e,a):a}function tb(a){for(var b=a[0],d=a[a.length-1],c,e=1;b!==d&&(b=b.nextSibling);e++)if(c||a[e]!==b)c||(c=B(ta.call(a,0,e))),
c.push(b);return c||a}function T(){return Object.create(null)}function le(a){function b(a,b,c){return a[b]||(a[b]=c())}var d=O("$injector"),c=O("ng");a=b(a,"angular",Object);a.$$minErr=a.$$minErr||O;return b(a,"module",function(){var a={};return function(f,g,h){if("hasOwnProperty"===f)throw c("badname","module");g&&a.hasOwnProperty(f)&&(a[f]=null);return b(a,f,function(){function a(b,d,e,f){f||(f=c);return function(){f[e||"push"]([b,d,arguments]);return V}}function b(a,d){return function(b,e){e&&
z(e)&&(e.$$moduleName=f);c.push([a,d,arguments]);return V}}if(!g)throw d("nomod",f);var c=[],e=[],p=[],s=a("$injector","invoke","push",e),V={_invokeQueue:c,_configBlocks:e,_runBlocks:p,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator"),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider",
"register"),directive:b("$compileProvider","directive"),component:b("$compileProvider","component"),config:s,run:function(a){p.push(a);return this}};h&&s(h);return V})}})}function ga(a,b){if(J(a)){b=b||[];for(var d=0,c=a.length;d<c;d++)b[d]=a[d]}else if(H(a))for(d in b=b||{},a)if("$"!==d.charAt(0)||"$"!==d.charAt(1))b[d]=a[d];return b||a}function me(a){R(a,{bootstrap:Bc,copy:Z,extend:R,merge:$d,equals:na,element:B,forEach:r,injector:db,noop:A,bind:bb,toJson:cb,fromJson:xc,identity:Ya,isUndefined:w,
isDefined:x,isString:F,isFunction:z,isObject:H,isNumber:S,isElement:Qb,isArray:J,version:ne,isDate:ia,lowercase:M,uppercase:ub,callbacks:{counter:0},getTestability:ie,$$minErr:O,$$csp:Fa,reloadWithDebugInfo:he});Ub=le(E);Ub("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:oe});a.provider("$compile",Fc).directive({a:pe,input:Gc,textarea:Gc,form:qe,script:re,select:se,style:te,option:ue,ngBind:ve,ngBindHtml:we,ngBindTemplate:xe,ngClass:ye,ngClassEven:ze,ngClassOdd:Ae,ngCloak:Be,ngController:Ce,
ngForm:De,ngHide:Ee,ngIf:Fe,ngInclude:Ge,ngInit:He,ngNonBindable:Ie,ngPluralize:Je,ngRepeat:Ke,ngShow:Le,ngStyle:Me,ngSwitch:Ne,ngSwitchWhen:Oe,ngSwitchDefault:Pe,ngOptions:Qe,ngTransclude:Re,ngModel:Se,ngList:Te,ngChange:Ue,pattern:Hc,ngPattern:Hc,required:Ic,ngRequired:Ic,minlength:Jc,ngMinlength:Jc,maxlength:Kc,ngMaxlength:Kc,ngValue:Ve,ngModelOptions:We}).directive({ngInclude:Xe}).directive(vb).directive(Lc);a.provider({$anchorScroll:Ye,$animate:Ze,$animateCss:$e,$$animateJs:af,$$animateQueue:bf,
$$AnimateRunner:cf,$$animateAsyncRun:df,$browser:ef,$cacheFactory:ff,$controller:gf,$document:hf,$exceptionHandler:jf,$filter:Mc,$$forceReflow:kf,$interpolate:lf,$interval:mf,$http:nf,$httpParamSerializer:of,$httpParamSerializerJQLike:pf,$httpBackend:qf,$xhrFactory:rf,$location:sf,$log:tf,$parse:uf,$rootScope:vf,$q:wf,$$q:xf,$sce:yf,$sceDelegate:zf,$sniffer:Af,$templateCache:Bf,$templateRequest:Cf,$$testability:Df,$timeout:Ef,$window:Ff,$$rAF:Gf,$$jqLite:Hf,$$HashMap:If,$$cookieReader:Jf})}])}function eb(a){return a.replace(Kf,
function(a,d,c,e){return e?c.toUpperCase():c}).replace(Lf,"Moz$1")}function Nc(a){a=a.nodeType;return 1===a||!a||9===a}function Oc(a,b){var d,c,e=b.createDocumentFragment(),f=[];if(Vb.test(a)){d=d||e.appendChild(b.createElement("div"));c=(Mf.exec(a)||["",""])[1].toLowerCase();c=ha[c]||ha._default;d.innerHTML=c[1]+a.replace(Nf,"<$1></$2>")+c[2];for(c=c[0];c--;)d=d.lastChild;f=ab(f,d.childNodes);d=e.firstChild;d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";r(f,function(a){e.appendChild(a)});
return e}function Pc(a,b){var d=a.parentNode;d&&d.replaceChild(b,a);b.appendChild(a)}function U(a){if(a instanceof U)return a;var b;F(a)&&(a=W(a),b=!0);if(!(this instanceof U)){if(b&&"<"!=a.charAt(0))throw Wb("nosel");return new U(a)}if(b){b=E.document;var d;a=(d=Of.exec(a))?[b.createElement(d[1])]:(d=Oc(a,b))?d.childNodes:[]}Qc(this,a)}function Xb(a){return a.cloneNode(!0)}function wb(a,b){b||fb(a);if(a.querySelectorAll)for(var d=a.querySelectorAll("*"),c=0,e=d.length;c<e;c++)fb(d[c])}function Rc(a,
b,d,c){if(x(c))throw Wb("offargs");var e=(c=xb(a))&&c.events,f=c&&c.handle;if(f)if(b){var g=function(b){var c=e[b];x(d)&&$a(c||[],d);x(d)&&c&&0<c.length||(a.removeEventListener(b,f,!1),delete e[b])};r(b.split(" "),function(a){g(a);yb[a]&&g(yb[a])})}else for(b in e)"$destroy"!==b&&a.removeEventListener(b,f,!1),delete e[b]}function fb(a,b){var d=a.ng339,c=d&&gb[d];c&&(b?delete c.data[b]:(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),Rc(a)),delete gb[d],a.ng339=void 0))}function xb(a,b){var d=
a.ng339,d=d&&gb[d];b&&!d&&(a.ng339=d=++Pf,d=gb[d]={events:{},data:{},handle:void 0});return d}function Yb(a,b,d){if(Nc(a)){var c=x(d),e=!c&&b&&!H(b),f=!b;a=(a=xb(a,!e))&&a.data;if(c)a[b]=d;else{if(f)return a;if(e)return a&&a[b];R(a,b)}}}function zb(a,b){return a.getAttribute?-1<(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+b+" "):!1}function Ab(a,b){b&&a.setAttribute&&r(b.split(" "),function(b){a.setAttribute("class",W((" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g,
" ").replace(" "+W(b)+" "," ")))})}function Bb(a,b){if(b&&a.setAttribute){var d=(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");r(b.split(" "),function(a){a=W(a);-1===d.indexOf(" "+a+" ")&&(d+=a+" ")});a.setAttribute("class",W(d))}}function Qc(a,b){if(b)if(b.nodeType)a[a.length++]=b;else{var d=b.length;if("number"===typeof d&&b.window!==b){if(d)for(var c=0;c<d;c++)a[a.length++]=b[c]}else a[a.length++]=b}}function Sc(a,b){return Cb(a,"$"+(b||"ngController")+"Controller")}function Cb(a,
b,d){9==a.nodeType&&(a=a.documentElement);for(b=J(b)?b:[b];a;){for(var c=0,e=b.length;c<e;c++)if(x(d=B.data(a,b[c])))return d;a=a.parentNode||11===a.nodeType&&a.host}}function Tc(a){for(wb(a,!0);a.firstChild;)a.removeChild(a.firstChild)}function Db(a,b){b||wb(a);var d=a.parentNode;d&&d.removeChild(a)}function Qf(a,b){b=b||E;if("complete"===b.document.readyState)b.setTimeout(a);else B(b).on("load",a)}function Uc(a,b){var d=Eb[b.toLowerCase()];return d&&Vc[ua(a)]&&d}function Rf(a,b){var d=function(c,
d){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=b[d||c.type],g=f?f.length:0;if(g){if(w(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};var k=f.specialHandlerWrapper||Sf;1<g&&(f=ga(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||k(a,c,f[l])}};d.elem=
a;return d}function Sf(a,b,d){d.call(a,b)}function Tf(a,b,d){var c=b.relatedTarget;c&&(c===a||Uf.call(a,c))||d.call(a,b)}function Hf(){this.$get=function(){return R(U,{hasClass:function(a,b){a.attr&&(a=a[0]);return zb(a,b)},addClass:function(a,b){a.attr&&(a=a[0]);return Bb(a,b)},removeClass:function(a,b){a.attr&&(a=a[0]);return Ab(a,b)}})}}function Ga(a,b){var d=a&&a.$$hashKey;if(d)return"function"===typeof d&&(d=a.$$hashKey()),d;d=typeof a;return d="function"==d||"object"==d&&null!==a?a.$$hashKey=
d+":"+(b||Zd)():d+":"+a}function Sa(a,b){if(b){var d=0;this.nextUid=function(){return++d}}r(a,this.put,this)}function Wc(a){a=(Function.prototype.toString.call(a)+" ").replace(Vf,"");return a.match(Wf)||a.match(Xf)}function Yf(a){return(a=Wc(a))?"function("+(a[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function db(a,b){function d(a){return function(b,c){if(H(b))r(b,uc(a));else return a(b,c)}}function c(a,b){Ra(a,"service");if(z(b)||J(b))b=p.instantiate(b);if(!b.$get)throw Ha("pget",a);return n[a+"Provider"]=
b}function e(a,b){return function(){var c=I.invoke(b,this);if(w(c))throw Ha("undef",a);return c}}function f(a,b,d){return c(a,{$get:!1!==d?e(a,b):b})}function g(a){sb(w(a)||J(a),"modulesToLoad","not an array");var b=[],c;r(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=p.get(e[0]);f[e[1]].apply(f,e[2])}}if(!m.get(a)){m.put(a,!0);try{F(a)?(c=Ub(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(p.invoke(a)):J(a)?b.push(p.invoke(a)):
Qa(a,"module")}catch(e){throw J(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ha("modulerr",a,e.stack||e.message||e);}}});return b}function h(a,c){function d(b,e){if(a.hasOwnProperty(b)){if(a[b]===k)throw Ha("cdep",b+" <- "+l.join(" <- "));return a[b]}try{return l.unshift(b),a[b]=k,a[b]=c(b,e)}catch(f){throw a[b]===k&&delete a[b],f;}finally{l.shift()}}function e(a,c,f){var g=[];a=db.$$annotate(a,b,f);for(var h=0,k=a.length;h<k;h++){var l=a[h];
if("string"!==typeof l)throw Ha("itkn",l);g.push(c&&c.hasOwnProperty(l)?c[l]:d(l,f))}return g}return{invoke:function(a,b,c,d){"string"===typeof c&&(d=c,c=null);c=e(a,c,d);J(a)&&(a=a[a.length-1]);d=11>=Ba?!1:"function"===typeof a&&/^(?:class\s|constructor\()/.test(Function.prototype.toString.call(a)+" ");return d?(c.unshift(null),new (Function.prototype.bind.apply(a,c))):a.apply(b,c)},instantiate:function(a,b,c){var d=J(a)?a[a.length-1]:a;a=e(a,b,c);a.unshift(null);return new (Function.prototype.bind.apply(d,
a))},get:d,annotate:db.$$annotate,has:function(b){return n.hasOwnProperty(b+"Provider")||a.hasOwnProperty(b)}}}b=!0===b;var k={},l=[],m=new Sa([],!0),n={$provide:{provider:d(c),factory:d(f),service:d(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:d(function(a,b){return f(a,da(b),!1)}),constant:d(function(a,b){Ra(a,"constant");n[a]=b;s[a]=b}),decorator:function(a,b){var c=p.get(a+"Provider"),d=c.$get;c.$get=function(){var a=I.invoke(d,c);return I.invoke(b,null,
{$delegate:a})}}}},p=n.$injector=h(n,function(a,b){ea.isString(b)&&l.push(b);throw Ha("unpr",l.join(" <- "));}),s={},V=h(s,function(a,b){var c=p.get(a+"Provider",b);return I.invoke(c.$get,c,void 0,a)}),I=V;n.$injectorProvider={$get:da(V)};var q=g(a),I=V.get("$injector");I.strictDi=b;r(q,function(a){a&&I.invoke(a)});return I}function Ye(){var a=!0;this.disableAutoScrolling=function(){a=!1};this.$get=["$window","$location","$rootScope",function(b,d,c){function e(a){var b=null;Array.prototype.some.call(a,
function(a){if("a"===ua(a))return b=a,!0});return b}function f(a){if(a){a.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():Qb(c)?(c=c[0],c="fixed"!==b.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):S(c)||(c=0);c&&(a=a.getBoundingClientRect().top,b.scrollBy(0,a-c))}else b.scrollTo(0,0)}function g(a){a=F(a)?a:d.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=b.document;a&&c.$watch(function(){return d.hash()},function(a,b){a===
b&&""===a||Qf(function(){c.$evalAsync(g)})});return g}]}function hb(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;J(a)&&(a=a.join(" "));J(b)&&(b=b.join(" "));return a+" "+b}function Zf(a){F(a)&&(a=a.split(" "));var b=T();r(a,function(a){a.length&&(b[a]=!0)});return b}function Ia(a){return H(a)?a:{}}function $f(a,b,d,c){function e(a){try{a.apply(null,ta.call(arguments,1))}finally{if(V--,0===V)for(;I.length;)try{I.pop()()}catch(b){d.error(b)}}}function f(){y=null;g();h()}function g(){q=P();
q=w(q)?null:q;na(q,D)&&(q=D);D=q}function h(){if(v!==k.url()||K!==q)v=k.url(),K=q,r(L,function(a){a(k.url(),q)})}var k=this,l=a.location,m=a.history,n=a.setTimeout,p=a.clearTimeout,s={};k.isMock=!1;var V=0,I=[];k.$$completeOutstandingRequest=e;k.$$incOutstandingRequestCount=function(){V++};k.notifyWhenNoOutstandingRequests=function(a){0===V?a():I.push(a)};var q,K,v=l.href,u=b.find("base"),y=null,P=c.history?function(){try{return m.state}catch(a){}}:A;g();K=q;k.url=function(b,d,e){w(e)&&(e=null);l!==
a.location&&(l=a.location);m!==a.history&&(m=a.history);if(b){var f=K===e;if(v===b&&(!c.history||f))return k;var h=v&&Ja(v)===Ja(b);v=b;K=e;!c.history||h&&f?(h||(y=b),d?l.replace(b):h?(d=l,e=b.indexOf("#"),e=-1===e?"":b.substr(e),d.hash=e):l.href=b,l.href!==b&&(y=b)):(m[d?"replaceState":"pushState"](e,"",b),g(),K=q);y&&(y=b);return k}return y||l.href.replace(/%27/g,"'")};k.state=function(){return q};var L=[],C=!1,D=null;k.onUrlChange=function(b){if(!C){if(c.history)B(a).on("popstate",f);B(a).on("hashchange",
f);C=!0}L.push(b);return b};k.$$applicationDestroyed=function(){B(a).off("hashchange popstate",f)};k.$$checkUrlChange=h;k.baseHref=function(){var a=u.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};k.defer=function(a,b){var c;V++;c=n(function(){delete s[c];e(a)},b||0);s[c]=!0;return c};k.defer.cancel=function(a){return s[a]?(delete s[a],p(a),e(A),!0):!1}}function ef(){this.$get=["$window","$log","$sniffer","$document",function(a,b,d,c){return new $f(a,c,b,d)}]}function ff(){this.$get=
function(){function a(a,c){function e(a){a!=n&&(p?p==a&&(p=a.n):p=a,f(a.n,a.p),f(a,n),n=a,n.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(a in b)throw O("$cacheFactory")("iid",a);var g=0,h=R({},c,{id:a}),k=T(),l=c&&c.capacity||Number.MAX_VALUE,m=T(),n=null,p=null;return b[a]={put:function(a,b){if(!w(b)){if(l<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}a in k||g++;k[a]=b;g>l&&this.remove(p.key);return b}},get:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;e(b)}return k[a]},
remove:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;b==n&&(n=b.p);b==p&&(p=b.n);f(b.n,b.p);delete m[a]}a in k&&(delete k[a],g--)},removeAll:function(){k=T();g=0;m=T();n=p=null},destroy:function(){m=h=k=null;delete b[a]},info:function(){return R({},h,{size:g})}}}var b={};a.info=function(){var a={};r(b,function(b,e){a[e]=b.info()});return a};a.get=function(a){return b[a]};return a}}function Bf(){this.$get=["$cacheFactory",function(a){return a("templates")}]}function Fc(a,b){function d(a,
b,c){var d=/^\s*([@&<]|=(\*?))(\??)\s*(\w*)\s*$/,e=T();r(a,function(a,f){if(a in n)e[f]=n[a];else{var g=a.match(d);if(!g)throw fa("iscp",b,f,a,c?"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f};g[4]&&(n[a]=e[f])}});return e}function c(a){var b=a.charAt(0);if(!b||b!==M(b))throw fa("baddir",a);if(a!==a.trim())throw fa("baddir",a);}function e(a){var b=a.require||a.controller&&a.name;!J(b)&&H(b)&&r(b,function(a,
c){var d=a.match(l);a.substring(d[0].length)||(b[c]=d[0]+c)});return b}var f={},g=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,h=/(([\w\-]+)(?:\:([^;]+))?;?)/,k=ce("ngSrc,ngSrcset,src,srcset"),l=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,m=/^(on[a-z]+|formaction)$/,n=T();this.directive=function I(b,d){Ra(b,"directive");F(b)?(c(b),sb(d,"directiveFactory"),f.hasOwnProperty(b)||(f[b]=[],a.factory(b+"Directive",["$injector","$exceptionHandler",function(a,c){var d=[];r(f[b],function(f,g){try{var h=a.invoke(f);z(h)?h={compile:da(h)}:
!h.compile&&h.link&&(h.compile=da(h.link));h.priority=h.priority||0;h.index=g;h.name=h.name||b;h.require=e(h);h.restrict=h.restrict||"EA";h.$$moduleName=f.$$moduleName;d.push(h)}catch(k){c(k)}});return d}])),f[b].push(d)):r(b,uc(I));return this};this.component=function(a,b){function c(a){function e(b){return z(b)||J(b)?function(c,d){return a.invoke(b,this,{$element:c,$attrs:d})}:b}var f=b.template||b.templateUrl?b.template:"",g={controller:d,controllerAs:Xc(b.controller)||b.controllerAs||"$ctrl",
template:e(f),templateUrl:e(b.templateUrl),transclude:b.transclude,scope:{},bindToController:b.bindings||{},restrict:"E",require:b.require};r(b,function(a,b){"$"===b.charAt(0)&&(g[b]=a)});return g}var d=b.controller||function(){};r(b,function(a,b){"$"===b.charAt(0)&&(c[b]=a,z(d)&&(d[b]=a))});c.$inject=["$injector"];return this.directive(a,c)};this.aHrefSanitizationWhitelist=function(a){return x(a)?(b.aHrefSanitizationWhitelist(a),this):b.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=
function(a){return x(a)?(b.imgSrcSanitizationWhitelist(a),this):b.imgSrcSanitizationWhitelist()};var p=!0;this.debugInfoEnabled=function(a){return x(a)?(p=a,this):p};var s=10;this.onChangesTtl=function(a){return arguments.length?(s=a,this):s};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$sce","$animate","$$sanitizeUri",function(a,b,c,e,n,y,P,L,C,D){function G(){try{if(!--oa)throw Z=void 0,fa("infchng",s);P.$apply(function(){for(var a=
[],b=0,c=Z.length;b<c;++b)try{Z[b]()}catch(d){a.push(d)}Z=void 0;if(a.length)throw a;})}finally{oa++}}function Aa(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a}function Q(a,b,c){la.innerHTML="<span "+b+">";b=la.firstChild.attributes;var d=b[0];b.removeNamedItem(d.name);d.value=c;a.attributes.setNamedItem(d)}function N(a,b){try{a.addClass(b)}catch(c){}}function ba(a,b,c,d,e){a instanceof B||(a=B(a));for(var f=/\S+/,g=0,h=a.length;g<
h;g++){var k=a[g];k.nodeType===Na&&k.nodeValue.match(f)&&Pc(k,a[g]=E.document.createElement("span"))}var l=t(a,b,a,c,d,e);ba.$$addScopeClass(a);var n=null;return function(b,c,d){sb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var f=d.parentBoundTranscludeFn,g=d.transcludeControllers;d=d.futureParentElement;f&&f.$$boundTransclude&&(f=f.$$boundTransclude);n||(n=(d=d&&d[0])?"foreignobject"!==ua(d)&&ka.call(d).match(/SVG/)?"svg":"html":"html");d="html"!==n?B(ca(n,B("<div>").append(a).html())):
c?Pa.clone.call(a):a;if(g)for(var h in g)d.data("$"+h+"Controller",g[h].instance);ba.$$addScopeInfo(d,b);c&&c(d,b);l&&l(b,d,d,f);return d}}function t(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,n,m,v,q;if(p)for(q=Array(c.length),n=0;n<h.length;n+=3)f=h[n],q[f]=c[f];else q=c;n=0;for(m=h.length;n<m;)k=q[h[n++]],c=h[n++],f=h[n++],c?(c.scope?(l=a.$new(),ba.$$addScopeInfo(B(k),l)):l=a,v=c.transcludeOnThisElement?wa(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?wa(a,b):null,c(f,l,k,d,v)):f&&f(a,
k.childNodes,void 0,e)}for(var h=[],k,l,n,m,p,v=0;v<a.length;v++){k=new Aa;l=$b(a[v],[],k,0===v?d:void 0,e);(f=l.length?Ta(l,a[v],k,b,c,null,[],[],f):null)&&f.scope&&ba.$$addScopeClass(k.$$element);k=f&&f.terminal||!(n=a[v].childNodes)||!n.length?null:t(n,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(v,f,k),m=!0,p=p||f;f=null}return m?g:null}function wa(a,b,c){function d(e,f,g,h,k){e||(e=a.$new(!1,k),e.$$transcluded=!0);return b(e,f,{parentBoundTranscludeFn:c,
transcludeControllers:g,futureParentElement:h})}var e=d.$$slots=T(),f;for(f in b.$$slots)e[f]=b.$$slots[f]?wa(a,b.$$slots[f],c):null;return d}function $b(a,b,c,d,e){var f=c.$attr,k;switch(a.nodeType){case 1:Da(b,xa(ua(a)),"E",d,e);for(var l,n,m,p=a.attributes,v=0,q=p&&p.length;v<q;v++){var s=!1,L=!1;l=p[v];k=l.name;n=W(l.value);l=xa(k);if(m=ya.test(l))k=k.replace(Yc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});(l=l.match(za))&&S(l[1])&&(s=k,L=k.substr(0,k.length-5)+"end",k=
k.substr(0,k.length-6));l=xa(k.toLowerCase());f[l]=k;if(m||!c.hasOwnProperty(l))c[l]=n,Uc(a,l)&&(c[l]=!0);ia(a,b,n,l,m);Da(b,l,"A",d,e,s,L)}a=a.className;H(a)&&(a=a.animVal);if(F(a)&&""!==a)for(;k=h.exec(a);)l=xa(k[2]),Da(b,l,"C",d,e)&&(c[l]=W(k[3])),a=a.substr(k.index+k[0].length);break;case Na:if(11===Ba)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===Na;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);aa(b,a.nodeValue);break;case 8:try{if(k=g.exec(a.nodeValue))l=
xa(k[1]),Da(b,l,"M",d,e)&&(c[l]=W(k[2]))}catch(C){}}b.sort(Y);return b}function Zc(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw fa("uterdir",b,c);1==a.nodeType&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return B(d)}function O(a,b,c){return function(d,e,f,g,h){e=Zc(e[0],b,c);return a(d,e,f,g,h)}}function ac(a,b,c,d,e,f){var g;return a?ba(b,c,d,e,f):function(){g||(g=ba(b,c,d,e,f),b=c=f=null);return g.apply(this,
arguments)}}function Ta(a,b,d,e,f,g,h,k,l){function n(a,b,c,d){if(a){c&&(a=O(a,c,d));a.require=u.require;a.directiveName=G;if(s===u||u.$$isolateScope)a=ga(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=O(b,c,d));b.require=u.require;b.directiveName=G;if(s===u||u.$$isolateScope)b=ga(b,{isolateScope:!0});k.push(b)}}function m(a,e,f,g,l){function n(a,b,c,d){var e;Za(a)||(d=c,c=b,b=a,a=void 0);y&&(e=N);c||(c=y?G.parent():G);if(d){var f=l.$$slots[d];if(f)return f(a,b,e,c,t);if(w(f))throw fa("noslot",d,va(G));
}else return l(a,b,e,c,t)}var p,C,u,D,I,N,Q,G;b===f?(g=d,G=d.$$element):(G=B(f),g=new Aa(G,d));I=e;s?D=e.$new(!0):v&&(I=e.$parent);l&&(Q=n,Q.$$boundTransclude=l,Q.isSlotFilled=function(a){return!!l.$$slots[a]});q&&(N=ag(G,g,Q,q,D,e,s));s&&(ba.$$addScopeInfo(G,D,!0,!(L&&(L===s||L===s.$$originalDirective))),ba.$$addScopeClass(G,!0),D.$$isolateBindings=s.$$isolateBindings,C=ha(e,g,D,D.$$isolateBindings,s),C.removeWatches&&D.$on("$destroy",C.removeWatches));for(p in N){C=q[p];u=N[p];var Zb=C.$$bindings.bindToController;
u.bindingInfo=u.identifier&&Zb?ha(I,g,u.instance,Zb,C):{};var P=u();P!==u.instance&&(u.instance=P,G.data("$"+C.name+"Controller",P),u.bindingInfo.removeWatches&&u.bindingInfo.removeWatches(),u.bindingInfo=ha(I,g,u.instance,Zb,C))}r(q,function(a,b){var c=a.require;a.bindToController&&!J(c)&&H(c)&&R(N[b].instance,ib(b,c,G,N))});r(N,function(a){var b=a.instance;if(z(b.$onChanges))try{b.$onChanges(a.bindingInfo.initialChanges)}catch(d){c(d)}if(z(b.$onInit))try{b.$onInit()}catch(e){c(e)}z(b.$onDestroy)&&
I.$on("$destroy",function(){b.$onDestroy()})});p=0;for(C=h.length;p<C;p++)u=h[p],ja(u,u.isolateScope?D:e,G,g,u.require&&ib(u.directiveName,u.require,G,N),Q);var t=e;s&&(s.template||null===s.templateUrl)&&(t=D);a&&a(t,f.childNodes,void 0,l);for(p=k.length-1;0<=p;p--)u=k[p],ja(u,u.isolateScope?D:e,G,g,u.require&&ib(u.directiveName,u.require,G,N),Q);r(N,function(a){a=a.instance;z(a.$postLink)&&a.$postLink()})}l=l||{};for(var p=-Number.MAX_VALUE,v=l.newScopeDirective,q=l.controllerDirectives,s=l.newIsolateScopeDirective,
L=l.templateDirective,C=l.nonTlbTranscludeDirective,D=!1,I=!1,y=l.hasElementTranscludeDirective,N=d.$$element=B(b),u,G,Q,P=e,t,Ca=!1,wa=!1,x,A=0,E=a.length;A<E;A++){u=a[A];var F=u.$$start,Ta=u.$$end;F&&(N=Zc(b,F,Ta));Q=void 0;if(p>u.priority)break;if(x=u.scope)u.templateUrl||(H(x)?(X("new/isolated scope",s||v,u,N),s=u):X("new/isolated scope",s,u,N)),v=v||u;G=u.name;if(!Ca&&(u.replace&&(u.templateUrl||u.template)||u.transclude&&!u.$$tlb)){for(x=A+1;Ca=a[x++];)if(Ca.transclude&&!Ca.$$tlb||Ca.replace&&
(Ca.templateUrl||Ca.template)){wa=!0;break}Ca=!0}!u.templateUrl&&u.controller&&(x=u.controller,q=q||T(),X("'"+G+"' controller",q[G],u,N),q[G]=u);if(x=u.transclude)if(D=!0,u.$$tlb||(X("transclusion",C,u,N),C=u),"element"==x)y=!0,p=u.priority,Q=N,N=d.$$element=B(ba.$$createComment(G,d[G])),b=N[0],da(f,ta.call(Q,0),b),Q[0].$$parentNode=Q[0].parentNode,P=ac(wa,Q,e,p,g&&g.name,{nonTlbTranscludeDirective:C});else{var M=T();Q=B(Xb(b)).contents();if(H(x)){Q=[];var S=T(),Da=T();r(x,function(a,b){var c="?"===
a.charAt(0);a=c?a.substring(1):a;S[a]=b;M[b]=null;Da[b]=c});r(N.contents(),function(a){var b=S[xa(ua(a))];b?(Da[b]=!0,M[b]=M[b]||[],M[b].push(a)):Q.push(a)});r(Da,function(a,b){if(!a)throw fa("reqslot",b);});for(var Y in M)M[Y]&&(M[Y]=ac(wa,M[Y],e))}N.empty();P=ac(wa,Q,e,void 0,void 0,{needsNewScope:u.$$isolateScope||u.$$newScope});P.$$slots=M}if(u.template)if(I=!0,X("template",L,u,N),L=u,x=z(u.template)?u.template(N,d):u.template,x=ra(x),u.replace){g=u;Q=Vb.test(x)?$c(ca(u.templateNamespace,W(x))):
[];b=Q[0];if(1!=Q.length||1!==b.nodeType)throw fa("tplrt",G,"");da(f,N,b);E={$attr:{}};x=$b(b,[],E);var aa=a.splice(A+1,a.length-(A+1));(s||v)&&ad(x,s,v);a=a.concat(x).concat(aa);U(d,E);E=a.length}else N.html(x);if(u.templateUrl)I=!0,X("template",L,u,N),L=u,u.replace&&(g=u),m=$(a.splice(A,a.length-A),N,d,f,D&&P,h,k,{controllerDirectives:q,newScopeDirective:v!==u&&v,newIsolateScopeDirective:s,templateDirective:L,nonTlbTranscludeDirective:C}),E=a.length;else if(u.compile)try{t=u.compile(N,d,P);var Z=
u.$$originalDirective||u;z(t)?n(null,bb(Z,t),F,Ta):t&&n(bb(Z,t.pre),bb(Z,t.post),F,Ta)}catch(ea){c(ea,va(N))}u.terminal&&(m.terminal=!0,p=Math.max(p,u.priority))}m.scope=v&&!0===v.scope;m.transcludeOnThisElement=D;m.templateOnThisElement=I;m.transclude=P;l.hasElementTranscludeDirective=y;return m}function ib(a,b,c,d){var e;if(F(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;if(!e){var h="$"+b+"Controller";e=g?c.inheritedData(h):
c.data(h)}if(!e&&!f)throw fa("ctreq",b,a);}else if(J(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=ib(a,b[g],c,d);else H(b)&&(e={},r(b,function(b,f){e[f]=ib(a,b,c,d)}));return e||null}function ag(a,b,c,d,e,f,g){var h=T(),k;for(k in d){var l=d[k],n={$scope:l===g||l.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},m=l.controller;"@"==m&&(m=b[l.name]);n=y(m,n,!0,l.controllerAs);h[l.name]=n;a.data("$"+l.name+"Controller",n.instance)}return h}function ad(a,b,c){for(var d=0,e=a.length;d<e;d++)a[d]=Rb(a[d],
{$$isolateScope:b,$$newScope:c})}function Da(b,e,g,h,k,l,n){if(e===k)return null;k=null;if(f.hasOwnProperty(e)){var m;e=a.get(e+"Directive");for(var p=0,v=e.length;p<v;p++)try{if(m=e[p],(w(h)||h>m.priority)&&-1!=m.restrict.indexOf(g)){l&&(m=Rb(m,{$$start:l,$$end:n}));if(!m.$$bindings){var q=m,s=m,L=m.name,u={isolateScope:null,bindToController:null};H(s.scope)&&(!0===s.bindToController?(u.bindToController=d(s.scope,L,!0),u.isolateScope={}):u.isolateScope=d(s.scope,L,!1));H(s.bindToController)&&(u.bindToController=
d(s.bindToController,L,!0));if(H(u.bindToController)){var C=s.controller,D=s.controllerAs;if(!C)throw fa("noctrl",L);if(!Xc(C,D))throw fa("noident",L);}var N=q.$$bindings=u;H(N.isolateScope)&&(m.$$isolateBindings=N.isolateScope)}b.push(m);k=m}}catch(G){c(G)}}return k}function S(b){if(f.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,e=c.length;d<e;d++)if(b=c[d],b.multiElement)return!0;return!1}function U(a,b){var c=b.$attr,d=a.$attr;r(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===
e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});r(b,function(b,e){a.hasOwnProperty(e)||"$"===e.charAt(0)||(a[e]=b,"class"!==e&&"style"!==e&&(d[e]=c[e]))})}function $(a,b,c,d,f,g,h,k){var l=[],n,m,p=b[0],s=a.shift(),q=Rb(s,{templateUrl:null,transclude:null,replace:null,$$originalDirective:s}),L=z(s.templateUrl)?s.templateUrl(b,c):s.templateUrl,u=s.templateNamespace;b.empty();e(L).then(function(e){var v,C;e=ra(e);if(s.replace){e=Vb.test(e)?$c(ca(u,W(e))):[];v=e[0];if(1!=e.length||1!==v.nodeType)throw fa("tplrt",
s.name,L);e={$attr:{}};da(d,b,v);var D=$b(v,[],e);H(s.scope)&&ad(D,!0);a=D.concat(a);U(c,e)}else v=p,b.html(e);a.unshift(q);n=Ta(a,v,c,f,b,s,g,h,k);r(d,function(a,c){a==v&&(d[c]=b[0])});for(m=t(b[0].childNodes,f);l.length;){e=l.shift();C=l.shift();var I=l.shift(),G=l.shift(),D=b[0];if(!e.$$destroyed){if(C!==p){var y=C.className;k.hasElementTranscludeDirective&&s.replace||(D=Xb(v));da(I,B(C),D);N(B(D),y)}C=n.transcludeOnThisElement?wa(e,n.transclude,G):G;n(m,e,D,d,C)}}l=null});return function(a,b,
c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(n.transcludeOnThisElement&&(a=wa(b,n.transclude,e)),n(m,b,c,d,a)))}}function Y(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function X(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw fa("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,va(d));}function aa(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&ba.$$addBindingClass(a);
return function(a,c){var e=c.parent();b||ba.$$addBindingClass(e);ba.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function ca(a,b){a=M(a||"html");switch(a){case "svg":case "math":var c=E.document.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function ea(a,b){if("srcdoc"==b)return L.HTML;var c=ua(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return L.RESOURCE_URL}function ia(a,
c,d,e,f){var g=ea(a,e);f=k[e]||f;var h=b(d,!0,g,f);if(h){if("multiple"===e&&"select"===ua(a))throw fa("selmulti",va(a));c.push({priority:100,compile:function(){return{pre:function(a,c,k){c=k.$$observers||(k.$$observers=T());if(m.test(e))throw fa("nodomevents");var l=k[e];l!==d&&(h=l&&b(l,!0,g,f),d=l);h&&(k[e]=h(a),(c[e]||(c[e]=[])).$$inter=!0,(k.$$observers&&k.$$observers[e].$$scope||a).$watch(h,function(a,b){"class"===e&&a!=b?k.$updateClass(a,b):k.$set(e,a)}))}}}})}}function da(a,b,c){var d=b[0],
e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=E.document.createDocumentFragment();for(g=0;g<e;g++)a.appendChild(b[g]);B.hasData(d)&&(B.data(c,B.data(d)),B(d).off("$destroy"));B.cleanData(a.querySelectorAll("*"));for(g=1;g<e;g++)delete b[g];b[0]=c;b.length=1}function ga(a,b){return R(function(){return a.apply(null,arguments)},
a,b)}function ja(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,va(d))}}function ha(a,c,d,e,f){function g(b,c,e){z(d.$onChanges)&&c!==e&&(Z||(a.$$postDigest(G),Z=[]),m||(m={},Z.push(h)),m[b]&&(e=m[b].previousValue),m[b]=new Fb(e,c))}function h(){d.$onChanges(m);m=void 0}var k=[],l={},m;r(e,function(e,h){var m=e.attrName,p=e.optional,v,s,L,C;switch(e.mode){case "@":p||sa.call(c,m)||(d[h]=c[m]=void 0);c.$observe(m,function(a){if(F(a)||Ea(a))g(h,a,d[h]),d[h]=a});c.$$observers[m].$$scope=a;v=c[m];F(v)?d[h]=
b(v)(a):Ea(v)&&(d[h]=v);l[h]=new Fb(bc,d[h]);break;case "=":if(!sa.call(c,m)){if(p)break;c[m]=void 0}if(p&&!c[m])break;s=n(c[m]);C=s.literal?na:function(a,b){return a===b||a!==a&&b!==b};L=s.assign||function(){v=d[h]=s(a);throw fa("nonassign",c[m],m,f.name);};v=d[h]=s(a);p=function(b){C(b,d[h])||(C(b,v)?L(a,b=d[h]):d[h]=b);return v=b};p.$stateful=!0;p=e.collection?a.$watchCollection(c[m],p):a.$watch(n(c[m],p),null,s.literal);k.push(p);break;case "<":if(!sa.call(c,m)){if(p)break;c[m]=void 0}if(p&&!c[m])break;
s=n(c[m]);var D=d[h]=s(a);l[h]=new Fb(bc,d[h]);p=a.$watch(s,function(a,b){if(b===a){if(b===D)return;b=D}g(h,a,b);d[h]=a},s.literal);k.push(p);break;case "&":s=c.hasOwnProperty(m)?n(c[m]):A;if(s===A&&p)break;d[h]=function(b){return s(a,b)}}});return{initialChanges:l,removeWatches:k.length&&function(){for(var a=0,b=k.length;a<b;++a)k[a]()}}}var ma=/^\w/,la=E.document.createElement("div"),oa=s,Z;Aa.prototype={$normalize:xa,$addClass:function(a){a&&0<a.length&&C.addClass(this.$$element,a)},$removeClass:function(a){a&&
0<a.length&&C.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=bd(a,b);c&&c.length&&C.addClass(this.$$element,c);(c=bd(b,a))&&c.length&&C.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=Uc(this.$$element[0],a),g=cd[a],h=a;f?(this.$$element.prop(a,b),e=f):g&&(this[g]=b,h=g);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Cc(a,"-"));f=ua(this.$$element);if("a"===f&&("href"===a||"xlinkHref"===a)||"img"===f&&"src"===a)this[a]=b=D(b,"src"===a);else if("img"===
f&&"srcset"===a&&x(b)){for(var f="",g=W(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(g)?k:/(,)/,g=g.split(k),k=Math.floor(g.length/2),l=0;l<k;l++)var n=2*l,f=f+D(W(g[n]),!0),f=f+(" "+W(g[n+1]));g=W(g[2*l]).split(/\s/);f+=D(W(g[0]),!0);2===g.length&&(f+=" "+W(g[1]));this[a]=b=f}!1!==d&&(null===b||w(b)?this.$$element.removeAttr(e):ma.test(e)?this.$$element.attr(e,b):Q(this.$$element[0],e,b));(a=this.$$observers)&&r(a[h],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,
d=c.$$observers||(c.$$observers=T()),e=d[a]||(d[a]=[]);e.push(b);P.$evalAsync(function(){e.$$inter||!c.hasOwnProperty(a)||w(c[a])||b(c[a])});return function(){$a(e,b)}}};var pa=b.startSymbol(),qa=b.endSymbol(),ra="{{"==pa&&"}}"==qa?Ya:function(a){return a.replace(/\{\{/g,pa).replace(/}}/g,qa)},ya=/^ngAttr[A-Z]/,za=/^(.+)Start$/;ba.$$addBindingInfo=p?function(a,b){var c=a.data("$binding")||[];J(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:A;ba.$$addBindingClass=p?function(a){N(a,"ng-binding")}:
A;ba.$$addScopeInfo=p?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:A;ba.$$addScopeClass=p?function(a,b){N(a,b?"ng-isolate-scope":"ng-scope")}:A;ba.$$createComment=function(a,b){var c="";p&&(c=" "+(a||"")+": ",b&&(c+=b+" "));return E.document.createComment(c)};return ba}]}function Fb(a,b){this.previousValue=a;this.currentValue=b}function xa(a){return eb(a.replace(Yc,""))}function bd(a,b){var d="",c=a.split(/\s+/),e=b.split(/\s+/),f=0;a:for(;f<c.length;f++){for(var g=
c[f],h=0;h<e.length;h++)if(g==e[h])continue a;d+=(0<d.length?" ":"")+g}return d}function $c(a){a=B(a);var b=a.length;if(1>=b)return a;for(;b--;)8===a[b].nodeType&&bg.call(a,b,1);return a}function Xc(a,b){if(b&&F(b))return b;if(F(a)){var d=dd.exec(a);if(d)return d[3]}}function gf(){var a={},b=!1;this.has=function(b){return a.hasOwnProperty(b)};this.register=function(b,c){Ra(b,"controller");H(b)?R(a,b):a[b]=c};this.allowGlobals=function(){b=!0};this.$get=["$injector","$window",function(d,c){function e(a,
b,c,d){if(!a||!H(a.$scope))throw O("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,k){var l,m,n;h=!0===h;k&&F(k)&&(n=k);if(F(f)){k=f.match(dd);if(!k)throw cg("ctrlfmt",f);m=k[1];n=n||k[3];f=a.hasOwnProperty(m)?a[m]:Ec(g.$scope,m,!0)||(b?Ec(c,m,!0):void 0);Qa(f,m,!0)}if(h)return h=(J(f)?f[f.length-1]:f).prototype,l=Object.create(h||null),n&&e(g,n,l,m||f.name),R(function(){var a=d.invoke(f,l,g,m);a!==l&&(H(a)||z(a))&&(l=a,n&&e(g,n,l,m||f.name));return l},{instance:l,identifier:n});l=
d.instantiate(f,g,m);n&&e(g,n,l,m||f.name);return l}}]}function hf(){this.$get=["$window",function(a){return B(a.document)}]}function jf(){this.$get=["$log",function(a){return function(b,d){a.error.apply(a,arguments)}}]}function cc(a){return H(a)?ia(a)?a.toISOString():cb(a):a}function of(){this.$get=function(){return function(a){if(!a)return"";var b=[];tc(a,function(a,c){null===a||w(a)||(J(a)?r(a,function(a){b.push(ja(c)+"="+ja(cc(a)))}):b.push(ja(c)+"="+ja(cc(a))))});return b.join("&")}}}function pf(){this.$get=
function(){return function(a){function b(a,e,f){null===a||w(a)||(J(a)?r(a,function(a,c){b(a,e+"["+(H(a)?c:"")+"]")}):H(a)&&!ia(a)?tc(a,function(a,c){b(a,e+(f?"":"[")+c+(f?"":"]"))}):d.push(ja(e)+"="+ja(cc(a))))}if(!a)return"";var d=[];b(a,"",!0);return d.join("&")}}}function dc(a,b){if(F(a)){var d=a.replace(dg,"").trim();if(d){var c=b("Content-Type");(c=c&&0===c.indexOf(ed))||(c=(c=d.match(eg))&&fg[c[0]].test(d));c&&(a=xc(d))}}return a}function fd(a){var b=T(),d;F(a)?r(a.split("\n"),function(a){d=
a.indexOf(":");var e=M(W(a.substr(0,d)));a=W(a.substr(d+1));e&&(b[e]=b[e]?b[e]+", "+a:a)}):H(a)&&r(a,function(a,d){var f=M(d),g=W(a);f&&(b[f]=b[f]?b[f]+", "+g:g)});return b}function gd(a){var b;return function(d){b||(b=fd(a));return d?(d=b[M(d)],void 0===d&&(d=null),d):b}}function hd(a,b,d,c){if(z(c))return c(a,b,d);r(c,function(c){a=c(a,b,d)});return a}function nf(){var a=this.defaults={transformResponse:[dc],transformRequest:[function(a){return H(a)&&"[object File]"!==ka.call(a)&&"[object Blob]"!==
ka.call(a)&&"[object FormData]"!==ka.call(a)?cb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ga(ec),put:ga(ec),patch:ga(ec)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},b=!1;this.useApplyAsync=function(a){return x(a)?(b=!!a,this):b};var d=!0;this.useLegacyPromiseExtensions=function(a){return x(a)?(d=!!a,this):d};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",
function(e,f,g,h,k,l){function m(b){function c(a){var b=R({},a);b.data=hd(a.data,a.headers,a.status,f.transformResponse);a=a.status;return 200<=a&&300>a?b:k.reject(b)}function e(a,b){var c,d={};r(a,function(a,e){z(a)?(c=a(b),null!=c&&(d[e]=c)):d[e]=a});return d}if(!H(b))throw O("$http")("badreq",b);if(!F(b.url))throw O("$http")("badreq",b.url);var f=R({method:"get",transformRequest:a.transformRequest,transformResponse:a.transformResponse,paramSerializer:a.paramSerializer},b);f.headers=function(b){var c=
a.headers,d=R({},b.headers),f,g,h,c=R({},c.common,c[M(b.method)]);a:for(f in c){g=M(f);for(h in d)if(M(h)===g)continue a;d[f]=c[f]}return e(d,ga(b))}(b);f.method=ub(f.method);f.paramSerializer=F(f.paramSerializer)?l.get(f.paramSerializer):f.paramSerializer;var g=[function(b){var d=b.headers,e=hd(b.data,gd(d),void 0,b.transformRequest);w(e)&&r(d,function(a,b){"content-type"===M(b)&&delete d[b]});w(b.withCredentials)&&!w(a.withCredentials)&&(b.withCredentials=a.withCredentials);return n(b,e).then(c,
c)},void 0],h=k.when(f);for(r(V,function(a){(a.request||a.requestError)&&g.unshift(a.request,a.requestError);(a.response||a.responseError)&&g.push(a.response,a.responseError)});g.length;){b=g.shift();var m=g.shift(),h=h.then(b,m)}d?(h.success=function(a){Qa(a,"fn");h.then(function(b){a(b.data,b.status,b.headers,f)});return h},h.error=function(a){Qa(a,"fn");h.then(null,function(b){a(b.data,b.status,b.headers,f)});return h}):(h.success=id("success"),h.error=id("error"));return h}function n(c,d){function g(a){if(a){var c=
{};r(a,function(a,d){c[d]=function(c){function d(){a(c)}b?h.$applyAsync(d):h.$$phase?d():h.$apply(d)}});return c}}function l(a,c,d,e){function f(){n(c,a,d,e)}D&&(200<=a&&300>a?D.put(Q,[a,c,fd(d),e]):D.remove(Q));b?h.$applyAsync(f):(f(),h.$$phase||h.$apply())}function n(a,b,d,e){b=-1<=b?b:0;(200<=b&&300>b?L.resolve:L.reject)({data:a,status:b,headers:gd(d),config:c,statusText:e})}function y(a){n(a.data,a.status,ga(a.headers()),a.statusText)}function V(){var a=m.pendingRequests.indexOf(c);-1!==a&&m.pendingRequests.splice(a,
1)}var L=k.defer(),C=L.promise,D,G,Aa=c.headers,Q=p(c.url,c.paramSerializer(c.params));m.pendingRequests.push(c);C.then(V,V);!c.cache&&!a.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(D=H(c.cache)?c.cache:H(a.cache)?a.cache:s);D&&(G=D.get(Q),x(G)?G&&z(G.then)?G.then(y,y):J(G)?n(G[1],G[0],ga(G[2]),G[3]):n(G,200,{},"OK"):D.put(Q,C));w(G)&&((G=jd(c.url)?f()[c.xsrfCookieName||a.xsrfCookieName]:void 0)&&(Aa[c.xsrfHeaderName||a.xsrfHeaderName]=G),e(c.method,Q,d,l,Aa,c.timeout,c.withCredentials,
c.responseType,g(c.eventHandlers),g(c.uploadEventHandlers)));return C}function p(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b);return a}var s=g("$http");a.paramSerializer=F(a.paramSerializer)?l.get(a.paramSerializer):a.paramSerializer;var V=[];r(c,function(a){V.unshift(F(a)?l.get(a):l.invoke(a))});m.pendingRequests=[];(function(a){r(arguments,function(a){m[a]=function(b,c){return m(R({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){r(arguments,function(a){m[a]=function(b,
c,d){return m(R({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");m.defaults=a;return m}]}function rf(){this.$get=function(){return function(){return new E.XMLHttpRequest}}}function qf(){this.$get=["$browser","$window","$document","$xhrFactory",function(a,b,d,c){return gg(a,c,a.defer,b.angular.callbacks,d[0])}]}function gg(a,b,d,c,e){function f(a,b,d){var f=e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m,!1);f.removeEventListener("error",
m,!1);e.body.removeChild(f);f=null;var g=-1,s="unknown";a&&("load"!==a.type||c[b].called||(a={type:"error"}),s=a.type,g="error"===a.type?404:200);d&&d(g,s)};f.addEventListener("load",m,!1);f.addEventListener("error",m,!1);e.body.appendChild(f);return m}return function(e,h,k,l,m,n,p,s,V,I){function q(){u&&u();y&&y.abort()}function K(b,c,e,f,g){x(L)&&d.cancel(L);u=y=null;b(c,e,f,g);a.$$completeOutstandingRequest(A)}a.$$incOutstandingRequestCount();h=h||a.url();if("jsonp"==M(e)){var v="_"+(c.counter++).toString(36);
c[v]=function(a){c[v].data=a;c[v].called=!0};var u=f(h.replace("JSON_CALLBACK","angular.callbacks."+v),v,function(a,b){K(l,a,c[v].data,"",b);c[v]=A})}else{var y=b(e,h);y.open(e,h,!0);r(m,function(a,b){x(a)&&y.setRequestHeader(b,a)});y.onload=function(){var a=y.statusText||"",b="response"in y?y.response:y.responseText,c=1223===y.status?204:y.status;0===c&&(c=b?200:"file"==qa(h).protocol?404:0);K(l,c,b,y.getAllResponseHeaders(),a)};e=function(){K(l,-1,null,null,"")};y.onerror=e;y.onabort=e;r(V,function(a,
b){y.addEventListener(b,a)});r(I,function(a,b){y.upload.addEventListener(b,a)});p&&(y.withCredentials=!0);if(s)try{y.responseType=s}catch(P){if("json"!==s)throw P;}y.send(w(k)?null:k)}if(0<n)var L=d(q,n);else n&&z(n.then)&&n.then(q)}}function lf(){var a="{{",b="}}";this.startSymbol=function(b){return b?(a=b,this):a};this.endSymbol=function(a){return a?(b=a,this):b};this.$get=["$parse","$exceptionHandler","$sce",function(d,c,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(n,a).replace(p,
b)}function h(a,b,c,d){var e;return e=a.$watch(function(a){e();return d(a)},b,c)}function k(f,k,n,p){function r(a){try{var b=a;a=n?e.getTrusted(n,b):e.valueOf(b);var d;if(p&&!x(a))d=a;else if(null==a)d="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=cb(a)}d=a}return d}catch(g){c(Ka.interr(f,g))}}if(!f.length||-1===f.indexOf(a)){var v;k||(k=g(f),v=da(k),v.exp=f,v.expressions=[],v.$$watchDelegate=h);return v}p=!!p;var u,y,P=0,L=[],C=[];v=f.length;for(var D=[],G=[];P<
v;)if(-1!=(u=f.indexOf(a,P))&&-1!=(y=f.indexOf(b,u+l)))P!==u&&D.push(g(f.substring(P,u))),P=f.substring(u+l,y),L.push(P),C.push(d(P,r)),P=y+m,G.push(D.length),D.push("");else{P!==v&&D.push(g(f.substring(P)));break}n&&1<D.length&&Ka.throwNoconcat(f);if(!k||L.length){var Aa=function(a){for(var b=0,c=L.length;b<c;b++){if(p&&w(a[b]))return;D[G[b]]=a[b]}return D.join("")};return R(function(a){var b=0,d=L.length,e=Array(d);try{for(;b<d;b++)e[b]=C[b](a);return Aa(e)}catch(g){c(Ka.interr(f,g))}},{exp:f,expressions:L,
$$watchDelegate:function(a,b){var c;return a.$watchGroup(C,function(d,e){var f=Aa(d);z(b)&&b.call(this,f,d!==e?c:f,a);c=f})}})}}var l=a.length,m=b.length,n=new RegExp(a.replace(/./g,f),"g"),p=new RegExp(b.replace(/./g,f),"g");k.startSymbol=function(){return a};k.endSymbol=function(){return b};return k}]}function mf(){this.$get=["$rootScope","$window","$q","$$q","$browser",function(a,b,d,c,e){function f(f,k,l,m){function n(){p?f.apply(null,s):f(q)}var p=4<arguments.length,s=p?ta.call(arguments,4):
[],r=b.setInterval,I=b.clearInterval,q=0,K=x(m)&&!m,v=(K?c:d).defer(),u=v.promise;l=x(l)?l:0;u.$$intervalId=r(function(){K?e.defer(n):a.$evalAsync(n);v.notify(q++);0<l&&q>=l&&(v.resolve(q),I(u.$$intervalId),delete g[u.$$intervalId]);K||a.$apply()},k);g[u.$$intervalId]=v;return u}var g={};f.cancel=function(a){return a&&a.$$intervalId in g?(g[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId),delete g[a.$$intervalId],!0):!1};return f}]}function fc(a){a=a.split("/");for(var b=a.length;b--;)a[b]=
qb(a[b]);return a.join("/")}function kd(a,b){var d=qa(a);b.$$protocol=d.protocol;b.$$host=d.hostname;b.$$port=aa(d.port)||hg[d.protocol]||null}function ld(a,b){var d="/"!==a.charAt(0);d&&(a="/"+a);var c=qa(a);b.$$path=decodeURIComponent(d&&"/"===c.pathname.charAt(0)?c.pathname.substring(1):c.pathname);b.$$search=Ac(c.search);b.$$hash=decodeURIComponent(c.hash);b.$$path&&"/"!=b.$$path.charAt(0)&&(b.$$path="/"+b.$$path)}function la(a,b){if(0===b.lastIndexOf(a,0))return b.substr(a.length)}function Ja(a){var b=
a.indexOf("#");return-1==b?a:a.substr(0,b)}function jb(a){return a.replace(/(#.+)|#$/,"$1")}function gc(a,b,d){this.$$html5=!0;d=d||"";kd(a,this);this.$$parse=function(a){var d=la(b,a);if(!F(d))throw Gb("ipthprfx",a,b);ld(d,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Tb(this.$$search),d=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(a?"?"+a:"")+d;this.$$absUrl=b+this.$$url.substr(1)};this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),
!0;var f,g;x(f=la(a,c))?(g=f,g=x(f=la(d,f))?b+(la("/",f)||f):a+g):x(f=la(b,c))?g=b+f:b==c+"/"&&(g=b);g&&this.$$parse(g);return!!g}}function hc(a,b,d){kd(a,this);this.$$parse=function(c){var e=la(a,c)||la(b,c),f;w(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",w(e)&&(a=c,this.replace())):(f=la(d,e),w(f)&&(f=e));ld(f,this);c=this.$$path;var e=a,g=/^\/[A-Z]:(\/.*)/;0===f.lastIndexOf(e,0)&&(f=f.replace(e,""));g.exec(f)||(c=(f=g.exec(c))?f[1]:c);this.$$path=c;this.$$compose()};this.$$compose=function(){var b=
Tb(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+(this.$$url?d+this.$$url:"")};this.$$parseLinkUrl=function(b,d){return Ja(a)==Ja(b)?(this.$$parse(b),!0):!1}}function md(a,b,d){this.$$html5=!0;hc.apply(this,arguments);this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;a==Ja(c)?f=c:(g=la(b,c))?f=a+d+g:b===c+"/"&&(f=b);f&&this.$$parse(f);return!!f};this.$$compose=function(){var b=Tb(this.$$search),
e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=fc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+d+this.$$url}}function Hb(a){return function(){return this[a]}}function nd(a,b){return function(d){if(w(d))return this[a];this[a]=b(d);this.$$compose();return this}}function sf(){var a="",b={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(b){return x(b)?(a=b,this):a};this.html5Mode=function(a){return Ea(a)?(b.enabled=a,this):H(a)?(Ea(a.enabled)&&(b.enabled=a.enabled),Ea(a.requireBase)&&
(b.requireBase=a.requireBase),Ea(a.rewriteLinks)&&(b.rewriteLinks=a.rewriteLinks),this):b};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(d,c,e,f,g){function h(a,b,d){var e=l.url(),f=l.$$state;try{c.url(a,b,d),l.$$state=c.state()}catch(g){throw l.url(e),l.$$state=f,g;}}function k(a,b){d.$broadcast("$locationChangeSuccess",l.absUrl(),a,l.$$state,b)}var l,m;m=c.baseHref();var n=c.url(),p;if(b.enabled){if(!m&&b.requireBase)throw Gb("nobase");p=n.substring(0,n.indexOf("/",
n.indexOf("//")+2))+(m||"/");m=e.history?gc:md}else p=Ja(n),m=hc;var s=p.substr(0,Ja(p).lastIndexOf("/")+1);l=new m(p,s,"#"+a);l.$$parseLinkUrl(n,n);l.$$state=c.state();var r=/^\s*(javascript|mailto):/i;f.on("click",function(a){if(b.rewriteLinks&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&2!=a.which&&2!=a.button){for(var e=B(a.target);"a"!==ua(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),k=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=
qa(h.animVal).href);r.test(h)||!h||e.attr("target")||a.isDefaultPrevented()||!l.$$parseLinkUrl(h,k)||(a.preventDefault(),l.absUrl()!=c.url()&&(d.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});jb(l.absUrl())!=jb(n)&&c.url(l.absUrl(),!0);var I=!0;c.onUrlChange(function(a,b){w(la(s,a))?g.location.href=a:(d.$evalAsync(function(){var c=l.absUrl(),e=l.$$state,f;a=jb(a);l.$$parse(a);l.$$state=b;f=d.$broadcast("$locationChangeStart",a,c,b,e).defaultPrevented;l.absUrl()===a&&(f?(l.$$parse(c),l.$$state=
e,h(c,!1,e)):(I=!1,k(c,e)))}),d.$$phase||d.$digest())});d.$watch(function(){var a=jb(c.url()),b=jb(l.absUrl()),f=c.state(),g=l.$$replace,n=a!==b||l.$$html5&&e.history&&f!==l.$$state;if(I||n)I=!1,d.$evalAsync(function(){var b=l.absUrl(),c=d.$broadcast("$locationChangeStart",b,a,l.$$state,f).defaultPrevented;l.absUrl()===b&&(c?(l.$$parse(a),l.$$state=f):(n&&h(b,g,f===l.$$state?null:l.$$state),k(a,f)))});l.$$replace=!1});return l}]}function tf(){var a=!0,b=this;this.debugEnabled=function(b){return x(b)?
(a=b,this):a};this.$get=["$window",function(d){function c(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=d.console||{},e=b[a]||b.log||A;a=!1;try{a=!!e.apply}catch(k){}return a?function(){var a=[];r(arguments,function(b){a.push(c(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),
debug:function(){var c=e("debug");return function(){a&&c.apply(b,arguments)}}()}}]}function Ua(a,b){if("__defineGetter__"===a||"__defineSetter__"===a||"__lookupGetter__"===a||"__lookupSetter__"===a||"__proto__"===a)throw ca("isecfld",b);return a}function ig(a){return a+""}function ra(a,b){if(a){if(a.constructor===a)throw ca("isecfn",b);if(a.window===a)throw ca("isecwindow",b);if(a.children&&(a.nodeName||a.prop&&a.attr&&a.find))throw ca("isecdom",b);if(a===Object)throw ca("isecobj",b);}return a}function od(a,
b){if(a){if(a.constructor===a)throw ca("isecfn",b);if(a===jg||a===kg||a===lg)throw ca("isecff",b);}}function Ib(a,b){if(a&&(a===(0).constructor||a===(!1).constructor||a==="".constructor||a==={}.constructor||a===[].constructor||a===Function.constructor))throw ca("isecaf",b);}function mg(a,b){return"undefined"!==typeof a?a:b}function pd(a,b){return"undefined"===typeof a?b:"undefined"===typeof b?a:a+b}function $(a,b){var d,c;switch(a.type){case t.Program:d=!0;r(a.body,function(a){$(a.expression,b);d=
d&&a.expression.constant});a.constant=d;break;case t.Literal:a.constant=!0;a.toWatch=[];break;case t.UnaryExpression:$(a.argument,b);a.constant=a.argument.constant;a.toWatch=a.argument.toWatch;break;case t.BinaryExpression:$(a.left,b);$(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case t.LogicalExpression:$(a.left,b);$(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.constant?[]:[a];break;case t.ConditionalExpression:$(a.test,
b);$(a.alternate,b);$(a.consequent,b);a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant;a.toWatch=a.constant?[]:[a];break;case t.Identifier:a.constant=!1;a.toWatch=[a];break;case t.MemberExpression:$(a.object,b);a.computed&&$(a.property,b);a.constant=a.object.constant&&(!a.computed||a.property.constant);a.toWatch=[a];break;case t.CallExpression:d=a.filter?!b(a.callee.name).$stateful:!1;c=[];r(a.arguments,function(a){$(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});
a.constant=d;a.toWatch=a.filter&&!b(a.callee.name).$stateful?c:[a];break;case t.AssignmentExpression:$(a.left,b);$(a.right,b);a.constant=a.left.constant&&a.right.constant;a.toWatch=[a];break;case t.ArrayExpression:d=!0;c=[];r(a.elements,function(a){$(a,b);d=d&&a.constant;a.constant||c.push.apply(c,a.toWatch)});a.constant=d;a.toWatch=c;break;case t.ObjectExpression:d=!0;c=[];r(a.properties,function(a){$(a.value,b);d=d&&a.value.constant&&!a.computed;a.value.constant||c.push.apply(c,a.value.toWatch)});
a.constant=d;a.toWatch=c;break;case t.ThisExpression:a.constant=!1;a.toWatch=[];break;case t.LocalsExpression:a.constant=!1,a.toWatch=[]}}function qd(a){if(1==a.length){a=a[0].expression;var b=a.toWatch;return 1!==b.length?b:b[0]!==a?b:void 0}}function rd(a){return a.type===t.Identifier||a.type===t.MemberExpression}function sd(a){if(1===a.body.length&&rd(a.body[0].expression))return{type:t.AssignmentExpression,left:a.body[0].expression,right:{type:t.NGValueParameter},operator:"="}}function td(a){return 0===
a.body.length||1===a.body.length&&(a.body[0].expression.type===t.Literal||a.body[0].expression.type===t.ArrayExpression||a.body[0].expression.type===t.ObjectExpression)}function ud(a,b){this.astBuilder=a;this.$filter=b}function vd(a,b){this.astBuilder=a;this.$filter=b}function Jb(a){return"constructor"==a}function ic(a){return z(a.valueOf)?a.valueOf():ng.call(a)}function uf(){var a=T(),b=T(),d={"true":!0,"false":!1,"null":null,undefined:void 0},c,e;this.addLiteral=function(a,b){d[a]=b};this.setIdentifierFns=
function(a,b){c=a;e=b;return this};this.$get=["$filter",function(f){function g(c,d,e){var g,k,C;e=e||K;switch(typeof c){case "string":C=c=c.trim();var D=e?b:a;g=D[C];if(!g){":"===c.charAt(0)&&":"===c.charAt(1)&&(k=!0,c=c.substring(2));g=e?q:I;var G=new jc(g);g=(new kc(G,f,g)).parse(c);g.constant?g.$$watchDelegate=p:k?g.$$watchDelegate=g.literal?n:m:g.inputs&&(g.$$watchDelegate=l);e&&(g=h(g));D[C]=g}return s(g,d);case "function":return s(c,d);default:return s(A,d)}}function h(a){function b(c,d,e,f){var g=
K;K=!0;try{return a(c,d,e,f)}finally{K=g}}if(!a)return a;b.$$watchDelegate=a.$$watchDelegate;b.assign=h(a.assign);b.constant=a.constant;b.literal=a.literal;for(var c=0;a.inputs&&c<a.inputs.length;++c)a.inputs[c]=h(a.inputs[c]);b.inputs=a.inputs;return b}function k(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=ic(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function l(a,b,c,d,e){var f=d.inputs,g;if(1===f.length){var h=k,f=f[0];return a.$watch(function(a){var b=f(a);k(b,h)||(g=d(a,void 0,
void 0,[b]),h=b&&ic(b));return g},b,c,e)}for(var l=[],n=[],m=0,p=f.length;m<p;m++)l[m]=k,n[m]=null;return a.$watch(function(a){for(var b=!1,c=0,e=f.length;c<e;c++){var h=f[c](a);if(b||(b=!k(h,l[c])))n[c]=h,l[c]=h&&ic(h)}b&&(g=d(a,void 0,void 0,n));return g},b,c,e)}function m(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);x(a)&&d.$$postDigest(function(){x(f)&&e()})},c)}function n(a,b,c,d){function e(a){var b=!0;r(a,function(a){x(a)||(b=
!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function p(a,b,c,d){var e;return e=a.$watch(function(a){e();return d(a)},b,c)}function s(a,b){if(!b)return a;var c=a.$$watchDelegate,d=!1,c=c!==n&&c!==m?function(c,e,f,g){f=d&&g?g[0]:a(c,e,f,g);return b(f,c,e)}:function(c,d,e,f){e=a(c,d,e,f);c=b(e,c,d);return x(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!==l?c.$$watchDelegate=a.$$watchDelegate:
b.$stateful||(c.$$watchDelegate=l,d=!a.inputs,c.inputs=a.inputs?a.inputs:[a]);return c}var V=Fa().noUnsafeEval,I={csp:V,expensiveChecks:!1,literals:Z(d),isIdentifierStart:z(c)&&c,isIdentifierContinue:z(e)&&e},q={csp:V,expensiveChecks:!0,literals:Z(d),isIdentifierStart:z(c)&&c,isIdentifierContinue:z(e)&&e},K=!1;g.$$runningExpensiveChecks=function(){return K};return g}]}function wf(){this.$get=["$rootScope","$exceptionHandler",function(a,b){return wd(function(b){a.$evalAsync(b)},b)}]}function xf(){this.$get=
["$browser","$exceptionHandler",function(a,b){return wd(function(b){a.defer(b)},b)}]}function wd(a,b){function d(){this.$$state={status:0}}function c(a,b){return function(c){b.call(a,c)}}function e(c){!c.processScheduled&&c.pending&&(c.processScheduled=!0,a(function(){var a,d,e;e=c.pending;c.processScheduled=!1;c.pending=void 0;for(var f=0,g=e.length;f<g;++f){d=e[f][0];a=e[f][c.status];try{z(a)?d.resolve(a(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),b(h)}}}))}
function f(){this.promise=new d}var g=O("$q",TypeError);R(d.prototype,{then:function(a,b,c){if(w(a)&&w(b)&&w(c))return this;var d=new f;this.$$state.pending=this.$$state.pending||[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&e(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}});R(f.prototype,{resolve:function(a){this.promise.$$state.status||(a===this.promise?
this.$$reject(g("qcycle",a)):this.$$resolve(a))},$$resolve:function(a){function d(a){k||(k=!0,h.$$resolve(a))}function f(a){k||(k=!0,h.$$reject(a))}var g,h=this,k=!1;try{if(H(a)||z(a))g=a&&a.then;z(g)?(this.promise.$$state.status=-1,g.call(a,d,f,c(this,this.notify))):(this.promise.$$state.value=a,this.promise.$$state.status=1,e(this.promise.$$state))}catch(l){f(l),b(l)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=
2;e(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&a(function(){for(var a,e,f=0,g=d.length;f<g;f++){e=d[f][0];a=d[f][3];try{e.notify(z(a)?a(c):c)}catch(h){b(h)}}})}});var h=function(a,b){var c=new f;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return h(e,!1)}return d&&z(d.then)?d.then(function(){return h(a,b)},function(a){return h(a,!1)}):h(a,b)},l=function(a,b,c,d){var e=
new f;e.resolve(a);return e.promise.then(b,c,d)},m=function(a){if(!z(a))throw g("norslvr",a);var b=new f;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};m.prototype=d.prototype;m.defer=function(){var a=new f;a.resolve=c(a,a.resolve);a.reject=c(a,a.reject);a.notify=c(a,a.notify);return a};m.reject=function(a){var b=new f;b.reject(a);return b.promise};m.when=l;m.resolve=l;m.all=function(a){var b=new f,c=0,d=J(a)?[]:{};r(a,function(a,e){c++;l(a).then(function(a){d.hasOwnProperty(e)||
(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return m}function Gf(){this.$get=["$window","$timeout",function(a,b){var d=a.requestAnimationFrame||a.webkitRequestAnimationFrame,c=a.cancelAnimationFrame||a.webkitCancelAnimationFrame||a.webkitCancelRequestAnimationFrame,e=!!d,f=e?function(a){var b=d(a);return function(){c(b)}}:function(a){var c=b(a,16.66,!1);return function(){b.cancel(c)}};f.supported=e;return f}]}function vf(){function a(a){function b(){this.$$watchers=
this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++pb;this.$$ChildScope=null}b.prototype=a;return b}var b=10,d=O("$rootScope"),c=null,e=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$exceptionHandler","$parse","$browser",function(f,g,h){function k(a){a.currentScope.$$destroyed=!0}function l(a){9===Ba&&(a.$$childHead&&l(a.$$childHead),a.$$nextSibling&&l(a.$$nextSibling));a.$parent=a.$$nextSibling=
a.$$prevSibling=a.$$childHead=a.$$childTail=a.$root=a.$$watchers=null}function m(){this.$id=++pb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function n(a){if(K.$$phase)throw d("inprog",K.$$phase);K.$$phase=a}function p(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function s(a,b,c){do a.$$listenerCount[c]-=
b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function t(){}function I(){for(;y.length;)try{y.shift()()}catch(a){f(a)}e=null}function q(){null===e&&(e=h.defer(function(){K.$apply(I)}))}m.prototype={constructor:m,$new:function(b,c){var d;c=c||this;b?(d=new m,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=a(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=
d;(b||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,d,e){var f=g(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,d,f,a);var h=this,k=h.$$watchers,l={fn:b,last:t,get:f,exp:e||a,eq:!!d};c=null;z(b)||(l.fn=A);k||(k=h.$$watchers=[]);k.unshift(l);p(this,1);return function(){0<=$a(k,l)&&p(h,-1);c=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&
b(e,e,g)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});r(a,function(a,b){var k=g.$watch(a,function(a,f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!w(e)){if(H(e))if(oa(e))for(f!==n&&(f=n,q=f.length=0,l++),a=e.length,q!==a&&(l++,f.length=q=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==
p&&(f=p={},q=0,l++);a=0;for(b in e)sa.call(e,b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(q++,f[b]=g,l++));if(q>a)for(b in l++,f)sa.call(e,b)||(q--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1<b.length,l=0,m=g(a,c),n=[],p={},s=!0,q=0;return this.$watch(m,function(){s?(s=!1,b(e,e,d)):b(e,h,d);if(k)if(H(e))if(oa(e)){h=Array(e.length);for(var a=0;a<e.length;a++)h[a]=e[a]}else for(a in h={},e)sa.call(e,a)&&(h[a]=e[a]);else h=e})},$digest:function(){var a,
g,k,l,m,p,s,q,r=b,y,x=[],w,A;n("$digest");h.$$checkUrlChange();this===K&&null!==e&&(h.defer.cancel(e),I());c=null;do{q=!1;y=this;for(p=0;p<v.length;p++){try{A=v[p],A.scope.$eval(A.expression,A.locals)}catch(E){f(E)}c=null}v.length=0;a:do{if(p=y.$$watchers)for(s=p.length;s--;)try{if(a=p[s])if(m=a.get,(g=m(y))!==(k=a.last)&&!(a.eq?na(g,k):"number"===typeof g&&"number"===typeof k&&isNaN(g)&&isNaN(k)))q=!0,c=a,a.last=a.eq?Z(g,null):g,l=a.fn,l(g,k===t?g:k,y),5>r&&(w=4-r,x[w]||(x[w]=[]),x[w].push({msg:z(a.exp)?
"fn: "+(a.exp.name||a.exp.toString()):a.exp,newVal:g,oldVal:k}));else if(a===c){q=!1;break a}}catch(B){f(B)}if(!(p=y.$$watchersCount&&y.$$childHead||y!==this&&y.$$nextSibling))for(;y!==this&&!(p=y.$$nextSibling);)y=y.$parent}while(y=p);if((q||v.length)&&!r--)throw K.$$phase=null,d("infdig",b,x);}while(q||v.length);for(K.$$phase=null;P<u.length;)try{u[P++]()}catch(F){f(F)}u.length=P=0},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===
K&&h.$$applicationDestroyed();p(this,-this.$$watchersCount);for(var b in this.$$listenerCount)s(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=A;this.$on=this.$watch=this.$watchGroup=
function(){return A};this.$$listeners={};this.$$nextSibling=null;l(this)}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){K.$$phase||v.length||h.defer(function(){v.length&&K.$digest()});v.push({scope:this,expression:g(a),locals:b})},$$postDigest:function(a){u.push(a)},$apply:function(a){try{n("$apply");try{return this.$eval(a)}finally{K.$$phase=null}}catch(b){f(b)}finally{try{K.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&y.push(b);
a=g(a);q()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,s(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=ab([h],arguments,1),l,m;do{d=e.$$listeners[a]||c;h.currentScope=
e;l=0;for(m=d.length;l<m;l++)if(d[l])try{d[l].apply(null,k)}catch(n){f(n)}else d.splice(l,1),l--,m--;if(g)return h.currentScope=null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var g=ab([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,g)}catch(l){f(l)}else d.splice(h,
1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var K=new m,v=K.$$asyncQueue=[],u=K.$$postDigestQueue=[],y=K.$$applyAsyncQueue=[],P=0;return K}]}function oe(){var a=/^\s*(https?|ftp|mailto|tel|file):/,b=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(b){return x(b)?(a=b,this):a};this.imgSrcSanitizationWhitelist=function(a){return x(a)?(b=a,this):b};
this.$get=function(){return function(d,c){var e=c?b:a,f;f=qa(d).href;return""===f||f.match(e)?d:"unsafe:"+f}}}function og(a){if("self"===a)return a;if(F(a)){if(-1<a.indexOf("***"))throw ya("iwcard",a);a=xd(a).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+a+"$")}if(Xa(a))return new RegExp("^"+a.source+"$");throw ya("imatcher");}function yd(a){var b=[];x(a)&&r(a,function(a){b.push(og(a))});return b}function zf(){this.SCE_CONTEXTS=ma;var a=["self"],b=[];this.resourceUrlWhitelist=
function(b){arguments.length&&(a=yd(b));return a};this.resourceUrlBlacklist=function(a){arguments.length&&(b=yd(a));return b};this.$get=["$injector",function(d){function c(a,b){return"self"===a?jd(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw ya("unsafe");
};d.has("$sanitize")&&(f=d.get("$sanitize"));var g=e(),h={};h[ma.HTML]=e(g);h[ma.CSS]=e(g);h[ma.URL]=e(g);h[ma.JS]=e(g);h[ma.RESOURCE_URL]=e(h[ma.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw ya("icontext",a,b);if(null===b||w(b)||""===b)return b;if("string"!==typeof b)throw ya("itype",a);return new c(b)},getTrusted:function(d,e){if(null===e||w(e)||""===e)return e;var g=h.hasOwnProperty(d)?h[d]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(d===ma.RESOURCE_URL){var g=
qa(e.toString()),n,p,s=!1;n=0;for(p=a.length;n<p;n++)if(c(a[n],g)){s=!0;break}if(s)for(n=0,p=b.length;n<p;n++)if(c(b[n],g)){s=!1;break}if(s)return e;throw ya("insecurl",e.toString());}if(d===ma.HTML)return f(e);throw ya("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function yf(){var a=!0;this.enabled=function(b){arguments.length&&(a=!!b);return a};this.$get=["$parse","$sceDelegate",function(b,d){if(a&&8>Ba)throw ya("iequirks");var c=ga(ma);c.isEnabled=function(){return a};
c.trustAs=d.trustAs;c.getTrusted=d.getTrusted;c.valueOf=d.valueOf;a||(c.trustAs=c.getTrusted=function(a,b){return b},c.valueOf=Ya);c.parseAs=function(a,d){var e=b(d);return e.literal&&e.constant?e:b(d,function(b){return c.getTrusted(a,b)})};var e=c.parseAs,f=c.getTrusted,g=c.trustAs;r(ma,function(a,b){var d=M(b);c[eb("parse_as_"+d)]=function(b){return e(a,b)};c[eb("get_trusted_"+d)]=function(b){return f(a,b)};c[eb("trust_as_"+d)]=function(b){return g(a,b)}});return c}]}function Af(){this.$get=["$window",
"$document",function(a,b){var d={},c=!(a.chrome&&a.chrome.app&&a.chrome.app.runtime)&&a.history&&a.history.pushState,e=aa((/android (\d+)/.exec(M((a.navigator||{}).userAgent))||[])[1]),f=/Boxee/i.test((a.navigator||{}).userAgent),g=b[0]||{},h,k=/^(Moz|webkit|ms)(?=[A-Z])/,l=g.body&&g.body.style,m=!1,n=!1;if(l){for(var p in l)if(m=k.exec(p)){h=m[0];h=h[0].toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in l&&"webkit");m=!!("transition"in l||h+"Transition"in l);n=!!("animation"in l||h+"Animation"in
l);!e||m&&n||(m=F(l.webkitTransition),n=F(l.webkitAnimation))}return{history:!(!c||4>e||f),hasEvent:function(a){if("input"===a&&11>=Ba)return!1;if(w(d[a])){var b=g.createElement("div");d[a]="on"+a in b}return d[a]},csp:Fa(),vendorPrefix:h,transitions:m,animations:n,android:e}}]}function Cf(){var a;this.httpOptions=function(b){return b?(a=b,this):a};this.$get=["$templateCache","$http","$q","$sce",function(b,d,c,e){function f(g,h){f.totalPendingRequests++;if(!F(g)||w(b.get(g)))g=e.getTrustedResourceUrl(g);
var k=d.defaults&&d.defaults.transformResponse;J(k)?k=k.filter(function(a){return a!==dc}):k===dc&&(k=null);return d.get(g,R({cache:b,transformResponse:k},a))["finally"](function(){f.totalPendingRequests--}).then(function(a){b.put(g,a.data);return a.data},function(a){if(!h)throw pg("tpload",g,a.status,a.statusText);return c.reject(a)})}f.totalPendingRequests=0;return f}]}function Df(){this.$get=["$rootScope","$browser","$location",function(a,b,d){return{findBindings:function(a,b,d){a=a.getElementsByClassName("ng-binding");
var g=[];r(a,function(a){var c=ea.element(a).data("$binding");c&&r(c,function(c){d?(new RegExp("(^|\\s)"+xd(b)+"(\\s|\\||$)")).test(c)&&g.push(a):-1!=c.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,d){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var k=a.querySelectorAll("["+g[h]+"model"+(d?"=":"*=")+'"'+b+'"]');if(k.length)return k}},getLocation:function(){return d.url()},setLocation:function(b){b!==d.url()&&(d.url(b),a.$digest())},whenStable:function(a){b.notifyWhenNoOutstandingRequests(a)}}}]}
function Ef(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(a,b,d,c,e){function f(f,k,l){z(f)||(l=k,k=f,f=A);var m=ta.call(arguments,3),n=x(l)&&!l,p=(n?c:d).defer(),s=p.promise,r;r=b.defer(function(){try{p.resolve(f.apply(null,m))}catch(b){p.reject(b),e(b)}finally{delete g[s.$$timeoutId]}n||a.$apply()},k);s.$$timeoutId=r;g[r]=p;return s}var g={};f.cancel=function(a){return a&&a.$$timeoutId in g?(g[a.$$timeoutId].reject("canceled"),delete g[a.$$timeoutId],b.defer.cancel(a.$$timeoutId)):
!1};return f}]}function qa(a){Ba&&(Y.setAttribute("href",a),a=Y.href);Y.setAttribute("href",a);return{href:Y.href,protocol:Y.protocol?Y.protocol.replace(/:$/,""):"",host:Y.host,search:Y.search?Y.search.replace(/^\?/,""):"",hash:Y.hash?Y.hash.replace(/^#/,""):"",hostname:Y.hostname,port:Y.port,pathname:"/"===Y.pathname.charAt(0)?Y.pathname:"/"+Y.pathname}}function jd(a){a=F(a)?qa(a):a;return a.protocol===zd.protocol&&a.host===zd.host}function Ff(){this.$get=da(E)}function Ad(a){function b(a){try{return decodeURIComponent(a)}catch(b){return a}}
var d=a[0]||{},c={},e="";return function(){var a,g,h,k,l;a=d.cookie||"";if(a!==e)for(e=a,a=e.split("; "),c={},h=0;h<a.length;h++)g=a[h],k=g.indexOf("="),0<k&&(l=b(g.substring(0,k)),w(c[l])&&(c[l]=b(g.substring(k+1))));return c}}function Jf(){this.$get=Ad}function Mc(a){function b(d,c){if(H(d)){var e={};r(d,function(a,c){e[c]=b(c,a)});return e}return a.factory(d+"Filter",c)}this.register=b;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];b("currency",Bd);b("date",Cd);
b("filter",qg);b("json",rg);b("limitTo",sg);b("lowercase",tg);b("number",Dd);b("orderBy",Ed);b("uppercase",ug)}function qg(){return function(a,b,d){if(!oa(a)){if(null==a)return a;throw O("filter")("notarray",a);}var c;switch(lc(b)){case "function":break;case "boolean":case "null":case "number":case "string":c=!0;case "object":b=vg(b,d,c);break;default:return a}return Array.prototype.filter.call(a,b)}}function vg(a,b,d){var c=H(a)&&"$"in a;!0===b?b=na:z(b)||(b=function(a,b){if(w(a))return!1;if(null===
a||null===b)return a===b;if(H(b)||H(a)&&!vc(a))return!1;a=M(""+a);b=M(""+b);return-1!==a.indexOf(b)});return function(e){return c&&!H(e)?La(e,a.$,b,!1):La(e,a,b,d)}}function La(a,b,d,c,e){var f=lc(a),g=lc(b);if("string"===g&&"!"===b.charAt(0))return!La(a,b.substring(1),d,c);if(J(a))return a.some(function(a){return La(a,b,d,c)});switch(f){case "object":var h;if(c){for(h in a)if("$"!==h.charAt(0)&&La(a[h],b,d,!0))return!0;return e?!1:La(a,b,d,!1)}if("object"===g){for(h in b)if(e=b[h],!z(e)&&!w(e)&&
(f="$"===h,!La(f?a:a[h],e,d,f,f)))return!1;return!0}return d(a,b);case "function":return!1;default:return d(a,b)}}function lc(a){return null===a?"null":typeof a}function Bd(a){var b=a.NUMBER_FORMATS;return function(a,c,e){w(c)&&(c=b.CURRENCY_SYM);w(e)&&(e=b.PATTERNS[1].maxFrac);return null==a?a:Fd(a,b.PATTERNS[1],b.GROUP_SEP,b.DECIMAL_SEP,e).replace(/\u00A4/g,c)}}function Dd(a){var b=a.NUMBER_FORMATS;return function(a,c){return null==a?a:Fd(a,b.PATTERNS[0],b.GROUP_SEP,b.DECIMAL_SEP,c)}}function wg(a){var b=
0,d,c,e,f,g;-1<(c=a.indexOf(Gd))&&(a=a.replace(Gd,""));0<(e=a.search(/e/i))?(0>c&&(c=e),c+=+a.slice(e+1),a=a.substring(0,e)):0>c&&(c=a.length);for(e=0;a.charAt(e)==mc;e++);if(e==(g=a.length))d=[0],c=1;else{for(g--;a.charAt(g)==mc;)g--;c-=e;d=[];for(f=0;e<=g;e++,f++)d[f]=+a.charAt(e)}c>Hd&&(d=d.splice(0,Hd-1),b=c-1,c=1);return{d:d,e:b,i:c}}function xg(a,b,d,c){var e=a.d,f=e.length-a.i;b=w(b)?Math.min(Math.max(d,f),c):+b;d=b+a.i;c=e[d];if(0<d){e.splice(Math.max(a.i,d));for(var g=d;g<e.length;g++)e[g]=
0}else for(f=Math.max(0,f),a.i=1,e.length=Math.max(1,d=b+1),e[0]=0,g=1;g<d;g++)e[g]=0;if(5<=c)if(0>d-1){for(c=0;c>d;c--)e.unshift(0),a.i++;e.unshift(1);a.i++}else e[d-1]++;for(;f<Math.max(0,b);f++)e.push(0);if(b=e.reduceRight(function(a,b,c,d){b+=a;d[c]=b%10;return Math.floor(b/10)},0))e.unshift(b),a.i++}function Fd(a,b,d,c,e){if(!F(a)&&!S(a)||isNaN(a))return"";var f=!isFinite(a),g=!1,h=Math.abs(a)+"",k="";if(f)k="\u221e";else{g=wg(h);xg(g,e,b.minFrac,b.maxFrac);k=g.d;h=g.i;e=g.e;f=[];for(g=k.reduce(function(a,
b){return a&&!b},!0);0>h;)k.unshift(0),h++;0<h?f=k.splice(h,k.length):(f=k,k=[0]);h=[];for(k.length>=b.lgSize&&h.unshift(k.splice(-b.lgSize,k.length).join(""));k.length>b.gSize;)h.unshift(k.splice(-b.gSize,k.length).join(""));k.length&&h.unshift(k.join(""));k=h.join(d);f.length&&(k+=c+f.join(""));e&&(k+="e+"+e)}return 0>a&&!g?b.negPre+k+b.negSuf:b.posPre+k+b.posSuf}function Kb(a,b,d,c){var e="";if(0>a||c&&0>=a)c?a=-a+1:(a=-a,e="-");for(a=""+a;a.length<b;)a=mc+a;d&&(a=a.substr(a.length-b));return e+
a}function X(a,b,d,c,e){d=d||0;return function(f){f=f["get"+a]();if(0<d||f>-d)f+=d;0===f&&-12==d&&(f=12);return Kb(f,b,c,e)}}function kb(a,b,d){return function(c,e){var f=c["get"+a](),g=ub((d?"STANDALONE":"")+(b?"SHORT":"")+a);return e[g][f]}}function Id(a){var b=(new Date(a,0,1)).getDay();return new Date(a,0,(4>=b?5:12)-b)}function Jd(a){return function(b){var d=Id(b.getFullYear());b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-+d;b=1+Math.round(b/6048E5);return Kb(b,a)}}function nc(a,
b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function Cd(a){function b(a){var b;if(b=a.match(d)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,k=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=aa(b[9]+b[10]),g=aa(b[9]+b[11]));h.call(a,aa(b[1]),aa(b[2])-1,aa(b[3]));f=aa(b[4]||0)-f;g=aa(b[5]||0)-g;h=aa(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));k.call(a,f,g,h,b)}return a}var d=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
return function(c,d,f){var g="",h=[],k,l;d=d||"mediumDate";d=a.DATETIME_FORMATS[d]||d;F(c)&&(c=yg.test(c)?aa(c):b(c));S(c)&&(c=new Date(c));if(!ia(c)||!isFinite(c.getTime()))return c;for(;d;)(l=zg.exec(d))?(h=ab(h,l,1),d=h.pop()):(h.push(d),d=null);var m=c.getTimezoneOffset();f&&(m=yc(f,m),c=Sb(c,f,!0));r(h,function(b){k=Ag[b];g+=k?k(c,a.DATETIME_FORMATS,m):"''"===b?"'":b.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function rg(){return function(a,b){w(b)&&(b=2);return cb(a,b)}}function sg(){return function(a,
b,d){b=Infinity===Math.abs(Number(b))?Number(b):aa(b);if(isNaN(b))return a;S(a)&&(a=a.toString());if(!oa(a))return a;d=!d||isNaN(d)?0:aa(d);d=0>d?Math.max(0,a.length+d):d;return 0<=b?oc(a,d,d+b):0===d?oc(a,b,a.length):oc(a,Math.max(0,d+b),d)}}function oc(a,b,d){return F(a)?a.slice(b,d):ta.call(a,b,d)}function Ed(a){function b(b){return b.map(function(b){var c=1,d=Ya;if(z(b))d=b;else if(F(b)){if("+"==b.charAt(0)||"-"==b.charAt(0))c="-"==b.charAt(0)?-1:1,b=b.substring(1);if(""!==b&&(d=a(b),d.constant))var e=
d(),d=function(a){return a[e]}}return{get:d,descending:c}})}function d(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}function c(a,b){var c=0,d=a.type,k=b.type;if(d===k){var k=a.value,l=b.value;"string"===d?(k=k.toLowerCase(),l=l.toLowerCase()):"object"===d&&(H(k)&&(k=a.index),H(l)&&(l=b.index));k!==l&&(c=k<l?-1:1)}else c=d<k?-1:1;return c}return function(a,f,g,h){if(null==a)return a;if(!oa(a))throw O("orderBy")("notarray",a);J(f)||(f=[f]);0===f.length&&
(f=["+"]);var k=b(f),l=g?-1:1,m=z(h)?h:c;a=Array.prototype.map.call(a,function(a,b){return{value:a,tieBreaker:{value:b,type:"number",index:b},predicateValues:k.map(function(c){var e=c.get(a);c=typeof e;if(null===e)c="string",e="null";else if("object"===c)a:{if(z(e.valueOf)&&(e=e.valueOf(),d(e)))break a;vc(e)&&(e=e.toString(),d(e))}return{value:e,type:c,index:b}})}});a.sort(function(a,b){for(var c=0,d=k.length;c<d;c++){var e=m(a.predicateValues[c],b.predicateValues[c]);if(e)return e*k[c].descending*
l}return m(a.tieBreaker,b.tieBreaker)*l});return a=a.map(function(a){return a.value})}}function Ma(a){z(a)&&(a={link:a});a.restrict=a.restrict||"AC";return da(a)}function Kd(a,b,d,c,e){var f=this,g=[];f.$error={};f.$$success={};f.$pending=void 0;f.$name=e(b.name||b.ngForm||"")(d);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;f.$$parentForm=Lb;f.$rollbackViewValue=function(){r(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){r(g,function(a){a.$commitViewValue()})};
f.$addControl=function(a){Ra(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a);a.$$parentForm=f};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];r(f.$pending,function(b,c){f.$setValidity(c,null,a)});r(f.$error,function(b,c){f.$setValidity(c,null,a)});r(f.$$success,function(b,c){f.$setValidity(c,null,a)});$a(g,a);a.$$parentForm=Lb};Ld({ctrl:this,$element:a,set:function(a,b,c){var d=a[b];d?
-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&($a(d,c),0===d.length&&delete a[b])},$animate:c});f.$setDirty=function(){c.removeClass(a,Va);c.addClass(a,Mb);f.$dirty=!0;f.$pristine=!1;f.$$parentForm.$setDirty()};f.$setPristine=function(){c.setClass(a,Va,Mb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;r(g,function(a){a.$setPristine()})};f.$setUntouched=function(){r(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){c.addClass(a,"ng-submitted");
f.$submitted=!0;f.$$parentForm.$setSubmitted()}}function pc(a){a.$formatters.push(function(b){return a.$isEmpty(b)?b:b.toString()})}function lb(a,b,d,c,e,f){var g=M(b[0].type);if(!e.android){var h=!1;b.on("compositionstart",function(){h=!0});b.on("compositionend",function(){h=!1;l()})}var k,l=function(a){k&&(f.defer.cancel(k),k=null);if(!h){var e=b.val();a=a&&a.type;"password"===g||d.ngTrim&&"false"===d.ngTrim||(e=W(e));(c.$viewValue!==e||""===e&&c.$$hasNativeValidators)&&c.$setViewValue(e,a)}};if(e.hasEvent("input"))b.on("input",
l);else{var m=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};b.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))b.on("paste cut",m)}b.on("change",l);if(Md[g]&&c.$$hasNativeValidators&&g===d.type)b.on("keydown wheel mousedown",function(a){if(!k){var b=this.validity,c=b.badInput,d=b.typeMismatch;k=f.defer(function(){k=null;b.badInput===c&&b.typeMismatch===d||l(a)})}});c.$render=function(){var a=c.$isEmpty(c.$viewValue)?
"":c.$viewValue;b.val()!==a&&b.val(a)}}function Nb(a,b){return function(d,c){var e,f;if(ia(d))return d;if(F(d)){'"'==d.charAt(0)&&'"'==d.charAt(d.length-1)&&(d=d.substring(1,d.length-1));if(Bg.test(d))return new Date(d);a.lastIndex=0;if(e=a.exec(d))return e.shift(),f=c?{yyyy:c.getFullYear(),MM:c.getMonth()+1,dd:c.getDate(),HH:c.getHours(),mm:c.getMinutes(),ss:c.getSeconds(),sss:c.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},r(e,function(a,c){c<b.length&&(f[b[c]]=+a)}),new Date(f.yyyy,
f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function mb(a,b,d,c){return function(e,f,g,h,k,l,m){function n(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function p(a){return x(a)&&!ia(a)?d(a)||void 0:a}Nd(e,f,g,h);lb(e,f,g,h,k,l);var s=h&&h.$options&&h.$options.timezone,r;h.$$parserName=a;h.$parsers.push(function(a){if(h.$isEmpty(a))return null;if(b.test(a))return a=d(a,r),s&&(a=Sb(a,s)),a});h.$formatters.push(function(a){if(a&&!ia(a))throw nb("datefmt",a);if(n(a))return(r=a)&&
s&&(r=Sb(r,s,!0)),m("date")(a,c,s);r=null;return""});if(x(g.min)||g.ngMin){var t;h.$validators.min=function(a){return!n(a)||w(t)||d(a)>=t};g.$observe("min",function(a){t=p(a);h.$validate()})}if(x(g.max)||g.ngMax){var q;h.$validators.max=function(a){return!n(a)||w(q)||d(a)<=q};g.$observe("max",function(a){q=p(a);h.$validate()})}}}function Nd(a,b,d,c){(c.$$hasNativeValidators=H(b[0].validity))&&c.$parsers.push(function(a){var c=b.prop("validity")||{};return c.badInput||c.typeMismatch?void 0:a})}function Od(a,
b,d,c,e){if(x(c)){a=a(c);if(!a.constant)throw nb("constexpr",d,c);return a(b)}return e}function qc(a,b){a="ngClass"+a;return["$animate",function(d){function c(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],m=0;m<b.length;m++)if(e==b[m])continue a;c.push(e)}return c}function e(a){var b=[];return J(a)?(r(a,function(a){b=b.concat(e(a))}),b):F(a)?a.split(" "):H(a)?(r(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",link:function(f,g,h){function k(a){a=l(a,1);h.$addClass(a)}
function l(a,b){var c=g.data("$classCounts")||T(),d=[];r(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function m(a,b){var e=c(b,a),f=c(a,b),e=l(e,1),f=l(f,-1);e&&e.length&&d.addClass(g,e);f&&f.length&&d.removeClass(g,f)}function n(a){if(!0===b||(f.$index&1)===b){var c=e(a||[]);if(!p)k(c);else if(!na(a,p)){var d=e(p);m(d,c)}}p=J(a)?a.map(function(a){return ga(a)}):ga(a)}var p;f.$watch(h[a],n,!0);h.$observe("class",function(b){n(f.$eval(h[a]))});
"ngClass"!==a&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var m=e(f.$eval(h[a]));g===b?k(m):(g=l(m,-1),h.$removeClass(g))}})}}}]}function Ld(a){function b(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function d(a,c){a=a?"-"+Cc(a,"-"):"";b(ob+a,!0===c);b(Pd+a,!1===c)}var c=a.ctrl,e=a.$element,f={},g=a.set,h=a.unset,k=a.$animate;f[Pd]=!(f[ob]=e.hasClass(ob));c.$setValidity=function(a,e,f){w(e)?(c.$pending||(c.$pending={}),g(c.$pending,a,f)):(c.$pending&&
h(c.$pending,a,f),Qd(c.$pending)&&(c.$pending=void 0));Ea(e)?e?(h(c.$error,a,f),g(c.$$success,a,f)):(g(c.$error,a,f),h(c.$$success,a,f)):(h(c.$error,a,f),h(c.$$success,a,f));c.$pending?(b(Rd,!0),c.$valid=c.$invalid=void 0,d("",null)):(b(Rd,!1),c.$valid=Qd(c.$error),c.$invalid=!c.$valid,d("",c.$valid));e=c.$pending&&c.$pending[a]?void 0:c.$error[a]?!1:c.$$success[a]?!0:null;d(a,e);c.$$parentForm.$setValidity(a,e,c)}}function Qd(a){if(a)for(var b in a)if(a.hasOwnProperty(b))return!1;return!0}var Cg=
/^\/(.+)\/([a-z]*)$/,sa=Object.prototype.hasOwnProperty,M=function(a){return F(a)?a.toLowerCase():a},ub=function(a){return F(a)?a.toUpperCase():a},Ba,B,pa,ta=[].slice,bg=[].splice,Dg=[].push,ka=Object.prototype.toString,wc=Object.getPrototypeOf,za=O("ng"),ea=E.angular||(E.angular={}),Ub,pb=0;Ba=E.document.documentMode;A.$inject=[];Ya.$inject=[];var J=Array.isArray,be=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/,W=function(a){return F(a)?a.trim():a},xd=
function(a){return a.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},Fa=function(){if(!x(Fa.rules)){var a=E.document.querySelector("[ng-csp]")||E.document.querySelector("[data-ng-csp]");if(a){var b=a.getAttribute("ng-csp")||a.getAttribute("data-ng-csp");Fa.rules={noUnsafeEval:!b||-1!==b.indexOf("no-unsafe-eval"),noInlineStyle:!b||-1!==b.indexOf("no-inline-style")}}else{a=Fa;try{new Function(""),b=!1}catch(d){b=!0}a.rules={noUnsafeEval:b,noInlineStyle:!1}}}return Fa.rules},
rb=function(){if(x(rb.name_))return rb.name_;var a,b,d=Oa.length,c,e;for(b=0;b<d;++b)if(c=Oa[b],a=E.document.querySelector("["+c.replace(":","\\:")+"jq]")){e=a.getAttribute(c+"jq");break}return rb.name_=e},ee=/:/g,Oa=["ng-","data-ng-","ng:","x-ng-"],je=/[A-Z]/g,Dc=!1,Na=3,ne={full:"1.5.7",major:1,minor:5,dot:7,codeName:"hexagonal-circumvolution"};U.expando="ng339";var gb=U.cache={},Pf=1;U._data=function(a){return this.cache[a[this.expando]]||{}};var Kf=/([\:\-\_]+(.))/g,Lf=/^moz([A-Z])/,yb={mouseleave:"mouseout",
mouseenter:"mouseover"},Wb=O("jqLite"),Of=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Vb=/<|&#?\w+;/,Mf=/<([\w:-]+)/,Nf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,ha={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ha.optgroup=ha.option;ha.tbody=ha.tfoot=ha.colgroup=ha.caption=ha.thead;
ha.th=ha.td;var Uf=E.Node.prototype.contains||function(a){return!!(this.compareDocumentPosition(a)&16)},Pa=U.prototype={ready:function(a){function b(){d||(d=!0,a())}var d=!1;"complete"===E.document.readyState?E.setTimeout(b):(this.on("DOMContentLoaded",b),U(E).on("load",b))},toString:function(){var a=[];r(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},eq:function(a){return 0<=a?B(this[a]):B(this[this.length+a])},length:0,push:Dg,sort:[].sort,splice:[].splice},Eb={};r("multiple selected checked disabled readOnly required open".split(" "),
function(a){Eb[M(a)]=a});var Vc={};r("input select option textarea button form details".split(" "),function(a){Vc[a]=!0});var cd={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};r({data:Yb,removeData:fb,hasData:function(a){for(var b in gb[a.ng339])return!0;return!1},cleanData:function(a){for(var b=0,d=a.length;b<d;b++)fb(a[b])}},function(a,b){U[b]=a});r({data:Yb,inheritedData:Cb,scope:function(a){return B.data(a,"$scope")||Cb(a.parentNode||a,["$isolateScope",
"$scope"])},isolateScope:function(a){return B.data(a,"$isolateScope")||B.data(a,"$isolateScopeNoTemplate")},controller:Sc,injector:function(a){return Cb(a,"$injector")},removeAttr:function(a,b){a.removeAttribute(b)},hasClass:zb,css:function(a,b,d){b=eb(b);if(x(d))a.style[b]=d;else return a.style[b]},attr:function(a,b,d){var c=a.nodeType;if(c!==Na&&2!==c&&8!==c)if(c=M(b),Eb[c])if(x(d))d?(a[b]=!0,a.setAttribute(b,c)):(a[b]=!1,a.removeAttribute(c));else return a[b]||(a.attributes.getNamedItem(b)||A).specified?
c:void 0;else if(x(d))a.setAttribute(b,d);else if(a.getAttribute)return a=a.getAttribute(b,2),null===a?void 0:a},prop:function(a,b,d){if(x(d))a[b]=d;else return a[b]},text:function(){function a(a,d){if(w(d)){var c=a.nodeType;return 1===c||c===Na?a.textContent:""}a.textContent=d}a.$dv="";return a}(),val:function(a,b){if(w(b)){if(a.multiple&&"select"===ua(a)){var d=[];r(a.options,function(a){a.selected&&d.push(a.value||a.text)});return 0===d.length?null:d}return a.value}a.value=b},html:function(a,b){if(w(b))return a.innerHTML;
wb(a,!0);a.innerHTML=b},empty:Tc},function(a,b){U.prototype[b]=function(b,c){var e,f,g=this.length;if(a!==Tc&&w(2==a.length&&a!==zb&&a!==Sc?b:c)){if(H(b)){for(e=0;e<g;e++)if(a===Yb)a(this[e],b);else for(f in b)a(this[e],f,b[f]);return this}e=a.$dv;g=w(e)?Math.min(g,1):g;for(f=0;f<g;f++){var h=a(this[f],b,c);e=e?e+h:h}return e}for(e=0;e<g;e++)a(this[e],b,c);return this}});r({removeData:fb,on:function(a,b,d,c){if(x(c))throw Wb("onargs");if(Nc(a)){c=xb(a,!0);var e=c.events,f=c.handle;f||(f=c.handle=
Rf(a,e));c=0<=b.indexOf(" ")?b.split(" "):[b];for(var g=c.length,h=function(b,c,g){var h=e[b];h||(h=e[b]=[],h.specialHandlerWrapper=c,"$destroy"===b||g||a.addEventListener(b,f,!1));h.push(d)};g--;)b=c[g],yb[b]?(h(yb[b],Tf),h(b,void 0,!0)):h(b)}},off:Rc,one:function(a,b,d){a=B(a);a.on(b,function e(){a.off(b,d);a.off(b,e)});a.on(b,d)},replaceWith:function(a,b){var d,c=a.parentNode;wb(a);r(new U(b),function(b){d?c.insertBefore(b,d.nextSibling):c.replaceChild(b,a);d=b})},children:function(a){var b=[];
r(a.childNodes,function(a){1===a.nodeType&&b.push(a)});return b},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,b){var d=a.nodeType;if(1===d||11===d){b=new U(b);for(var d=0,c=b.length;d<c;d++)a.appendChild(b[d])}},prepend:function(a,b){if(1===a.nodeType){var d=a.firstChild;r(new U(b),function(b){a.insertBefore(b,d)})}},wrap:function(a,b){Pc(a,B(b).eq(0).clone()[0])},remove:Db,detach:function(a){Db(a,!0)},after:function(a,b){var d=a,c=a.parentNode;b=new U(b);for(var e=
0,f=b.length;e<f;e++){var g=b[e];c.insertBefore(g,d.nextSibling);d=g}},addClass:Bb,removeClass:Ab,toggleClass:function(a,b,d){b&&r(b.split(" "),function(b){var e=d;w(e)&&(e=!zb(a,b));(e?Bb:Ab)(a,b)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,b){return a.getElementsByTagName?a.getElementsByTagName(b):[]},clone:Xb,triggerHandler:function(a,b,d){var c,e,f=b.type||b,g=xb(a);if(g=(g=g&&g.events)&&g[f])c={preventDefault:function(){this.defaultPrevented=
!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:A,type:f,target:a},b.type&&(c=R(c,b)),b=ga(g),e=d?[c].concat(d):[c],r(b,function(b){c.isImmediatePropagationStopped()||b.apply(a,e)})}},function(a,b){U.prototype[b]=function(b,c,e){for(var f,g=0,h=this.length;g<h;g++)w(f)?(f=a(this[g],b,c,e),x(f)&&(f=B(f))):
Qc(f,a(this[g],b,c,e));return x(f)?f:this};U.prototype.bind=U.prototype.on;U.prototype.unbind=U.prototype.off});Sa.prototype={put:function(a,b){this[Ga(a,this.nextUid)]=b},get:function(a){return this[Ga(a,this.nextUid)]},remove:function(a){var b=this[a=Ga(a,this.nextUid)];delete this[a];return b}};var If=[function(){this.$get=[function(){return Sa}]}],Wf=/^([^\(]+?)=>/,Xf=/^[^\(]*\(\s*([^\)]*)\)/m,Eg=/,/,Fg=/^\s*(_?)(\S+?)\1\s*$/,Vf=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ha=O("$injector");db.$$annotate=
function(a,b,d){var c;if("function"===typeof a){if(!(c=a.$inject)){c=[];if(a.length){if(b)throw F(d)&&d||(d=a.name||Yf(a)),Ha("strictdi",d);b=Wc(a);r(b[1].split(Eg),function(a){a.replace(Fg,function(a,b,d){c.push(d)})})}a.$inject=c}}else J(a)?(b=a.length-1,Qa(a[b],"fn"),c=a.slice(0,b)):Qa(a,"fn",!0);return c};var Sd=O("$animate"),af=function(){this.$get=A},bf=function(){var a=new Sa,b=[];this.$get=["$$AnimateRunner","$rootScope",function(d,c){function e(a,b,c){var d=!1;b&&(b=F(b)?b.split(" "):J(b)?
b:[],r(b,function(b){b&&(d=!0,a[b]=c)}));return d}function f(){r(b,function(b){var c=a.get(b);if(c){var d=Zf(b.attr("class")),e="",f="";r(c,function(a,b){a!==!!d[b]&&(a?e+=(e.length?" ":"")+b:f+=(f.length?" ":"")+b)});r(b,function(a){e&&Bb(a,e);f&&Ab(a,f)});a.remove(b)}});b.length=0}return{enabled:A,on:A,off:A,pin:A,push:function(g,h,k,l){l&&l();k=k||{};k.from&&g.css(k.from);k.to&&g.css(k.to);if(k.addClass||k.removeClass)if(h=k.addClass,l=k.removeClass,k=a.get(g)||{},h=e(k,h,!0),l=e(k,l,!1),h||l)a.put(g,
k),b.push(g),1===b.length&&c.$$postDigest(f);g=new d;g.complete();return g}}}]},Ze=["$provide",function(a){var b=this;this.$$registeredAnimations=Object.create(null);this.register=function(d,c){if(d&&"."!==d.charAt(0))throw Sd("notcsel",d);var e=d+"-animation";b.$$registeredAnimations[d.substr(1)]=e;a.factory(e,c)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Sd("nongcls",
"ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function b(a,c,d){if(d){var h;a:{for(h=0;h<d.length;h++){var k=d[h];if(1===k.nodeType){h=k;break a}}h=void 0}!h||h.parentNode||h.previousElementSibling||(d=null)}d?d.after(a):c.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(e,f,g,h){f=f&&B(f);g=g&&B(g);f=f||g.parent();b(e,f,g);return a.push(e,"enter",Ia(h))},move:function(e,f,g,h){f=f&&B(f);g=g&&B(g);
f=f||g.parent();b(e,f,g);return a.push(e,"move",Ia(h))},leave:function(b,c){return a.push(b,"leave",Ia(c),function(){b.remove()})},addClass:function(b,c,g){g=Ia(g);g.addClass=hb(g.addclass,c);return a.push(b,"addClass",g)},removeClass:function(b,c,g){g=Ia(g);g.removeClass=hb(g.removeClass,c);return a.push(b,"removeClass",g)},setClass:function(b,c,g,h){h=Ia(h);h.addClass=hb(h.addClass,c);h.removeClass=hb(h.removeClass,g);return a.push(b,"setClass",h)},animate:function(b,c,g,h,k){k=Ia(k);k.from=k.from?
R(k.from,c):c;k.to=k.to?R(k.to,g):g;k.tempClasses=hb(k.tempClasses,h||"ng-inline-animate");return a.push(b,"animate",k)}}}]}],df=function(){this.$get=["$$rAF",function(a){function b(b){d.push(b);1<d.length||a(function(){for(var a=0;a<d.length;a++)d[a]();d=[]})}var d=[];return function(){var a=!1;b(function(){a=!0});return function(d){a?d():b(d)}}}]},cf=function(){this.$get=["$q","$sniffer","$$animateAsyncRun","$document","$timeout",function(a,b,d,c,e){function f(a){this.setHost(a);var b=d();this._doneCallbacks=
[];this._tick=function(a){var d=c[0];d&&d.hidden?e(a,0,!1):b(a)};this._state=0}f.chain=function(a,b){function c(){if(d===a.length)b(!0);else a[d](function(a){!1===a?b(!1):(d++,c())})}var d=0;c()};f.all=function(a,b){function c(f){e=e&&f;++d===a.length&&b(e)}var d=0,e=!0;r(a,function(a){a.done(c)})};f.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===this._state?a():this._doneCallbacks.push(a)},progress:A,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,
c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&&this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end();this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=
this;0===b._state&&(b._state=1,b._tick(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(r(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=0,this._state=2)}};return f}]},$e=function(){this.$get=["$$rAF","$q","$$AnimateRunner",function(a,b,d){return function(b,e){function f(){a(function(){g.addClass&&(b.addClass(g.addClass),g.addClass=null);g.removeClass&&(b.removeClass(g.removeClass),g.removeClass=null);g.to&&(b.css(g.to),g.to=null);h||k.complete();h=!0});return k}
var g=e||{};g.$$prepared||(g=Z(g));g.cleanupStyles&&(g.from=g.to=null);g.from&&(b.css(g.from),g.from=null);var h,k=new d;return{start:f,end:f}}}]},fa=O("$compile"),bc=new function(){};Fc.$inject=["$provide","$$sanitizeUriProvider"];Fb.prototype.isFirstChange=function(){return this.previousValue===bc};var Yc=/^((?:x|data)[\:\-_])/i,cg=O("$controller"),dd=/^(\S+)(\s+as\s+([\w$]+))?$/,kf=function(){this.$get=["$document",function(a){return function(b){b?!b.nodeType&&b instanceof B&&(b=b[0]):b=a[0].body;
return b.offsetWidth+1}}]},ed="application/json",ec={"Content-Type":ed+";charset=utf-8"},eg=/^\[|^\{(?!\{)/,fg={"[":/]$/,"{":/}$/},dg=/^\)\]\}',?\n/,Gg=O("$http"),id=function(a){return function(){throw Gg("legacy",a);}},Ka=ea.$interpolateMinErr=O("$interpolate");Ka.throwNoconcat=function(a){throw Ka("noconcat",a);};Ka.interr=function(a,b){return Ka("interr",a,b.toString())};var Hg=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,hg={http:80,https:443,ftp:21},Gb=O("$location"),Ig={$$absUrl:"",$$html5:!1,$$replace:!1,
absUrl:Hb("$$absUrl"),url:function(a){if(w(a))return this.$$url;var b=Hg.exec(a);(b[1]||""===a)&&this.path(decodeURIComponent(b[1]));(b[2]||b[1]||""===a)&&this.search(b[3]||"");this.hash(b[5]||"");return this},protocol:Hb("$$protocol"),host:Hb("$$host"),port:Hb("$$port"),path:nd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,b){switch(arguments.length){case 0:return this.$$search;case 1:if(F(a)||S(a))a=a.toString(),this.$$search=Ac(a);else if(H(a))a=
Z(a,{}),r(a,function(b,c){null==b&&delete a[c]}),this.$$search=a;else throw Gb("isrcharg");break;default:w(b)||null===b?delete this.$$search[a]:this.$$search[a]=b}this.$$compose();return this},hash:nd("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};r([md,hc,gc],function(a){a.prototype=Object.create(Ig);a.prototype.state=function(b){if(!arguments.length)return this.$$state;if(a!==gc||!this.$$html5)throw Gb("nostate");this.$$state=w(b)?null:
b;return this}});var ca=O("$parse"),jg=Function.prototype.call,kg=Function.prototype.apply,lg=Function.prototype.bind,Ob=T();r("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Ob[a]=!0});var Jg={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},jc=function(a){this.options=a};jc.prototype={constructor:jc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||
"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdentifierStart(this.peekMultichar()))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var b=a+this.peek(),d=b+this.peek(2),c=Ob[b],e=Ob[d];Ob[a]||c||e?(a=e?d:c?b:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},
is:function(a,b){return-1!==b.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdentifierStart:function(a){return this.options.isIdentifierStart?this.options.isIdentifierStart(a,this.codePointAt(a)):this.isValidIdentifierStart(a)},isValidIdentifierStart:function(a){return"a"<=a&&"z">=
a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isIdentifierContinue:function(a){return this.options.isIdentifierContinue?this.options.isIdentifierContinue(a,this.codePointAt(a)):this.isValidIdentifierContinue(a)},isValidIdentifierContinue:function(a,b){return this.isValidIdentifierStart(a,b)||this.isNumber(a)},codePointAt:function(a){return 1===a.length?a.charCodeAt(0):(a.charCodeAt(0)<<10)+a.charCodeAt(1)-56613888},peekMultichar:function(){var a=this.text.charAt(this.index),b=this.peek();if(!b)return a;var d=
a.charCodeAt(0),c=b.charCodeAt(0);return 55296<=d&&56319>=d&&56320<=c&&57343>=c?a+b:a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,b,d){d=d||this.index;b=x(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,d)+"]":" "+d;throw ca("lexerr",a,b,this.text);},readNumber:function(){for(var a="",b=this.index;this.index<this.text.length;){var d=M(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var c=this.peek();if("e"==d&&this.isExpOperator(c))a+=
d;else if(this.isExpOperator(d)&&c&&this.isNumber(c)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||c&&this.isNumber(c)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:b,text:a,constant:!0,value:Number(a)})},readIdent:function(){var a=this.index;for(this.index+=this.peekMultichar().length;this.index<this.text.length;){var b=this.peekMultichar();if(!this.isIdentifierContinue(b))break;this.index+=b.length}this.tokens.push({index:a,
text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var b=this.index;this.index++;for(var d="",c=a,e=!1;this.index<this.text.length;){var f=this.text.charAt(this.index),c=c+f;if(e)"u"===f?(e=this.text.substring(this.index+1,this.index+5),e.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+e+"]"),this.index+=4,d+=String.fromCharCode(parseInt(e,16))):d+=Jg[f]||f,e=!1;else if("\\"===f)e=!0;else{if(f===a){this.index++;this.tokens.push({index:b,text:c,constant:!0,
value:d});return}d+=f}this.index++}this.throwError("Unterminated quote",b)}};var t=function(a,b){this.lexer=a;this.options=b};t.Program="Program";t.ExpressionStatement="ExpressionStatement";t.AssignmentExpression="AssignmentExpression";t.ConditionalExpression="ConditionalExpression";t.LogicalExpression="LogicalExpression";t.BinaryExpression="BinaryExpression";t.UnaryExpression="UnaryExpression";t.CallExpression="CallExpression";t.MemberExpression="MemberExpression";t.Identifier="Identifier";t.Literal=
"Literal";t.ArrayExpression="ArrayExpression";t.Property="Property";t.ObjectExpression="ObjectExpression";t.ThisExpression="ThisExpression";t.LocalsExpression="LocalsExpression";t.NGValueParameter="NGValueParameter";t.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),
!this.expect(";"))return{type:t.Program,body:a}},expressionStatement:function(){return{type:t.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:t.AssignmentExpression,left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),b,d;return this.expect("?")&&
(b=this.expression(),this.consume(":"))?(d=this.expression(),{type:t.ConditionalExpression,test:a,alternate:b,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:t.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:t.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),b;b=this.expect("==","!=",
"===","!==");)a={type:t.BinaryExpression,operator:b.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),b;b=this.expect("<",">","<=",">=");)a={type:t.BinaryExpression,operator:b.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),b;b=this.expect("+","-");)a={type:t.BinaryExpression,operator:b.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),b;b=this.expect("*",
"/","%");)a={type:t.BinaryExpression,operator:b.text,left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:t.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.selfReferential.hasOwnProperty(this.peek().text)?a=Z(this.selfReferential[this.consume().text]):this.options.literals.hasOwnProperty(this.peek().text)?
a={type:t.Literal,value:this.options.literals[this.consume().text]}:this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:t.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===b.text?(a={type:t.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:t.MemberExpression,object:a,
property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var b={type:t.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.filterChain());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:t.Identifier,name:a.text}},
constant:function(){return{type:t.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:t.ArrayExpression,elements:a}},object:function(){var a=[],b;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;b={type:t.Property,kind:"init"};this.peek().constant?(b.key=this.constant(),b.computed=!1,this.consume(":"),b.value=this.expression()):
this.peek().identifier?(b.key=this.identifier(),b.computed=!1,this.peek(":")?(this.consume(":"),b.value=this.expression()):b.value=b.key):this.peek("[")?(this.consume("["),b.key=this.expression(),this.consume("]"),b.computed=!0,this.consume(":"),b.value=this.expression()):this.throwError("invalid key",this.peek());a.push(b)}while(this.expect(","))}this.consume("}");return{type:t.ObjectExpression,properties:a}},throwError:function(a,b){throw ca("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index));
},consume:function(a){if(0===this.tokens.length)throw ca("ueoe",this.text);var b=this.expect(a);b||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return b},peekToken:function(){if(0===this.tokens.length)throw ca("ueoe",this.text);return this.tokens[0]},peek:function(a,b,d,c){return this.peekAhead(0,a,b,d,c)},peekAhead:function(a,b,d,c,e){if(this.tokens.length>a){a=this.tokens[a];var f=a.text;if(f===b||f===d||f===c||f===e||!(b||d||c||e))return a}return!1},expect:function(a,b,d,c){return(a=
this.peek(a,b,d,c))?(this.tokens.shift(),a):!1},selfReferential:{"this":{type:t.ThisExpression},$locals:{type:t.LocalsExpression}}};ud.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:b,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};$(c,d.$filter);var e="",f;this.stage="assign";if(f=sd(c))this.state.computing="assign",e=this.nextId(),this.recurse(f,e),this.return_(e),e="fn.assign="+this.generateFunction("assign",
"s,v,l");f=qd(c.body);d.stage="inputs";r(f,function(a,b){var c="fn"+b;d.state[c]={vars:[],body:[],own:{}};d.state.computing=c;var e=d.nextId();d.recurse(a,e);d.return_(e);d.state.inputs.push(c);a.watchId=b});this.state.computing="fn";this.stage="main";this.recurse(c);e='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+e+this.watchFns()+"return fn;";e=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue",
"ensureSafeAssignContext","ifDefined","plus","text",e))(this.$filter,Ua,ra,od,ig,Ib,mg,pd,a);this.state=this.stage=void 0;e.literal=td(c);e.constant=c.constant;return e},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,d=this;r(b,function(b){a.push("var "+b+"="+d.generateFunction(b,"s"))});b.length&&a.push("fn.inputs=["+b.join(",")+"];");return a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=
[],b=this;r(this.state.filters,function(d,c){a.push(d+"=$filter("+b.escape(c)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,b,d,c,e,f){var g,h,k=this,l,m,n;c=c||A;if(!f&&x(a.watchId))b=b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,c,e,!0));else switch(a.type){case t.Program:r(a.body,
function(b,c){k.recurse(b.expression,void 0,void 0,function(a){h=a});c!==a.body.length-1?k.current().body.push(h,";"):k.return_(h)});break;case t.Literal:m=this.escape(a.value);this.assign(b,m);c(m);break;case t.UnaryExpression:this.recurse(a.argument,void 0,void 0,function(a){h=a});m=a.operator+"("+this.ifDefined(h,0)+")";this.assign(b,m);c(m);break;case t.BinaryExpression:this.recurse(a.left,void 0,void 0,function(a){g=a});this.recurse(a.right,void 0,void 0,function(a){h=a});m="+"===a.operator?
this.plus(g,h):"-"===a.operator?this.ifDefined(g,0)+a.operator+this.ifDefined(h,0):"("+g+")"+a.operator+"("+h+")";this.assign(b,m);c(m);break;case t.LogicalExpression:b=b||this.nextId();k.recurse(a.left,b);k.if_("&&"===a.operator?b:k.not(b),k.lazyRecurse(a.right,b));c(b);break;case t.ConditionalExpression:b=b||this.nextId();k.recurse(a.test,b);k.if_(b,k.lazyRecurse(a.alternate,b),k.lazyRecurse(a.consequent,b));c(b);break;case t.Identifier:b=b||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),
this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Ua(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){e&&1!==e&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(b,k.nonComputedMember("s",a.name))})},b&&k.lazyAssign(b,k.nonComputedMember("l",a.name)));(k.state.expensiveChecks||Jb(a.name))&&k.addEnsureSafeObject(b);c(b);break;case t.MemberExpression:g=
d&&(d.context=this.nextId())||this.nextId();b=b||this.nextId();k.recurse(a.object,g,void 0,function(){k.if_(k.notNull(g),function(){e&&1!==e&&k.addEnsureSafeAssignContext(g);if(a.computed)h=k.nextId(),k.recurse(a.property,h),k.getStringValue(h),k.addEnsureSafeMemberName(h),e&&1!==e&&k.if_(k.not(k.computedMember(g,h)),k.lazyAssign(k.computedMember(g,h),"{}")),m=k.ensureSafeObject(k.computedMember(g,h)),k.assign(b,m),d&&(d.computed=!0,d.name=h);else{Ua(a.property.name);e&&1!==e&&k.if_(k.not(k.nonComputedMember(g,
a.property.name)),k.lazyAssign(k.nonComputedMember(g,a.property.name),"{}"));m=k.nonComputedMember(g,a.property.name);if(k.state.expensiveChecks||Jb(a.property.name))m=k.ensureSafeObject(m);k.assign(b,m);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(b,"undefined")});c(b)},!!e);break;case t.CallExpression:b=b||this.nextId();a.filter?(h=k.filter(a.callee.name),l=[],r(a.arguments,function(a){var b=k.nextId();k.recurse(a,b);l.push(b)}),m=h+"("+l.join(",")+")",k.assign(b,m),c(b)):(h=
k.nextId(),g={},l=[],k.recurse(a.callee,h,g,function(){k.if_(k.notNull(h),function(){k.addEnsureSafeFunction(h);r(a.arguments,function(a){k.recurse(a,k.nextId(),void 0,function(a){l.push(k.ensureSafeObject(a))})});g.name?(k.state.expensiveChecks||k.addEnsureSafeObject(g.context),m=k.member(g.context,g.name,g.computed)+"("+l.join(",")+")"):m=h+"("+l.join(",")+")";m=k.ensureSafeObject(m);k.assign(b,m)},function(){k.assign(b,"undefined")});c(b)}));break;case t.AssignmentExpression:h=this.nextId();g=
{};if(!rd(a.left))throw ca("lval");this.recurse(a.left,void 0,g,function(){k.if_(k.notNull(g.context),function(){k.recurse(a.right,h);k.addEnsureSafeObject(k.member(g.context,g.name,g.computed));k.addEnsureSafeAssignContext(g.context);m=k.member(g.context,g.name,g.computed)+a.operator+h;k.assign(b,m);c(b||m)})},1);break;case t.ArrayExpression:l=[];r(a.elements,function(a){k.recurse(a,k.nextId(),void 0,function(a){l.push(a)})});m="["+l.join(",")+"]";this.assign(b,m);c(m);break;case t.ObjectExpression:l=
[];n=!1;r(a.properties,function(a){a.computed&&(n=!0)});n?(b=b||this.nextId(),this.assign(b,"{}"),r(a.properties,function(a){a.computed?(g=k.nextId(),k.recurse(a.key,g)):g=a.key.type===t.Identifier?a.key.name:""+a.key.value;h=k.nextId();k.recurse(a.value,h);k.assign(k.member(b,g,a.computed),h)})):(r(a.properties,function(b){k.recurse(b.value,a.constant?void 0:k.nextId(),void 0,function(a){l.push(k.escape(b.key.type===t.Identifier?b.key.name:""+b.key.value)+":"+a)})}),m="{"+l.join(",")+"}",this.assign(b,
m));c(b||m);break;case t.ThisExpression:this.assign(b,"s");c("s");break;case t.LocalsExpression:this.assign(b,"l");c("l");break;case t.NGValueParameter:this.assign(b,"v"),c("v")}},getHasOwnProperty:function(a,b){var d=a+"."+b,c=this.current().own;c.hasOwnProperty(d)||(c[d]=this.nextId(!1,a+"&&("+this.escape(b)+" in "+a+")"));return c[d]},assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));
return this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,b,d){if(!0===a)b();else{var c=this.current().body;c.push("if(",a,"){");b();c.push("}");d&&(c.push("else{"),d(),c.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){var d=/[^$_a-zA-Z0-9]/g;return/[$_a-zA-Z][$_a-zA-Z0-9]*/.test(b)?
a+"."+b:a+'["'+b.replace(d,this.stringEscapeFn)+'"]'},computedMember:function(a,b){return a+"["+b+"]"},member:function(a,b,d){return d?this.computedMember(a,b):this.nonComputedMember(a,b)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},addEnsureSafeAssignContext:function(a){this.current().body.push(this.ensureSafeAssignContext(a),
";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},getStringValue:function(a){this.assign(a,"getStringValue("+a+")")},ensureSafeAssignContext:function(a){return"ensureSafeAssignContext("+a+",text)"},lazyRecurse:function(a,b,d,c,e,f){var g=this;return function(){g.recurse(a,b,d,c,e,f)}},lazyAssign:function(a,b){var d=this;return function(){d.assign(a,
b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(F(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(S(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw ca("esc");},nextId:function(a,b){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(b?"="+b:""));return d},current:function(){return this.state[this.state.computing]}};
vd.prototype={compile:function(a,b){var d=this,c=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=b;$(c,d.$filter);var e,f;if(e=sd(c))f=this.recurse(e);e=qd(c.body);var g;e&&(g=[],r(e,function(a,b){var c=d.recurse(a);a.input=c;g.push(c);a.watchId=b}));var h=[];r(c.body,function(a){h.push(d.recurse(a.expression))});e=0===c.body.length?A:1===c.body.length?h[0]:function(a,b){var c;r(h,function(d){c=d(a,b)});return c};f&&(e.assign=function(a,b,c){return f(a,c,b)});g&&(e.inputs=g);e.literal=
td(c);e.constant=c.constant;return e},recurse:function(a,b,d){var c,e,f=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case t.Literal:return this.value(a.value,b);case t.UnaryExpression:return e=this.recurse(a.argument),this["unary"+a.operator](e,b);case t.BinaryExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case t.LogicalExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case t.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),
this.recurse(a.alternate),this.recurse(a.consequent),b);case t.Identifier:return Ua(a.name,f.expression),f.identifier(a.name,f.expensiveChecks||Jb(a.name),b,d,f.expression);case t.MemberExpression:return c=this.recurse(a.object,!1,!!d),a.computed||(Ua(a.property.name,f.expression),e=a.property.name),a.computed&&(e=this.recurse(a.property)),a.computed?this.computedMember(c,e,b,d,f.expression):this.nonComputedMember(c,e,f.expensiveChecks,b,d,f.expression);case t.CallExpression:return g=[],r(a.arguments,
function(a){g.push(f.recurse(a))}),a.filter&&(e=this.$filter(a.callee.name)),a.filter||(e=this.recurse(a.callee,!0)),a.filter?function(a,c,d,f){for(var n=[],p=0;p<g.length;++p)n.push(g[p](a,c,d,f));a=e.apply(void 0,n,f);return b?{context:void 0,name:void 0,value:a}:a}:function(a,c,d,m){var n=e(a,c,d,m),p;if(null!=n.value){ra(n.context,f.expression);od(n.value,f.expression);p=[];for(var s=0;s<g.length;++s)p.push(ra(g[s](a,c,d,m),f.expression));p=ra(n.value.apply(n.context,p),f.expression)}return b?
{value:p}:p};case t.AssignmentExpression:return c=this.recurse(a.left,!0,1),e=this.recurse(a.right),function(a,d,g,m){var n=c(a,d,g,m);a=e(a,d,g,m);ra(n.value,f.expression);Ib(n.context);n.context[n.name]=a;return b?{value:a}:a};case t.ArrayExpression:return g=[],r(a.elements,function(a){g.push(f.recurse(a))}),function(a,c,d,e){for(var f=[],p=0;p<g.length;++p)f.push(g[p](a,c,d,e));return b?{value:f}:f};case t.ObjectExpression:return g=[],r(a.properties,function(a){a.computed?g.push({key:f.recurse(a.key),
computed:!0,value:f.recurse(a.value)}):g.push({key:a.key.type===t.Identifier?a.key.name:""+a.key.value,computed:!1,value:f.recurse(a.value)})}),function(a,c,d,e){for(var f={},p=0;p<g.length;++p)g[p].computed?f[g[p].key(a,c,d,e)]=g[p].value(a,c,d,e):f[g[p].key]=g[p].value(a,c,d,e);return b?{value:f}:f};case t.ThisExpression:return function(a){return b?{value:a}:a};case t.LocalsExpression:return function(a,c){return b?{value:c}:c};case t.NGValueParameter:return function(a,c,d){return b?{value:d}:d}}},
"unary+":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=x(d)?+d:0;return b?{value:d}:d}},"unary-":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=x(d)?-d:0;return b?{value:d}:d}},"unary!":function(a,b){return function(d,c,e,f){d=!a(d,c,e,f);return b?{value:d}:d}},"binary+":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);h=pd(h,c);return d?{value:h}:h}},"binary-":function(a,b,d){return function(c,e,f,g){var h=a(c,e,f,g);c=b(c,e,f,g);h=(x(h)?h:0)-(x(c)?c:0);return d?
{value:h}:h}},"binary*":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)*b(c,e,f,g);return d?{value:c}:c}},"binary/":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)/b(c,e,f,g);return d?{value:c}:c}},"binary%":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)%b(c,e,f,g);return d?{value:c}:c}},"binary===":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)===b(c,e,f,g);return d?{value:c}:c}},"binary!==":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!==b(c,e,f,g);return d?{value:c}:
c}},"binary==":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)==b(c,e,f,g);return d?{value:c}:c}},"binary!=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!=b(c,e,f,g);return d?{value:c}:c}},"binary<":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<b(c,e,f,g);return d?{value:c}:c}},"binary>":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>b(c,e,f,g);return d?{value:c}:c}},"binary<=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<=b(c,e,f,g);return d?{value:c}:c}},"binary>=":function(a,
b,d){return function(c,e,f,g){c=a(c,e,f,g)>=b(c,e,f,g);return d?{value:c}:c}},"binary&&":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)&&b(c,e,f,g);return d?{value:c}:c}},"binary||":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)||b(c,e,f,g);return d?{value:c}:c}},"ternary?:":function(a,b,d,c){return function(e,f,g,h){e=a(e,f,g,h)?b(e,f,g,h):d(e,f,g,h);return c?{value:e}:e}},value:function(a,b){return function(){return b?{context:void 0,name:void 0,value:a}:a}},identifier:function(a,
b,d,c,e){return function(f,g,h,k){f=g&&a in g?g:f;c&&1!==c&&f&&!f[a]&&(f[a]={});g=f?f[a]:void 0;b&&ra(g,e);return d?{context:f,name:a,value:g}:g}},computedMember:function(a,b,d,c,e){return function(f,g,h,k){var l=a(f,g,h,k),m,n;null!=l&&(m=b(f,g,h,k),m+="",Ua(m,e),c&&1!==c&&(Ib(l),l&&!l[m]&&(l[m]={})),n=l[m],ra(n,e));return d?{context:l,name:m,value:n}:n}},nonComputedMember:function(a,b,d,c,e,f){return function(g,h,k,l){g=a(g,h,k,l);e&&1!==e&&(Ib(g),g&&!g[b]&&(g[b]={}));h=null!=g?g[b]:void 0;(d||
Jb(b))&&ra(h,f);return c?{context:g,name:b,value:h}:h}},inputs:function(a,b){return function(d,c,e,f){return f?f[b]:a(d,c,e)}}};var kc=function(a,b,d){this.lexer=a;this.$filter=b;this.options=d;this.ast=new t(a,d);this.astCompiler=d.csp?new vd(this.ast,b):new ud(this.ast,b)};kc.prototype={constructor:kc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};var ng=Object.prototype.valueOf,ya=O("$sce"),ma={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},
pg=O("$compile"),Y=E.document.createElement("a"),zd=qa(E.location.href);Ad.$inject=["$document"];Mc.$inject=["$provide"];var Hd=22,Gd=".",mc="0";Bd.$inject=["$locale"];Dd.$inject=["$locale"];var Ag={yyyy:X("FullYear",4,0,!1,!0),yy:X("FullYear",2,0,!0,!0),y:X("FullYear",1,0,!1,!0),MMMM:kb("Month"),MMM:kb("Month",!0),MM:X("Month",2,1),M:X("Month",1,1),LLLL:kb("Month",!1,!0),dd:X("Date",2),d:X("Date",1),HH:X("Hours",2),H:X("Hours",1),hh:X("Hours",2,-12),h:X("Hours",1,-12),mm:X("Minutes",2),m:X("Minutes",
1),ss:X("Seconds",2),s:X("Seconds",1),sss:X("Milliseconds",3),EEEE:kb("Day"),EEE:kb("Day",!0),a:function(a,b){return 12>a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,d){a=-1*d;return a=(0<=a?"+":"")+(Kb(Math[0<a?"floor":"ceil"](a/60),2)+Kb(Math.abs(a%60),2))},ww:Jd(2),w:Jd(1),G:nc,GG:nc,GGG:nc,GGGG:function(a,b){return 0>=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},zg=/((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,yg=/^\-?\d+$/;Cd.$inject=["$locale"];
var tg=da(M),ug=da(ub);Ed.$inject=["$parse"];var pe=da({restrict:"E",compile:function(a,b){if(!b.href&&!b.xlinkHref)return function(a,b){if("a"===b[0].nodeName.toLowerCase()){var e="[object SVGAnimatedString]"===ka.call(b.prop("href"))?"xlink:href":"href";b.on("click",function(a){b.attr(e)||a.preventDefault()})}}}}),vb={};r(Eb,function(a,b){function d(a,d,e){a.$watch(e[c],function(a){e.$set(b,!!a)})}if("multiple"!=a){var c=xa("ng-"+b),e=d;"checked"===a&&(e=function(a,b,e){e.ngModel!==e[c]&&d(a,b,
e)});vb[c]=function(){return{restrict:"A",priority:100,link:e}}}});r(cd,function(a,b){vb[b]=function(){return{priority:100,link:function(a,c,e){if("ngPattern"===b&&"/"==e.ngPattern.charAt(0)&&(c=e.ngPattern.match(Cg))){e.$set("ngPattern",new RegExp(c[1],c[2]));return}a.$watch(e[b],function(a){e.$set(b,a)})}}}});r(["src","srcset","href"],function(a){var b=xa("ng-"+a);vb[b]=function(){return{priority:99,link:function(d,c,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===ka.call(c.prop("href"))&&
(g="xlinkHref",e.$attr[g]="xlink:href",f=null);e.$observe(b,function(b){b?(e.$set(g,b),Ba&&f&&c.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});var Lb={$addControl:A,$$renameControl:function(a,b){a.$name=b},$removeControl:A,$setValidity:A,$setDirty:A,$setPristine:A,$setSubmitted:A};Kd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Td=function(a){return["$timeout","$parse",function(b,d){function c(a){return""===a?d('this[""]').assign:d(a).assign||A}return{name:"form",restrict:a?
"EAC":"E",require:["form","^^?form"],controller:Kd,compile:function(d,f){d.addClass(Va).addClass(ob);var g=f.name?"name":a&&f.ngForm?"ngForm":!1;return{pre:function(a,d,e,f){var n=f[0];if(!("action"in e)){var p=function(b){a.$apply(function(){n.$commitViewValue();n.$setSubmitted()});b.preventDefault()};d[0].addEventListener("submit",p,!1);d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",p,!1)},0,!1)})}(f[1]||n.$$parentForm).$addControl(n);var s=g?c(n.$name):A;g&&(s(a,n),e.$observe(g,
function(b){n.$name!==b&&(s(a,void 0),n.$$parentForm.$$renameControl(n,b),s=c(n.$name),s(a,n))}));d.on("$destroy",function(){n.$$parentForm.$removeControl(n);s(a,void 0);R(n,Lb)})}}}}}]},qe=Td(),De=Td(!0),Bg=/^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/,Kg=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,Lg=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,
Mg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Ud=/^(\d{4,})-(\d{2})-(\d{2})$/,Vd=/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,rc=/^(\d{4,})-W(\d\d)$/,Wd=/^(\d{4,})-(\d\d)$/,Xd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Md=T();r(["date","datetime-local","month","time","week"],function(a){Md[a]=!0});var Yd={text:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c)},date:mb("date",Ud,Nb(Ud,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":mb("datetimelocal",Vd,Nb(Vd,"yyyy MM dd HH mm ss sss".split(" ")),
"yyyy-MM-ddTHH:mm:ss.sss"),time:mb("time",Xd,Nb(Xd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:mb("week",rc,function(a,b){if(ia(a))return a;if(F(a)){rc.lastIndex=0;var d=rc.exec(a);if(d){var c=+d[1],e=+d[2],f=d=0,g=0,h=0,k=Id(c),e=7*(e-1);b&&(d=b.getHours(),f=b.getMinutes(),g=b.getSeconds(),h=b.getMilliseconds());return new Date(c,0,k.getDate()+e,d,f,g,h)}}return NaN},"yyyy-Www"),month:mb("month",Wd,Nb(Wd,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,c,e,f){Nd(a,b,d,c);lb(a,b,d,c,e,f);c.$$parserName=
"number";c.$parsers.push(function(a){if(c.$isEmpty(a))return null;if(Mg.test(a))return parseFloat(a)});c.$formatters.push(function(a){if(!c.$isEmpty(a)){if(!S(a))throw nb("numfmt",a);a=a.toString()}return a});if(x(d.min)||d.ngMin){var g;c.$validators.min=function(a){return c.$isEmpty(a)||w(g)||a>=g};d.$observe("min",function(a){x(a)&&!S(a)&&(a=parseFloat(a,10));g=S(a)&&!isNaN(a)?a:void 0;c.$validate()})}if(x(d.max)||d.ngMax){var h;c.$validators.max=function(a){return c.$isEmpty(a)||w(h)||a<=h};d.$observe("max",
function(a){x(a)&&!S(a)&&(a=parseFloat(a,10));h=S(a)&&!isNaN(a)?a:void 0;c.$validate()})}},url:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c);c.$$parserName="url";c.$validators.url=function(a,b){var d=a||b;return c.$isEmpty(d)||Kg.test(d)}},email:function(a,b,d,c,e,f){lb(a,b,d,c,e,f);pc(c);c.$$parserName="email";c.$validators.email=function(a,b){var d=a||b;return c.$isEmpty(d)||Lg.test(d)}},radio:function(a,b,d,c){w(d.name)&&b.attr("name",++pb);b.on("click",function(a){b[0].checked&&c.$setViewValue(d.value,
a&&a.type)});c.$render=function(){b[0].checked=d.value==c.$viewValue};d.$observe("value",c.$render)},checkbox:function(a,b,d,c,e,f,g,h){var k=Od(h,a,"ngTrueValue",d.ngTrueValue,!0),l=Od(h,a,"ngFalseValue",d.ngFalseValue,!1);b.on("click",function(a){c.$setViewValue(b[0].checked,a&&a.type)});c.$render=function(){b[0].checked=c.$viewValue};c.$isEmpty=function(a){return!1===a};c.$formatters.push(function(a){return na(a,k)});c.$parsers.push(function(a){return a?k:l})},hidden:A,button:A,submit:A,reset:A,
file:A},Gc=["$browser","$sniffer","$filter","$parse",function(a,b,d,c){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,f,g,h){h[0]&&(Yd[M(g.type)]||Yd.text)(e,f,g,h[0],b,a,d,c)}}}}],Ng=/^(true|false|\d+)$/,Ve=function(){return{restrict:"A",priority:100,compile:function(a,b){return Ng.test(b.ngValue)?function(a,b,e){e.$set("value",a.$eval(e.ngValue))}:function(a,b,e){a.$watch(e.ngValue,function(a){e.$set("value",a)})}}}},ve=["$compile",function(a){return{restrict:"AC",compile:function(b){a.$$addBindingClass(b);
return function(b,c,e){a.$$addBindingInfo(c,e.ngBind);c=c[0];b.$watch(e.ngBind,function(a){c.textContent=w(a)?"":a})}}}}],xe=["$interpolate","$compile",function(a,b){return{compile:function(d){b.$$addBindingClass(d);return function(c,d,f){c=a(d.attr(f.$attr.ngBindTemplate));b.$$addBindingInfo(d,c.expressions);d=d[0];f.$observe("ngBindTemplate",function(a){d.textContent=w(a)?"":a})}}}}],we=["$sce","$parse","$compile",function(a,b,d){return{restrict:"A",compile:function(c,e){var f=b(e.ngBindHtml),g=
b(e.ngBindHtml,function(b){return a.valueOf(b)});d.$$addBindingClass(c);return function(b,c,e){d.$$addBindingInfo(c,e.ngBindHtml);b.$watch(g,function(){var d=f(b);c.html(a.getTrustedHtml(d)||"")})}}}}],Ue=da({restrict:"A",require:"ngModel",link:function(a,b,d,c){c.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),ye=qc("",!0),Ae=qc("Odd",0),ze=qc("Even",1),Be=Ma({compile:function(a,b){b.$set("ngCloak",void 0);a.removeClass("ng-cloak")}}),Ce=[function(){return{restrict:"A",scope:!0,controller:"@",
priority:500}}],Lc={},Og={blur:!0,focus:!0};r("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var b=xa("ng-"+a);Lc[b]=["$parse","$rootScope",function(d,c){return{restrict:"A",compile:function(e,f){var g=d(f[b],null,!0);return function(b,d){d.on(a,function(d){var e=function(){g(b,{$event:d})};Og[a]&&c.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var Fe=["$animate","$compile",function(a,
b){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(d,c,e,f,g){var h,k,l;d.$watch(e.ngIf,function(d){d?k||g(function(d,f){k=f;d[d.length++]=b.$$createComment("end ngIf",e.ngIf);h={clone:d};a.enter(d,c.parent(),c)}):(l&&(l.remove(),l=null),k&&(k.$destroy(),k=null),h&&(l=tb(h.clone),a.leave(l).then(function(){l=null}),h=null))})}}}],Ge=["$templateRequest","$anchorScroll","$animate",function(a,b,d){return{restrict:"ECA",priority:400,terminal:!0,
transclude:"element",controller:ea.noop,compile:function(c,e){var f=e.ngInclude||e.src,g=e.onload||"",h=e.autoscroll;return function(c,e,m,n,p){var s=0,r,t,q,w=function(){t&&(t.remove(),t=null);r&&(r.$destroy(),r=null);q&&(d.leave(q).then(function(){t=null}),t=q,q=null)};c.$watch(f,function(f){var m=function(){!x(h)||h&&!c.$eval(h)||b()},t=++s;f?(a(f,!0).then(function(a){if(!c.$$destroyed&&t===s){var b=c.$new();n.template=a;a=p(b,function(a){w();d.enter(a,null,e).then(m)});r=b;q=a;r.$emit("$includeContentLoaded",
f);c.$eval(g)}},function(){c.$$destroyed||t!==s||(w(),c.$emit("$includeContentError",f))}),c.$emit("$includeContentRequested",f)):(w(),n.template=null)})}}}}],Xe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(b,d,c,e){ka.call(d[0]).match(/SVG/)?(d.empty(),a(Oc(e.template,E.document).childNodes)(b,function(a){d.append(a)},{futureParentElement:d})):(d.html(e.template),a(d.contents())(b))}}}],He=Ma({priority:450,compile:function(){return{pre:function(a,
b,d){a.$eval(d.ngInit)}}}}),Te=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,b,d,c){var e=b.attr(d.$attr.ngList)||", ",f="false"!==d.ngTrim,g=f?W(e):e;c.$parsers.push(function(a){if(!w(a)){var b=[];a&&r(a.split(g),function(a){a&&b.push(f?W(a):a)});return b}});c.$formatters.push(function(a){if(J(a))return a.join(e)});c.$isEmpty=function(a){return!a||!a.length}}}},ob="ng-valid",Pd="ng-invalid",Va="ng-pristine",Mb="ng-dirty",Rd="ng-pending",nb=O("ngModel"),Pg=["$scope",
"$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,b,d,c,e,f,g,h,k,l){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=void 0;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=void 0;this.$name=l(d.name||"",!1)(a);
this.$$parentForm=Lb;var m=e(d.ngModel),n=m.assign,p=m,s=n,t=null,I,q=this;this.$$setOptions=function(a){if((q.$options=a)&&a.getterSetter){var b=e(d.ngModel+"()"),f=e(d.ngModel+"($$$p)");p=function(a){var c=m(a);z(c)&&(c=b(a));return c};s=function(a,b){z(m(a))?f(a,{$$$p:b}):n(a,b)}}else if(!m.assign)throw nb("nonassign",d.ngModel,va(c));};this.$render=A;this.$isEmpty=function(a){return w(a)||""===a||null===a||a!==a};this.$$updateEmptyClasses=function(a){q.$isEmpty(a)?(f.removeClass(c,"ng-not-empty"),
f.addClass(c,"ng-empty")):(f.removeClass(c,"ng-empty"),f.addClass(c,"ng-not-empty"))};var K=0;Ld({ctrl:this,$element:c,set:function(a,b){a[b]=!0},unset:function(a,b){delete a[b]},$animate:f});this.$setPristine=function(){q.$dirty=!1;q.$pristine=!0;f.removeClass(c,Mb);f.addClass(c,Va)};this.$setDirty=function(){q.$dirty=!0;q.$pristine=!1;f.removeClass(c,Va);f.addClass(c,Mb);q.$$parentForm.$setDirty()};this.$setUntouched=function(){q.$touched=!1;q.$untouched=!0;f.setClass(c,"ng-untouched","ng-touched")};
this.$setTouched=function(){q.$touched=!0;q.$untouched=!1;f.setClass(c,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){g.cancel(t);q.$viewValue=q.$$lastCommittedViewValue;q.$render()};this.$validate=function(){if(!S(q.$modelValue)||!isNaN(q.$modelValue)){var a=q.$$rawModelValue,b=q.$valid,c=q.$modelValue,d=q.$options&&q.$options.allowInvalid;q.$$runValidators(a,q.$$lastCommittedViewValue,function(e){d||b===e||(q.$modelValue=e?a:void 0,q.$modelValue!==c&&q.$$writeModelToScope())})}};
this.$$runValidators=function(a,b,c){function d(){var c=!0;r(q.$validators,function(d,e){var g=d(a,b);c=c&&g;f(e,g)});return c?!0:(r(q.$asyncValidators,function(a,b){f(b,null)}),!1)}function e(){var c=[],d=!0;r(q.$asyncValidators,function(e,g){var h=e(a,b);if(!h||!z(h.then))throw nb("nopromise",h);f(g,void 0);c.push(h.then(function(){f(g,!0)},function(){d=!1;f(g,!1)}))});c.length?k.all(c).then(function(){g(d)},A):g(!0)}function f(a,b){h===K&&q.$setValidity(a,b)}function g(a){h===K&&c(a)}K++;var h=
K;(function(){var a=q.$$parserName||"parse";if(w(I))f(a,null);else return I||(r(q.$validators,function(a,b){f(b,null)}),r(q.$asyncValidators,function(a,b){f(b,null)})),f(a,I),I;return!0})()?d()?e():g(!1):g(!1)};this.$commitViewValue=function(){var a=q.$viewValue;g.cancel(t);if(q.$$lastCommittedViewValue!==a||""===a&&q.$$hasNativeValidators)q.$$updateEmptyClasses(a),q.$$lastCommittedViewValue=a,q.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var b=q.$$lastCommittedViewValue;
if(I=w(b)?void 0:!0)for(var c=0;c<q.$parsers.length;c++)if(b=q.$parsers[c](b),w(b)){I=!1;break}S(q.$modelValue)&&isNaN(q.$modelValue)&&(q.$modelValue=p(a));var d=q.$modelValue,e=q.$options&&q.$options.allowInvalid;q.$$rawModelValue=b;e&&(q.$modelValue=b,q.$modelValue!==d&&q.$$writeModelToScope());q.$$runValidators(b,q.$$lastCommittedViewValue,function(a){e||(q.$modelValue=a?b:void 0,q.$modelValue!==d&&q.$$writeModelToScope())})};this.$$writeModelToScope=function(){s(a,q.$modelValue);r(q.$viewChangeListeners,
function(a){try{a()}catch(c){b(c)}})};this.$setViewValue=function(a,b){q.$viewValue=a;q.$options&&!q.$options.updateOnDefault||q.$$debounceViewValueCommit(b)};this.$$debounceViewValueCommit=function(b){var c=0,d=q.$options;d&&x(d.debounce)&&(d=d.debounce,S(d)?c=d:S(d[b])?c=d[b]:S(d["default"])&&(c=d["default"]));g.cancel(t);c?t=g(function(){q.$commitViewValue()},c):h.$$phase?q.$commitViewValue():a.$apply(function(){q.$commitViewValue()})};a.$watch(function(){var b=p(a);if(b!==q.$modelValue&&(q.$modelValue===
q.$modelValue||b===b)){q.$modelValue=q.$$rawModelValue=b;I=void 0;for(var c=q.$formatters,d=c.length,e=b;d--;)e=c[d](e);q.$viewValue!==e&&(q.$$updateEmptyClasses(e),q.$viewValue=q.$$lastCommittedViewValue=e,q.$render(),q.$$runValidators(b,e,A))}return b})}],Se=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:Pg,priority:1,compile:function(b){b.addClass(Va).addClass("ng-untouched").addClass(ob);return{pre:function(a,b,e,f){var g=f[0];b=f[1]||
g.$$parentForm;g.$$setOptions(f[2]&&f[2].$options);b.$addControl(g);e.$observe("name",function(a){g.$name!==a&&g.$$parentForm.$$renameControl(g,a)});a.$on("$destroy",function(){g.$$parentForm.$removeControl(g)})},post:function(b,c,e,f){var g=f[0];if(g.$options&&g.$options.updateOn)c.on(g.$options.updateOn,function(a){g.$$debounceViewValueCommit(a&&a.type)});c.on("blur",function(){g.$touched||(a.$$phase?b.$evalAsync(g.$setTouched):b.$apply(g.$setTouched))})}}}}}],Qg=/(\s+|^)default(\s+|$)/,We=function(){return{restrict:"A",
controller:["$scope","$attrs",function(a,b){var d=this;this.$options=Z(a.$eval(b.ngModelOptions));x(this.$options.updateOn)?(this.$options.updateOnDefault=!1,this.$options.updateOn=W(this.$options.updateOn.replace(Qg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},Ie=Ma({terminal:!0,priority:1E3}),Rg=O("ngOptions"),Sg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
Qe=["$compile","$document","$parse",function(a,b,d){function c(a,b,c){function e(a,b,c,d,f){this.selectValue=a;this.viewValue=b;this.label=c;this.group=d;this.disabled=f}function f(a){var b;if(!r&&oa(a))b=a;else{b=[];for(var c in a)a.hasOwnProperty(c)&&"$"!==c.charAt(0)&&b.push(c)}return b}var n=a.match(Sg);if(!n)throw Rg("iexp",a,va(b));var p=n[5]||n[7],r=n[6];a=/ as /.test(n[0])&&n[1];var t=n[9];b=d(n[2]?n[1]:p);var x=a&&d(a)||b,q=t&&d(t),w=t?function(a,b){return q(c,b)}:function(a){return Ga(a)},
v=function(a,b){return w(a,D(a,b))},u=d(n[2]||n[1]),y=d(n[3]||""),A=d(n[4]||""),z=d(n[8]),C={},D=r?function(a,b){C[r]=b;C[p]=a;return C}:function(a){C[p]=a;return C};return{trackBy:t,getTrackByValue:v,getWatchables:d(z,function(a){var b=[];a=a||[];for(var d=f(a),e=d.length,g=0;g<e;g++){var h=a===d?g:d[g],l=a[h],h=D(l,h),l=w(l,h);b.push(l);if(n[2]||n[1])l=u(c,h),b.push(l);n[4]&&(h=A(c,h),b.push(h))}return b}),getOptions:function(){for(var a=[],b={},d=z(c)||[],g=f(d),h=g.length,n=0;n<h;n++){var p=d===
g?n:g[n],q=D(d[p],p),r=x(c,q),p=w(r,q),s=u(c,q),C=y(c,q),q=A(c,q),r=new e(p,r,s,C,q);a.push(r);b[p]=r}return{items:a,selectValueMap:b,getOptionFromViewValue:function(a){return b[v(a)]},getViewValueFromOption:function(a){return t?ea.copy(a.viewValue):a.viewValue}}}}}var e=E.document.createElement("option"),f=E.document.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","ngModel"],link:{pre:function(a,b,c,d){d[0].registerOption=A},post:function(d,h,k,l){function m(a,b){a.element=
b;b.disabled=a.disabled;a.label!==b.label&&(b.label=a.label,b.textContent=a.label);a.value!==b.value&&(b.value=a.selectValue)}function n(){var a=y&&p.readValue();if(y)for(var b=y.items.length-1;0<=b;b--){var c=y.items[b];c.group?Db(c.element.parentNode):Db(c.element)}y=z.getOptions();var d={};v&&h.prepend(w);y.items.forEach(function(a){var b;if(x(a.group)){b=d[a.group];b||(b=f.cloneNode(!1),E.appendChild(b),b.label=a.group,d[a.group]=b);var c=e.cloneNode(!1)}else b=E,c=e.cloneNode(!1);b.appendChild(c);
m(a,c)});h[0].appendChild(E);s.$render();s.$isEmpty(a)||(b=p.readValue(),(z.trackBy||t?na(a,b):a===b)||(s.$setViewValue(b),s.$render()))}var p=l[0],s=l[1],t=k.multiple,w;l=0;for(var q=h.children(),A=q.length;l<A;l++)if(""===q[l].value){w=q.eq(l);break}var v=!!w,u=B(e.cloneNode(!1));u.val("?");var y,z=c(k.ngOptions,h,d),E=b[0].createDocumentFragment();t?(s.$isEmpty=function(a){return!a||0===a.length},p.writeValue=function(a){y.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){if(a=
y.getOptionFromViewValue(a))a.element.selected=!0})},p.readValue=function(){var a=h.val()||[],b=[];r(a,function(a){(a=y.selectValueMap[a])&&!a.disabled&&b.push(y.getViewValueFromOption(a))});return b},z.trackBy&&d.$watchCollection(function(){if(J(s.$viewValue))return s.$viewValue.map(function(a){return z.getTrackByValue(a)})},function(){s.$render()})):(p.writeValue=function(a){var b=y.getOptionFromViewValue(a);b?(h[0].value!==b.selectValue&&(u.remove(),v||w.remove(),h[0].value=b.selectValue,b.element.selected=
!0),b.element.setAttribute("selected","selected")):null===a||v?(u.remove(),v||h.prepend(w),h.val(""),w.prop("selected",!0),w.attr("selected",!0)):(v||w.remove(),h.prepend(u),h.val("?"),u.prop("selected",!0),u.attr("selected",!0))},p.readValue=function(){var a=y.selectValueMap[h.val()];return a&&!a.disabled?(v||w.remove(),u.remove(),y.getViewValueFromOption(a)):null},z.trackBy&&d.$watch(function(){return z.getTrackByValue(s.$viewValue)},function(){s.$render()}));v?(w.remove(),a(w)(d),w.removeClass("ng-scope")):
w=B(e.cloneNode(!1));h.empty();n();d.$watchCollection(z.getWatchables,n)}}}}],Je=["$locale","$interpolate","$log",function(a,b,d){var c=/{}/g,e=/^when(Minus)?(.+)$/;return{link:function(f,g,h){function k(a){g.text(a||"")}var l=h.count,m=h.$attr.when&&g.attr(h.$attr.when),n=h.offset||0,p=f.$eval(m)||{},s={},t=b.startSymbol(),x=b.endSymbol(),q=t+l+"-"+n+x,z=ea.noop,v;r(h,function(a,b){var c=e.exec(b);c&&(c=(c[1]?"-":"")+M(c[2]),p[c]=g.attr(h.$attr[b]))});r(p,function(a,d){s[d]=b(a.replace(c,q))});f.$watch(l,
function(b){var c=parseFloat(b),e=isNaN(c);e||c in p||(c=a.pluralCat(c-n));c===v||e&&S(v)&&isNaN(v)||(z(),e=s[c],w(e)?(null!=b&&d.debug("ngPluralize: no rule defined for '"+c+"' in "+m),z=A,k()):z=f.$watch(e,k),v=c)})}}}],Ke=["$parse","$animate","$compile",function(a,b,d){var c=O("ngRepeat"),e=function(a,b,c,d,e,m,n){a[c]=d;e&&(a[e]=m);a.$index=b;a.$first=0===b;a.$last=b===n-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(b&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,
terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,k=d.$$createComment("end ngRepeat",h),l=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!l)throw c("iexp",h);var m=l[1],n=l[2],p=l[3],s=l[4],l=m.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!l)throw c("iidexp",m);var t=l[3]||l[1],w=l[2];if(p&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(p)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(p)))throw c("badident",
p);var q,x,v,u,y={$id:Ga};s?q=a(s):(v=function(a,b){return Ga(b)},u=function(a){return a});return function(a,d,f,g,l){q&&(x=function(b,c,d){w&&(y[w]=b);y[t]=c;y.$index=d;return q(a,y)});var m=T();a.$watchCollection(n,function(f){var g,n,q=d[0],s,y=T(),z,A,E,C,D,B,F;p&&(a[p]=f);if(oa(f))D=f,n=x||v;else for(F in n=x||u,D=[],f)sa.call(f,F)&&"$"!==F.charAt(0)&&D.push(F);z=D.length;F=Array(z);for(g=0;g<z;g++)if(A=f===D?g:D[g],E=f[A],C=n(A,E,g),m[C])B=m[C],delete m[C],y[C]=B,F[g]=B;else{if(y[C])throw r(F,
function(a){a&&a.scope&&(m[a.id]=a)}),c("dupes",h,C,E);F[g]={id:C,scope:void 0,clone:void 0};y[C]=!0}for(s in m){B=m[s];C=tb(B.clone);b.leave(C);if(C[0].parentNode)for(g=0,n=C.length;g<n;g++)C[g].$$NG_REMOVED=!0;B.scope.$destroy()}for(g=0;g<z;g++)if(A=f===D?g:D[g],E=f[A],B=F[g],B.scope){s=q;do s=s.nextSibling;while(s&&s.$$NG_REMOVED);B.clone[0]!=s&&b.move(tb(B.clone),null,q);q=B.clone[B.clone.length-1];e(B.scope,g,t,E,w,A,z)}else l(function(a,c){B.scope=c;var d=k.cloneNode(!1);a[a.length++]=d;b.enter(a,
null,q);q=d;B.clone=a;y[B.id]=B;e(B.scope,g,t,E,w,A,z)});m=y})}}}}],Le=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngShow,function(b){a[b?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Ee=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngHide,function(b){a[b?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Me=Ma(function(a,b,d){a.$watch(d.ngStyle,function(a,
d){d&&a!==d&&r(d,function(a,c){b.css(c,"")});a&&b.css(a)},!0)}),Ne=["$animate","$compile",function(a,b){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(d,c,e,f){var g=[],h=[],k=[],l=[],m=function(a,b){return function(){a.splice(b,1)}};d.$watch(e.ngSwitch||e.on,function(c){var d,e;d=0;for(e=k.length;d<e;++d)a.cancel(k[d]);d=k.length=0;for(e=l.length;d<e;++d){var t=tb(h[d].clone);l[d].$destroy();(k[d]=a.leave(t)).then(m(k,d))}h.length=0;l.length=0;(g=f.cases["!"+
c]||f.cases["?"])&&r(g,function(c){c.transclude(function(d,e){l.push(e);var f=c.element;d[d.length++]=b.$$createComment("end ngSwitchWhen");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],Oe=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["!"+d.ngSwitchWhen]=c.cases["!"+d.ngSwitchWhen]||[];c.cases["!"+d.ngSwitchWhen].push({transclude:e,element:b})}}),Pe=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,
b,d,c,e){c.cases["?"]=c.cases["?"]||[];c.cases["?"].push({transclude:e,element:b})}}),Tg=O("ngTransclude"),Re=Ma({restrict:"EAC",link:function(a,b,d,c,e){d.ngTransclude===d.$attr.ngTransclude&&(d.ngTransclude="");if(!e)throw Tg("orphan",va(b));e(function(a){a.length&&(b.empty(),b.append(a))},null,d.ngTransclude||d.ngTranscludeSlot)}}),re=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(b,d){"text/ng-template"==d.type&&a.put(d.id,b[0].text)}}}],Ug={$setViewValue:A,$render:A},
Vg=["$element","$scope",function(a,b){var d=this,c=new Sa;d.ngModelCtrl=Ug;d.unknownOption=B(E.document.createElement("option"));d.renderUnknownOption=function(b){b="? "+Ga(b)+" ?";d.unknownOption.val(b);a.prepend(d.unknownOption);a.val(b)};b.$on("$destroy",function(){d.renderUnknownOption=A});d.removeUnknownOption=function(){d.unknownOption.parent()&&d.unknownOption.remove()};d.readValue=function(){d.removeUnknownOption();return a.val()};d.writeValue=function(b){d.hasOption(b)?(d.removeUnknownOption(),
a.val(b),""===b&&d.emptyOption.prop("selected",!0)):null==b&&d.emptyOption?(d.removeUnknownOption(),a.val("")):d.renderUnknownOption(b)};d.addOption=function(a,b){if(8!==b[0].nodeType){Ra(a,'"option value"');""===a&&(d.emptyOption=b);var g=c.get(a)||0;c.put(a,g+1);d.ngModelCtrl.$render();b[0].hasAttribute("selected")&&(b[0].selected=!0)}};d.removeOption=function(a){var b=c.get(a);b&&(1===b?(c.remove(a),""===a&&(d.emptyOption=void 0)):c.put(a,b-1))};d.hasOption=function(a){return!!c.get(a)};d.registerOption=
function(a,b,c,h,k){if(h){var l;c.$observe("value",function(a){x(l)&&d.removeOption(l);l=a;d.addOption(a,b)})}else k?a.$watch(k,function(a,e){c.$set("value",a);e!==a&&d.removeOption(e);d.addOption(a,b)}):d.addOption(c.value,b);b.on("$destroy",function(){d.removeOption(c.value);d.ngModelCtrl.$render()})}}],se=function(){return{restrict:"E",require:["select","?ngModel"],controller:Vg,priority:1,link:{pre:function(a,b,d,c){var e=c[1];if(e){var f=c[0];f.ngModelCtrl=e;b.on("change",function(){a.$apply(function(){e.$setViewValue(f.readValue())})});
if(d.multiple){f.readValue=function(){var a=[];r(b.find("option"),function(b){b.selected&&a.push(b.value)});return a};f.writeValue=function(a){var c=new Sa(a);r(b.find("option"),function(a){a.selected=x(c.get(a.value))})};var g,h=NaN;a.$watch(function(){h!==e.$viewValue||na(g,e.$viewValue)||(g=ga(e.$viewValue),e.$render());h=e.$viewValue});e.$isEmpty=function(a){return!a||0===a.length}}}},post:function(a,b,d,c){var e=c[1];if(e){var f=c[0];e.$render=function(){f.writeValue(e.$viewValue)}}}}}},ue=["$interpolate",
function(a){return{restrict:"E",priority:100,compile:function(b,d){if(x(d.value))var c=a(d.value,!0);else{var e=a(b.text(),!0);e||d.$set("value",b.text())}return function(a,b,d){var k=b.parent();(k=k.data("$selectController")||k.parent().data("$selectController"))&&k.registerOption(a,b,d,c,e)}}}}],te=da({restrict:"E",terminal:!1}),Ic=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){c&&(d.required=!0,c.$validators.required=function(a,b){return!d.required||!c.$isEmpty(b)},d.$observe("required",
function(){c.$validate()}))}}},Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e,f=d.ngPattern||d.pattern;d.$observe("pattern",function(a){F(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw O("ngPattern")("noregexp",f,a,va(b));e=a||void 0;c.$validate()});c.$validators.pattern=function(a,b){return c.$isEmpty(b)||w(e)||e.test(b)}}}}},Kc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=-1;d.$observe("maxlength",function(a){a=
aa(a);e=isNaN(a)?-1:a;c.$validate()});c.$validators.maxlength=function(a,b){return 0>e||c.$isEmpty(b)||b.length<=e}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=0;d.$observe("minlength",function(a){e=aa(a)||0;c.$validate()});c.$validators.minlength=function(a,b){return c.$isEmpty(b)||b.length>=e}}}}};E.angular.bootstrap?E.console&&console.log("WARNING: Tried to load angular more than once."):(ke(),me(ea),ea.module("ngLocale",[],["$provide",function(a){function b(a){a+=
"";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),
WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,
c){var e=a|0,f=c;void 0===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),B(E.document).ready(function(){ge(E.document,Bc)}))})(window);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
//# sourceMappingURL=angular.min.js.map
;
define("angular", (function (global) {
    return function () {
        var ret, fn;
        return ret || global.angular;
    };
}(this)));

modules/Poller/pollerMod.js
/**
 * angular-poller
 *
 * @description
 * Angular poller service. It uses a timer and sends requests every few seconds to
 * keep the client synced with the server.
 *
 * @version v0.3.1
 * @link http://github.com/emmaguo/angular-poller
 * @license MIT
 *
 * @example
 * Simple example:
 *      var myPoller = poller.get(target);
 *      myPoller.promise.then(null, null, callback);
 *
 * Advanced example:
 *      var myPoller = poller.get(target, {
 *          action: 'query',
 *          argumentsArray: [
 *              {
 *                  verb: 'greet',
 *                  salutation: 'Hello'
 *              }
 *          ],
 *          delay: 6000,
 *          smart: true,
 *          catchError: true
 *      });
 *      myPoller.promise.then(null, null, callback);
 */

'use strict';

(function (window, angular, undefined) {

    angular.module('TVG.poller', [])

        .constant('pollerConfig', {
            stopOnRouteChange: false,
            stopOnStateChange: false
        })

        .run(function ($rootScope, poller, pollerConfig) {

            /**
             * Automatically stop all pollers before route change ($routeProvider) or state change ($stateProvider).
             */
            if (pollerConfig.stopOnRouteChange) {

                $rootScope.$on('$routeChangeStart', function () {
                    poller.stopAll();
                });
            } else if (pollerConfig.stopOnStateChange) {

                $rootScope.$on('$stateChangeStart', function () {
                    poller.stopAll();
                });
            }
        })

        .factory('poller', function ($interval, $q, $http) {

            var pollers = [], // Poller registry

                defaults = {
                    action: 'get',
                    argumentsArray: [],
                    delay: 5000,
                    smart: false,
                    catchError: true,
                    deferInit: false
                },

                /**
                 * Poller model:
                 *  - target (can be $resource object, or Restangular object, or $http url)
                 *  - action
                 *  - argumentsArray
                 *  - delay
                 *  - smart (indicates whether poller should only send new request if the previous one is resolved)
                 *  - catchError (indicates whether poller should get notified of error responses)
                 *  - promise
                 *  - interval
                 *
                 * @param target
                 * @param options
                 */
                Poller = function (target, options) {

                    this.target = target;
                    this.set(options);
                    this.deferreds = [];
                },

                /**
                 * Find poller by target in poller registry.
                 *
                 * @param target
                 * @returns {object}
                 */
                findPoller = function (target, options) {

                    var poller = null;

                    angular.forEach(pollers, function (item) {
                        if (angular.equals(item.target, target) && item.action === options.action) {
                            poller = item;
                        }
                    });

                    return poller;
                };

            angular.extend(Poller.prototype, {

                /**
                 * Set poller action, argumentsArray, delay, smart and catchError flags.
                 *
                 * If options.action is defined, then set poller action to options.action,
                 * else if poller.action is undefined, then set it to defaults.action,
                 * else do nothing. The same goes for poller.argumentsArray, poller.delay, poller.smart and poller.catchError.
                 *
                 * @param options
                 */
                set: function (options) {

                    angular.forEach(['action', 'argumentsArray', 'delay', 'smart', 'catchError', 'deferInit'], function (prop) {
                        if (options && options[prop]) {
                            this[prop] = options[prop];
                        } else if (!this[prop]) {
                            this[prop] = defaults[prop];
                        }
                    }, this);
                },

                /**
                 * Start poller service.
                 */
                start: function () {

                    var target = this.target,
                        action = this.action,
                        argumentsArray = this.argumentsArray.slice(0),
                        delay = this.delay,
                        smart = this.smart,
                        catchError = this.catchError,
                        self = this,
                        current,
                        timestamp,
                        deferred,
                        deferInit = this.deferInit;

                    deferred = $q.defer();
                    deferred.promise.timestamp = Date.now();
                    this.deferreds.push(deferred);

                    /**
                     * $resource: typeof target === 'function'
                     * Restangular: typeof target === 'object'
                     * $http: typeof target === 'string'
                     */
                    if (typeof target === 'string') {

                        /**
                         * Update argumentsArray and target for target[action].apply(self, argumentsArray).
                         *
                         * @example
                         * $http.get(url, [config])
                         * $http.post(url, data, [config])
                         */
                        argumentsArray.unshift(target);
                        target = $http;
                    }

                    function tick() {

                        // If smart flag is true, then only send new request if the previous one is resolved.
                        if (!smart || !angular.isDefined(current) || current.$resolved) {

                            timestamp = new Date();
                            current = target[action].apply(self, argumentsArray);
                            current.$resolved = false;

                            /**
                             * $resource: current.$promise.then
                             * Restangular: current.then
                             * $http: current.then
                             */
                            (current.$promise || current).then(function (result) {

                                current.$resolved = true;

                                // Ignore success response if request is sent before poller is stopped.
                                if (angular.isUndefined(self.stopTimestamp) || timestamp >= self.stopTimestamp) {
                                    angular.forEach(self.deferreds, function (d) {
                                        d.notify(result);
                                    });
                                }

                            }, function (error) {
                                current.$resolved = true;

                                // Send error response if catchError flag is true and request is sent before poller is stopped
                                if (catchError && (angular.isUndefined(self.stopTimestamp) || timestamp >= self.stopTimestamp)) {
                                    angular.forEach(self.deferreds, function (d) {
										d.notify(error);
                                    });
                                }
                            });
                        }
                    }

                    if (!deferInit) {
                        tick();
                    }

                    this.interval = $interval(tick, delay);
                    this.promise = deferred.promise;
                    this.then = function then () {
                        this.promise.then.apply(this.promise, arguments);
                        return this.promise;
                    };
                },

                /**
                 * Stop poller service if it is running.
                 */
                stop: function () {

                    if (angular.isDefined(this.interval)) {
                        $interval.cancel(this.interval);
                        this.interval = undefined;
                        this.stopTimestamp = new Date();
                    }
                },

                /**
                 * Restart poller service.
                 */
                restart: function () {
                    this.stop();
                    this.start();
                },

                removeDeferred: function (promise) {
                    var activeDeferreds = [];

                    for (var i = 0; i < this.deferreds.length; i++) {
                        var d = this.deferreds[i];

                        if (!angular.equals(d.promise, promise)) {
                            activeDeferreds.push(d);
                        }
                    }
                    this.deferreds = activeDeferreds;
                    if (!this.deferreds.length) {
                        this.stop();
                    }
                }
            });

            return {

                /**
                 * Return a singleton instance of a poller. If poller does not exist, then register and
                 * start it. Otherwise return it and restart it if necessary.
                 *
                 * @param target
                 * @param options
                 * @returns {object}
                 */
                get: function (target, options) {

                    var poller = findPoller(target, options);

                    if (!poller) {

                        poller = new Poller(target, options);
                        pollers.push(poller);
                        poller.start();

                    } else {

                        poller.set(options);
                        poller.restart();
                    }

                    return poller;
                },

                /**
                 * Total number of pollers in poller registry.
                 *
                 * @returns {number}
                 */
                size: function () {
                    return pollers.length;
                },

                /**
                 * Stop all poller services.
                 */
                stopAll: function () {
                    angular.forEach(pollers, function (p) {
                        p.stop();
                    });
                },

                /**
                 * Restart all poller services.
                 */
                restartAll: function () {
                    angular.forEach(pollers, function (p) {
                        p.restart();
                    });
                },

                /**
                 * Stop and remove all poller services
                 */
                reset: function () {
                    this.stopAll();
                    pollers = [];
                }
            };
        }
    );
}(window, window.angular));

define("Poller", ["angular"], function(){});

vendors/angular-route/angular-route.min.js
/*
 AngularJS v1.5.7
 (c) 2010-2016 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(F,d){'use strict';function x(t,l,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(b,e,a,c,k){function p(){m&&(g.cancel(m),m=null);h&&(h.$destroy(),h=null);n&&(m=g.leave(n),m.then(function(){m=null}),n=null)}function A(){var a=t.current&&t.current.locals;if(d.isDefined(a&&a.$template)){var a=b.$new(),c=t.current;n=k(a,function(a){g.enter(a,null,n||e).then(function(){!d.isDefined(z)||z&&!b.$eval(z)||l()});p()});h=c.scope=a;h.$emit("$viewContentLoaded");
h.$eval(s)}else p()}var h,n,m,z=a.autoscroll,s=a.onload||"";b.$on("$routeChangeSuccess",A);A()}}}function w(d,l,g){return{restrict:"ECA",priority:-400,link:function(b,e){var a=g.current,c=a.locals;e.html(c.$template);var k=d(e.contents());if(a.controller){c.$scope=b;var p=l(a.controller,c);a.controllerAs&&(b[a.controllerAs]=p);e.data("$ngControllerController",p);e.children().data("$ngControllerController",p)}b[a.resolveAs||"$resolve"]=c;k(b)}}}var C=d.isArray,D=d.isObject,s=d.module("ngRoute",["ng"]).provider("$route",
function(){function t(b,e){return d.extend(Object.create(b),e)}function l(b,d){var a=d.caseInsensitiveMatch,c={originalPath:b,regexp:b},g=c.keys=[];b=b.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)(\*\?|[\?\*])?/g,function(b,a,d,c){b="?"===c||"*?"===c?"?":null;c="*"===c||"*?"===c?"*":null;g.push({name:d,optional:!!b});a=a||"";return""+(b?"":a)+"(?:"+(b?a:"")+(c&&"(.+?)"||"([^/]+)")+(b||"")+")"+(b||"")}).replace(/([\/$\*])/g,"\\$1");c.regexp=new RegExp("^"+b+"$",a?"i":"");return c}var g={};this.when=
function(b,e){var a;a=void 0;if(C(e)){a=a||[];for(var c=0,k=e.length;c<k;c++)a[c]=e[c]}else if(D(e))for(c in a=a||{},e)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=e[c];a=a||e;d.isUndefined(a.reloadOnSearch)&&(a.reloadOnSearch=!0);d.isUndefined(a.caseInsensitiveMatch)&&(a.caseInsensitiveMatch=this.caseInsensitiveMatch);g[b]=d.extend(a,b&&l(b,a));b&&(c="/"==b[b.length-1]?b.substr(0,b.length-1):b+"/",g[c]=d.extend({redirectTo:b},l(c,a)));return this};this.caseInsensitiveMatch=!1;this.otherwise=function(b){"string"===
typeof b&&(b={redirectTo:b});this.when(null,b);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(b,e,a,c,k,p,l){function h(a){var f=v.current;(B=(r=x())&&f&&r.$$route===f.$$route&&d.equals(r.pathParams,f.pathParams)&&!r.reloadOnSearch&&!y)||!f&&!r||b.$broadcast("$routeChangeStart",r,f).defaultPrevented&&a&&a.preventDefault()}function n(){var u=v.current,f=r;if(B)u.params=f.params,d.copy(u.params,a),b.$broadcast("$routeUpdate",u);else if(f||
u)y=!1,(v.current=f)&&f.redirectTo&&(d.isString(f.redirectTo)?e.path(w(f.redirectTo,f.params)).search(f.params).replace():e.url(f.redirectTo(f.pathParams,e.path(),e.search())).replace()),c.when(f).then(m).then(function(c){f==v.current&&(f&&(f.locals=c,d.copy(f.params,a)),b.$broadcast("$routeChangeSuccess",f,u))},function(a){f==v.current&&b.$broadcast("$routeChangeError",f,u,a)})}function m(a){if(a){var b=d.extend({},a.resolve);d.forEach(b,function(a,c){b[c]=d.isString(a)?k.get(a):k.invoke(a,null,
null,c)});a=s(a);d.isDefined(a)&&(b.$template=a);return c.all(b)}}function s(a){var b,c;d.isDefined(b=a.template)?d.isFunction(b)&&(b=b(a.params)):d.isDefined(c=a.templateUrl)&&(d.isFunction(c)&&(c=c(a.params)),d.isDefined(c)&&(a.loadedTemplateUrl=l.valueOf(c),b=p(c)));return b}function x(){var a,b;d.forEach(g,function(c,g){var q;if(q=!b){var h=e.path();q=c.keys;var l={};if(c.regexp)if(h=c.regexp.exec(h)){for(var k=1,p=h.length;k<p;++k){var m=q[k-1],n=h[k];m&&n&&(l[m.name]=n)}q=l}else q=null;else q=
null;q=a=q}q&&(b=t(c,{params:d.extend({},e.search(),a),pathParams:a}),b.$$route=c)});return b||g[null]&&t(g[null],{params:{},pathParams:{}})}function w(a,b){var c=[];d.forEach((a||"").split(":"),function(a,d){if(0===d)c.push(a);else{var e=a.match(/(\w+)(?:[?*])?(.*)/),g=e[1];c.push(b[g]);c.push(e[2]||"");delete b[g]}});return c.join("")}var y=!1,r,B,v={routes:g,reload:function(){y=!0;var a={defaultPrevented:!1,preventDefault:function(){this.defaultPrevented=!0;y=!1}};b.$evalAsync(function(){h(a);
a.defaultPrevented||n()})},updateParams:function(a){if(this.current&&this.current.$$route)a=d.extend({},this.current.params,a),e.path(w(this.current.$$route.originalPath,a)),e.search(a);else throw E("norout");}};b.$on("$locationChangeStart",h);b.$on("$locationChangeSuccess",n);return v}]}),E=d.$$minErr("ngRoute");s.provider("$routeParams",function(){this.$get=function(){return{}}});s.directive("ngView",x);s.directive("ngView",w);x.$inject=["$route","$anchorScroll","$animate"];w.$inject=["$compile",
"$controller","$route"]})(window,window.angular);
//# sourceMappingURL=angular-route.min.js.map
;
define("angularRoute", ["angular"], function(){});

vendors/angular-bootstrap/ui-bootstrap.min.js
/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 2.2.0 - 2016-10-10
 * License: MIT
 */angular.module("ui.bootstrap",["ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$q","$parse","$injector",function(a,b,c,d){var e=d.has("$animateCss")?d.get("$animateCss"):null;return{link:function(d,f,g){function h(){r=!!("horizontal"in g),r?(s={width:""},t={width:"0"}):(s={height:""},t={height:"0"}),d.$eval(g.uibCollapse)||f.addClass("in").addClass("collapse").attr("aria-expanded",!0).attr("aria-hidden",!1).css(s)}function i(a){return r?{width:a.scrollWidth+"px"}:{height:a.scrollHeight+"px"}}function j(){f.hasClass("collapse")&&f.hasClass("in")||b.resolve(n(d)).then(function(){f.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),e?e(f,{addClass:"in",easing:"ease",css:{overflow:"hidden"},to:i(f[0])}).start()["finally"](k):a.addClass(f,"in",{css:{overflow:"hidden"},to:i(f[0])}).then(k)})}function k(){f.removeClass("collapsing").addClass("collapse").css(s),o(d)}function l(){return f.hasClass("collapse")||f.hasClass("in")?void b.resolve(p(d)).then(function(){f.css(i(f[0])).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),e?e(f,{removeClass:"in",to:t}).start()["finally"](m):a.removeClass(f,"in",{to:t}).then(m)}):m()}function m(){f.css(t),f.removeClass("collapsing").addClass("collapse"),q(d)}var n=c(g.expanding),o=c(g.expanded),p=c(g.collapsing),q=c(g.collapsed),r=!1,s={},t={};h(),d.$watch(g.uibCollapse,function(a){a?l():j()})}}}]),angular.module("ui.bootstrap.tabindex",[]).directive("uibTabindexToggle",function(){return{restrict:"A",link:function(a,b,c){c.$observe("disabled",function(a){c.$set("tabindex",a?-1:null)})}}}),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse","ui.bootstrap.tabindex"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(c){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion-group.html"},scope:{heading:"@",panelClass:"@?",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){b.addClass("panel"),d.addGroup(a),a.openClass=c.openClass||"panel-open",a.panelClass=c.panelClass||"panel-default",a.$watch("isOpen",function(c){b.toggleClass(a.openClass,!!c),c&&d.closeOthers(a)}),a.toggleOpen=function(b){a.isDisabled||b&&32!==b.which||(a.isOpen=!a.isOpen)};var e="accordiongroup-"+a.$id+"-"+Math.floor(1e4*Math.random());a.headingId=e+"-tab",a.panelId=e+"-panel"}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("uibAccordionTransclude",function(){function a(){return"uib-accordion-header,data-uib-accordion-header,x-uib-accordion-header,uib\\:accordion-header,[uib-accordion-header],[data-uib-accordion-header],[x-uib-accordion-header]"}return{require:"^uibAccordionGroup",link:function(b,c,d,e){b.$watch(function(){return e[d.uibAccordionTransclude]},function(b){if(b){var d=angular.element(c[0].querySelector(a()));d.html(""),d.append(b)}})}}}),angular.module("ui.bootstrap.alert",[]).controller("UibAlertController",["$scope","$element","$attrs","$interpolate","$timeout",function(a,b,c,d,e){a.closeable=!!c.close,b.addClass("alert"),c.$set("role","alert"),a.closeable&&b.addClass("alert-dismissible");var f=angular.isDefined(c.dismissOnTimeout)?d(c.dismissOnTimeout)(a.$parent):null;f&&e(function(){a.close()},parseInt(f,10))}]).directive("uibAlert",function(){return{controller:"UibAlertController",controllerAs:"alert",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/alert/alert.html"},transclude:!0,scope:{close:"&"}}}),angular.module("ui.bootstrap.buttons",[]).constant("uibButtonConfig",{activeClass:"active",toggleEvent:"click"}).controller("UibButtonsController",["uibButtonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("uibBtnRadio",["$parse",function(a){return{require:["uibBtnRadio","ngModel"],controller:"UibButtonsController",controllerAs:"buttons",link:function(b,c,d,e){var f=e[0],g=e[1],h=a(d.uibUncheckable);c.find("input").css({display:"none"}),g.$render=function(){c.toggleClass(f.activeClass,angular.equals(g.$modelValue,b.$eval(d.uibBtnRadio)))},c.on(f.toggleEvent,function(){if(!d.disabled){var a=c.hasClass(f.activeClass);a&&!angular.isDefined(d.uncheckable)||b.$apply(function(){g.$setViewValue(a?null:b.$eval(d.uibBtnRadio)),g.$render()})}}),d.uibUncheckable&&b.$watch(h,function(a){d.$set("uncheckable",a?"":void 0)})}}}]).directive("uibBtnCheckbox",function(){return{require:["uibBtnCheckbox","ngModel"],controller:"UibButtonsController",controllerAs:"button",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){return angular.isDefined(b)?a.$eval(b):c}var h=d[0],i=d[1];b.find("input").css({display:"none"}),i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.on(h.toggleEvent,function(){c.disabled||a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("UibCarouselController",["$scope","$element","$interval","$timeout","$animate",function(a,b,c,d,e){function f(){for(;t.length;)t.shift()}function g(a){for(var b=0;b<q.length;b++)q[b].slide.active=b===a}function h(c,d,i){if(!u){if(angular.extend(c,{direction:i}),angular.extend(q[s].slide||{},{direction:i}),e.enabled(b)&&!a.$currentTransition&&q[d].element&&p.slides.length>1){q[d].element.data(r,c.direction);var j=p.getCurrentIndex();angular.isNumber(j)&&q[j].element&&q[j].element.data(r,c.direction),a.$currentTransition=!0,e.on("addClass",q[d].element,function(b,c){if("close"===c&&(a.$currentTransition=null,e.off("addClass",b),t.length)){var d=t.pop().slide,g=d.index,i=g>p.getCurrentIndex()?"next":"prev";f(),h(d,g,i)}})}a.active=c.index,s=c.index,g(d),l()}}function i(a){for(var b=0;b<q.length;b++)if(q[b].slide===a)return b}function j(){n&&(c.cancel(n),n=null)}function k(b){b.length||(a.$currentTransition=null,f())}function l(){j();var b=+a.interval;!isNaN(b)&&b>0&&(n=c(m,b))}function m(){var b=+a.interval;o&&!isNaN(b)&&b>0&&q.length?a.next():a.pause()}var n,o,p=this,q=p.slides=a.slides=[],r="uib-slideDirection",s=a.active,t=[],u=!1;b.addClass("carousel"),p.addSlide=function(b,c){q.push({slide:b,element:c}),q.sort(function(a,b){return+a.slide.index-+b.slide.index}),(b.index===a.active||1===q.length&&!angular.isNumber(a.active))&&(a.$currentTransition&&(a.$currentTransition=null),s=b.index,a.active=b.index,g(s),p.select(q[i(b)]),1===q.length&&a.play())},p.getCurrentIndex=function(){for(var a=0;a<q.length;a++)if(q[a].slide.index===s)return a},p.next=a.next=function(){var b=(p.getCurrentIndex()+1)%q.length;return 0===b&&a.noWrap()?void a.pause():p.select(q[b],"next")},p.prev=a.prev=function(){var b=p.getCurrentIndex()-1<0?q.length-1:p.getCurrentIndex()-1;return a.noWrap()&&b===q.length-1?void a.pause():p.select(q[b],"prev")},p.removeSlide=function(b){var c=i(b),d=t.indexOf(q[c]);-1!==d&&t.splice(d,1),q.splice(c,1),q.length>0&&s===c?c>=q.length?(s=q.length-1,a.active=s,g(s),p.select(q[q.length-1])):(s=c,a.active=s,g(s),p.select(q[c])):s>c&&(s--,a.active=s),0===q.length&&(s=null,a.active=null,f())},p.select=a.select=function(b,c){var d=i(b.slide);void 0===c&&(c=d>p.getCurrentIndex()?"next":"prev"),b.slide.index===s||a.$currentTransition?b&&b.slide.index!==s&&a.$currentTransition&&t.push(q[d]):h(b.slide,d,c)},a.indexOfSlide=function(a){return+a.slide.index},a.isActive=function(b){return a.active===b.slide.index},a.isPrevDisabled=function(){return 0===a.active&&a.noWrap()},a.isNextDisabled=function(){return a.active===q.length-1&&a.noWrap()},a.pause=function(){a.noPause||(o=!1,j())},a.play=function(){o||(o=!0,l())},b.on("mouseenter",a.pause),b.on("mouseleave",a.play),a.$on("$destroy",function(){u=!0,j()}),a.$watch("noTransition",function(a){e.enabled(b,!a)}),a.$watch("interval",l),a.$watchCollection("slides",k),a.$watch("active",function(a){if(angular.isNumber(a)&&s!==a){for(var b=0;b<q.length;b++)if(q[b].slide.index===a){a=b;break}var c=q[a];c&&(g(a),p.select(q[a]),s=a)}})}]).directive("uibCarousel",function(){return{transclude:!0,controller:"UibCarouselController",controllerAs:"carousel",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/carousel.html"},scope:{active:"=",interval:"=",noTransition:"=",noPause:"=",noWrap:"&"}}}).directive("uibSlide",["$animate",function(a){return{require:"^uibCarousel",restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/slide.html"},scope:{actual:"=?",index:"=?"},link:function(b,c,d,e){c.addClass("item"),e.addSlide(b,c),b.$on("$destroy",function(){e.removeSlide(b)}),b.$watch("active",function(b){a[b?"addClass":"removeClass"](c,"active")})}}}]).animation(".item",["$animateCss",function(a){function b(a,b,c){a.removeClass(b),c&&c()}var c="uib-slideDirection";return{beforeAddClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i+" "+h,f);return d.addClass(h),a(d,{addClass:i}).start().done(j),function(){g=!0}}f()},beforeRemoveClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i,f);return a(d,{addClass:i}).start().done(j),function(){g=!0}}f()}}}]),angular.module("ui.bootstrap.dateparser",[]).service("uibDateParser",["$log","$locale","dateFilter","orderByFilter",function(a,b,c,d){function e(a){var b=[],c=a.split(""),e=a.indexOf("'");if(e>-1){var f=!1;a=a.split("");for(var g=e;g<a.length;g++)f?("'"===a[g]&&(g+1<a.length&&"'"===a[g+1]?(a[g+1]="$",c[g+1]=""):(c[g]="",f=!1)),a[g]="$"):"'"===a[g]&&(a[g]="$",c[g]="",f=!0);a=a.join("")}return angular.forEach(q,function(d){var e=a.indexOf(d.key);if(e>-1){a=a.split(""),c[e]="("+d.regex+")",a[e]="$";for(var f=e+1,g=e+d.key.length;g>f;f++)c[f]="",a[f]="$";a=a.join(""),b.push({index:e,key:d.key,apply:d.apply,matcher:d.regex})}}),{regex:new RegExp("^"+c.join("")+"$"),map:d(b,"index")}}function f(a){for(var b,c,d=[],e=0;e<a.length;)if(angular.isNumber(c)){if("'"===a.charAt(e))(e+1>=a.length||"'"!==a.charAt(e+1))&&(d.push(g(a,c,e)),c=null);else if(e===a.length)for(;c<a.length;)b=h(a,c),d.push(b),c=b.endIdx;e++}else"'"!==a.charAt(e)?(b=h(a,e),d.push(b.parser),e=b.endIdx):(c=e,e++);return d}function g(a,b,c){return function(){return a.substr(b+1,c-b-1)}}function h(a,b){for(var c=a.substr(b),d=0;d<q.length;d++)if(new RegExp("^"+q[d].key).test(c)){var e=q[d];return{endIdx:b+e.key.length,parser:e.formatter}}return{endIdx:b+1,parser:function(){return c.charAt(0)}}}function i(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}function j(a){return parseInt(a,10)}function k(a,b){return a&&b?o(a,b):a}function l(a,b){return a&&b?o(a,b,!0):a}function m(a,b){a=a.replace(/:/g,"");var c=Date.parse("Jan 01, 1970 00:00:00 "+a)/6e4;return isNaN(c)?b:c}function n(a,b){return a=new Date(a.getTime()),a.setMinutes(a.getMinutes()+b),a}function o(a,b,c){c=c?-1:1;var d=a.getTimezoneOffset(),e=m(b,d);return n(a,c*(e-d))}var p,q,r=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.init=function(){p=b.id,this.parsers={},this.formatters={},q=[{key:"yyyy",regex:"\\d{4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yyyy")}},{key:"yy",regex:"\\d{2}",apply:function(a){a=+a,this.year=69>a?a+2e3:a+1900},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yy")}},{key:"y",regex:"\\d{1,4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"y")}},{key:"M!",regex:"0?[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){var b=a.getMonth();return/^[0-9]$/.test(b)?c(a,"MM"):c(a,"M")}},{key:"MMMM",regex:b.DATETIME_FORMATS.MONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.MONTH.indexOf(a)},formatter:function(a){return c(a,"MMMM")}},{key:"MMM",regex:b.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.SHORTMONTH.indexOf(a)},formatter:function(a){return c(a,"MMM")}},{key:"MM",regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"MM")}},{key:"M",regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"M")}},{key:"d!",regex:"[0-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){var b=a.getDate();return/^[1-9]$/.test(b)?c(a,"dd"):c(a,"d")}},{key:"dd",regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"dd")}},{key:"d",regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"d")}},{key:"EEEE",regex:b.DATETIME_FORMATS.DAY.join("|"),formatter:function(a){return c(a,"EEEE")}},{key:"EEE",regex:b.DATETIME_FORMATS.SHORTDAY.join("|"),formatter:function(a){return c(a,"EEE")}},{key:"HH",regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"HH")}},{key:"hh",regex:"0[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"hh")}},{key:"H",regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"H")}},{key:"h",regex:"[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"h")}},{key:"mm",regex:"[0-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"mm")}},{key:"m",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"m")}},{key:"sss",regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a},formatter:function(a){return c(a,"sss")}},{key:"ss",regex:"[0-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"ss")}},{key:"s",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"s")}},{key:"a",regex:b.DATETIME_FORMATS.AMPMS.join("|"),apply:function(a){12===this.hours&&(this.hours=0),"PM"===a&&(this.hours+=12)},formatter:function(a){return c(a,"a")}},{key:"Z",regex:"[+-]\\d{4}",apply:function(a){var b=a.match(/([+-])(\d{2})(\d{2})/),c=b[1],d=b[2],e=b[3];this.hours+=j(c+d),this.minutes+=j(c+e)},formatter:function(a){return c(a,"Z")}},{key:"ww",regex:"[0-4][0-9]|5[0-3]",formatter:function(a){return c(a,"ww")}},{key:"w",regex:"[0-9]|[1-4][0-9]|5[0-3]",formatter:function(a){return c(a,"w")}},{key:"GGGG",regex:b.DATETIME_FORMATS.ERANAMES.join("|").replace(/\s/g,"\\s"),formatter:function(a){return c(a,"GGGG")}},{key:"GGG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GGG")}},{key:"GG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GG")}},{key:"G",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"G")}}]},this.init(),this.filter=function(a,c){if(!angular.isDate(a)||isNaN(a)||!c)return"";c=b.DATETIME_FORMATS[c]||c,b.id!==p&&this.init(),this.formatters[c]||(this.formatters[c]=f(c));var d=this.formatters[c];return d.reduce(function(b,c){return b+c(a)},"")},this.parse=function(c,d,f){if(!angular.isString(c)||!d)return c;d=b.DATETIME_FORMATS[d]||d,d=d.replace(r,"\\$&"),b.id!==p&&this.init(),this.parsers[d]||(this.parsers[d]=e(d,"apply"));var g=this.parsers[d],h=g.regex,j=g.map,k=c.match(h),l=!1;if(k&&k.length){var m,n;angular.isDate(f)&&!isNaN(f.getTime())?m={year:f.getFullYear(),month:f.getMonth(),date:f.getDate(),hours:f.getHours(),minutes:f.getMinutes(),seconds:f.getSeconds(),milliseconds:f.getMilliseconds()}:(f&&a.warn("dateparser:","baseDate is not a valid date"),m={year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0});for(var o=1,q=k.length;q>o;o++){var s=j[o-1];"Z"===s.matcher&&(l=!0),s.apply&&s.apply.call(m,k[o])}var t=l?Date.prototype.setUTCFullYear:Date.prototype.setFullYear,u=l?Date.prototype.setUTCHours:Date.prototype.setHours;return i(m.year,m.month,m.date)&&(!angular.isDate(f)||isNaN(f.getTime())||l?(n=new Date(0),t.call(n,m.year,m.month,m.date),u.call(n,m.hours||0,m.minutes||0,m.seconds||0,m.milliseconds||0)):(n=new Date(f),t.call(n,m.year,m.month,m.date),u.call(n,m.hours,m.minutes,m.seconds,m.milliseconds))),n}},this.toTimezone=k,this.fromTimezone=l,this.timezoneToOffset=m,this.addDateMinutes=n,this.convertTimezoneToLocal=o}]),angular.module("ui.bootstrap.isClass",[]).directive("uibIsClass",["$animate",function(a){var b=/^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/,c=/^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;return{restrict:"A",compile:function(d,e){function f(a,b,c){i.push(a),j.push({scope:a,element:b}),o.forEach(function(b,c){g(b,a)}),a.$on("$destroy",h)}function g(b,d){var e=b.match(c),f=d.$eval(e[1]),g=e[2],h=k[b];if(!h){var i=function(b){var c=null;j.some(function(a){var d=a.scope.$eval(m);return d===b?(c=a,!0):void 0}),h.lastActivated!==c&&(h.lastActivated&&a.removeClass(h.lastActivated.element,f),c&&a.addClass(c.element,f),h.lastActivated=c)};k[b]=h={lastActivated:null,scope:d,watchFn:i,compareWithExp:g,watcher:d.$watch(g,i)}}h.watchFn(d.$eval(g))}function h(a){var b=a.targetScope,c=i.indexOf(b);if(i.splice(c,1),j.splice(c,1),i.length){var d=i[0];angular.forEach(k,function(a){a.scope===b&&(a.watcher=d.$watch(a.compareWithExp,a.watchFn),a.scope=d)})}else k={}}var i=[],j=[],k={},l=e.uibIsClass.match(b),m=l[2],n=l[1],o=n.split(",");return f}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.isClass"]).value("$datepickerSuppressError",!1).value("$datepickerLiteralWarning",!0).constant("uibDatepickerConfig",{datepickerMode:"day",formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",maxDate:null,maxMode:"year",minDate:null,minMode:"day",monthColumns:3,ngModelOptions:{},shortcutPropagation:!1,showWeeks:!0,yearColumns:5,yearRows:4}).controller("UibDatepickerController",["$scope","$element","$attrs","$parse","$interpolate","$locale","$log","dateFilter","uibDatepickerConfig","$datepickerLiteralWarning","$datepickerSuppressError","uibDateParser",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(b){a.datepickerMode=b,a.datepickerOptions.datepickerMode=b}var n=this,o={$setViewValue:angular.noop},p={},q=[];b.addClass("uib-datepicker"),c.$set("role","application"),a.datepickerOptions||(a.datepickerOptions={}),this.modes=["day","month","year"],["customClass","dateDisabled","datepickerMode","formatDay","formatDayHeader","formatDayTitle","formatMonth","formatMonthTitle","formatYear","maxDate","maxMode","minDate","minMode","monthColumns","showWeeks","shortcutPropagation","startingDay","yearColumns","yearRows"].forEach(function(b){switch(b){case"customClass":case"dateDisabled":a[b]=a.datepickerOptions[b]||angular.noop;break;case"datepickerMode":a.datepickerMode=angular.isDefined(a.datepickerOptions.datepickerMode)?a.datepickerOptions.datepickerMode:i.datepickerMode;break;case"formatDay":case"formatDayHeader":case"formatDayTitle":case"formatMonth":case"formatMonthTitle":case"formatYear":n[b]=angular.isDefined(a.datepickerOptions[b])?e(a.datepickerOptions[b])(a.$parent):i[b];break;case"monthColumns":case"showWeeks":case"shortcutPropagation":case"yearColumns":case"yearRows":n[b]=angular.isDefined(a.datepickerOptions[b])?a.datepickerOptions[b]:i[b];break;case"startingDay":angular.isDefined(a.datepickerOptions.startingDay)?n.startingDay=a.datepickerOptions.startingDay:angular.isNumber(i.startingDay)?n.startingDay=i.startingDay:n.startingDay=(f.DATETIME_FORMATS.FIRSTDAYOFWEEK+8)%7;break;case"maxDate":case"minDate":a.$watch("datepickerOptions."+b,function(a){a?angular.isDate(a)?n[b]=l.fromTimezone(new Date(a),p.timezone):(j&&g.warn("Literal date support has been deprecated, please switch to date object usage"),n[b]=new Date(h(a,"medium"))):n[b]=i[b]?l.fromTimezone(new Date(i[b]),p.timezone):null,n.refreshView()});break;case"maxMode":case"minMode":a.datepickerOptions[b]?a.$watch(function(){return a.datepickerOptions[b]},function(c){n[b]=a[b]=angular.isDefined(c)?c:a.datepickerOptions[b],("minMode"===b&&n.modes.indexOf(a.datepickerOptions.datepickerMode)<n.modes.indexOf(n[b])||"maxMode"===b&&n.modes.indexOf(a.datepickerOptions.datepickerMode)>n.modes.indexOf(n[b]))&&(a.datepickerMode=n[b],a.datepickerOptions.datepickerMode=n[b])}):n[b]=a[b]=i[b]||null}}),a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),a.disabled=angular.isDefined(c.disabled)||!1,angular.isDefined(c.ngDisabled)&&q.push(a.$parent.$watch(c.ngDisabled,function(b){a.disabled=b,n.refreshView()})),a.isActive=function(b){return 0===n.compare(b.date,n.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(b){o=b,p=b.$options||a.datepickerOptions.ngModelOptions||i.ngModelOptions,a.datepickerOptions.initDate?(n.activeDate=l.fromTimezone(a.datepickerOptions.initDate,p.timezone)||new Date,a.$watch("datepickerOptions.initDate",function(a){a&&(o.$isEmpty(o.$modelValue)||o.$invalid)&&(n.activeDate=l.fromTimezone(a,p.timezone),n.refreshView())})):n.activeDate=new Date;var c=o.$modelValue?new Date(o.$modelValue):new Date;this.activeDate=isNaN(c)?l.fromTimezone(new Date,p.timezone):l.fromTimezone(c,p.timezone),o.$render=function(){n.render()}},this.render=function(){if(o.$viewValue){var a=new Date(o.$viewValue),b=!isNaN(a);b?this.activeDate=l.fromTimezone(a,p.timezone):k||g.error('Datepicker directive: "ng-model" value must be a Date object')}this.refreshView()},this.refreshView=function(){if(this.element){a.selectedDt=null,this._refreshView(),a.activeDt&&(a.activeDateId=a.activeDt.uid);var b=o.$viewValue?new Date(o.$viewValue):null;b=l.fromTimezone(b,p.timezone),o.$setValidity("dateDisabled",!b||this.element&&!this.isDisabled(b))}},this.createDateObject=function(b,c){var d=o.$viewValue?new Date(o.$viewValue):null;d=l.fromTimezone(d,p.timezone);var e=new Date;e=l.fromTimezone(e,p.timezone);var f=this.compare(b,e),g={date:b,label:l.filter(b,c),selected:d&&0===this.compare(b,d),disabled:this.isDisabled(b),past:0>f,current:0===f,future:f>0,customClass:this.customClass(b)||null};return d&&0===this.compare(b,d)&&(a.selectedDt=g),n.activeDate&&0===this.compare(g.date,n.activeDate)&&(a.activeDt=g),g},this.isDisabled=function(b){return a.disabled||this.minDate&&this.compare(b,this.minDate)<0||this.maxDate&&this.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===n.minMode){var c=o.$viewValue?l.fromTimezone(new Date(o.$viewValue),p.timezone):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),c=l.toTimezone(c,p.timezone),o.$setViewValue(c),o.$render()}else n.activeDate=b,m(n.modes[n.modes.indexOf(a.datepickerMode)-1]),a.$emit("uib:datepicker.mode");a.$broadcast("uib:datepicker.focus")},a.move=function(a){var b=n.activeDate.getFullYear()+a*(n.step.years||0),c=n.activeDate.getMonth()+a*(n.step.months||0);n.activeDate.setFullYear(b,c,1),n.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===n.maxMode&&1===b||a.datepickerMode===n.minMode&&-1===b||(m(n.modes[n.modes.indexOf(a.datepickerMode)+b]),a.$emit("uib:datepicker.mode"))},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var r=function(){n.element[0].focus()};a.$on("uib:datepicker.focus",r),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey&&!a.disabled)if(b.preventDefault(),n.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(n.isDisabled(n.activeDate))return;a.select(n.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(n.handleKeyDown(c,b),n.refreshView()):a.toggleMode("up"===c?1:-1)},b.on("keydown",function(b){a.$apply(function(){a.keydown(b)})}),a.$on("$destroy",function(){for(;q.length;)q.shift()()})}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;b>f;)c=new Date(e),d[f++]=c,e.setDate(e.getDate()+1);return d},this._refreshView=function(){var b=this.activeDate.getFullYear(),d=this.activeDate.getMonth(),f=new Date(this.activeDate);f.setFullYear(b,d,1);var g=this.startingDay-f.getDay(),h=g>0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;42>k;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;7>l;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;n>o;o++)a.weekNumbers.push(e(a.rows[o][m].date))}},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth(),a.getDate()),d=new Date(b.getFullYear(),b.getMonth(),b.getDate());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getDate();if("left"===a)c-=1;else if("up"===a)c-=7;else if("right"===a)c+=1;else if("down"===a)c+=7;else if("pageup"===a||"pagedown"===a){var e=this.activeDate.getMonth()+("pageup"===a?-1:1);this.activeDate.setMonth(e,1),c=Math.min(d(this.activeDate.getFullYear(),this.activeDate.getMonth()),c)}else"home"===a?c=1:"end"===a&&(c=d(this.activeDate.getFullYear(),this.activeDate.getMonth()));this.activeDate.setDate(c)}}]).controller("UibMonthpickerController",["$scope","$element","dateFilter",function(a,b,c){this.step={years:1},this.element=b,this.init=function(a){angular.extend(a,this),a.refreshView()},this._refreshView=function(){for(var b,d=new Array(12),e=this.activeDate.getFullYear(),f=0;12>f;f++)b=new Date(this.activeDate),b.setFullYear(e,f,1),d[f]=angular.extend(this.createDateObject(b,this.formatMonth),{uid:a.uniqueId+"-"+f});a.title=c(this.activeDate,this.formatMonthTitle),a.rows=this.split(d,this.monthColumns),a.yearHeaderColspan=this.monthColumns>3?this.monthColumns-2:1},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth()),d=new Date(b.getFullYear(),b.getMonth());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getMonth();if("left"===a)c-=1;else if("up"===a)c-=this.monthColumns;else if("right"===a)c+=1;else if("down"===a)c+=this.monthColumns;else if("pageup"===a||"pagedown"===a){var d=this.activeDate.getFullYear()+("pageup"===a?-1:1);this.activeDate.setFullYear(d)}else"home"===a?c=0:"end"===a&&(c=11);this.activeDate.setMonth(c)}}]).controller("UibYearpickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a){return parseInt((a-1)/f,10)*f+1}var e,f;this.element=b,this.yearpickerInit=function(){e=this.yearColumns,f=this.yearRows*e,this.step={years:f}},this._refreshView=function(){for(var b,c=new Array(f),g=0,h=d(this.activeDate.getFullYear());f>g;g++)b=new Date(this.activeDate),b.setFullYear(h+g,0,1),c[g]=angular.extend(this.createDateObject(b,this.formatYear),{uid:a.uniqueId+"-"+g});a.title=[c[0].label,c[f-1].label].join(" - "),a.rows=this.split(c,e),a.columns=e},this.compare=function(a,b){return a.getFullYear()-b.getFullYear()},this.handleKeyDown=function(a,b){var c=this.activeDate.getFullYear();"left"===a?c-=1:"up"===a?c-=e:"right"===a?c+=1:"down"===a?c+=e:"pageup"===a||"pagedown"===a?c+=("pageup"===a?-1:1)*f:"home"===a?c=d(this.activeDate.getFullYear()):"end"===a&&(c=d(this.activeDate.getFullYear())+f-1),this.activeDate.setFullYear(c)}}]).directive("uibDatepicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/datepicker.html"},scope:{datepickerOptions:"=?"},require:["uibDatepicker","^ngModel"],restrict:"A",controller:"UibDatepickerController",controllerAs:"datepicker",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}).directive("uibDaypicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/day.html"},require:["^uibDatepicker","uibDaypicker"],restrict:"A",controller:"UibDaypickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibMonthpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/month.html"},require:["^uibDatepicker","uibMonthpicker"],restrict:"A",controller:"UibMonthpickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibYearpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/year.html"},require:["^uibDatepicker","uibYearpicker"],restrict:"A",controller:"UibYearpickerController",link:function(a,b,c,d){var e=d[0];angular.extend(e,d[1]),e.yearpickerInit(),e.refreshView()}}}),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(a,b){var c,d,e={normal:/(auto|scroll)/,hidden:/(auto|scroll|hidden)/},f={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/},g=/(HTML|BODY)/;return{getRawNode:function(a){return a.nodeName?a:a[0]||a},parseStyle:function(a){return a=parseFloat(a),isFinite(a)?a:0},offsetParent:function(c){function d(a){return"static"===(b.getComputedStyle(a).position||"static")}c=this.getRawNode(c);for(var e=c.offsetParent||a[0].documentElement;e&&e!==a[0].documentElement&&d(e);)e=e.offsetParent;return e||a[0].documentElement},scrollbarWidth:function(e){if(e){if(angular.isUndefined(d)){var f=a.find("body");f.addClass("uib-position-body-scrollbar-measure"),d=b.innerWidth-f[0].clientWidth,d=isFinite(d)?d:0,f.removeClass("uib-position-body-scrollbar-measure")}return d}if(angular.isUndefined(c)){var g=angular.element('<div class="uib-position-scrollbar-measure"></div>');a.find("body").append(g),c=g[0].offsetWidth-g[0].clientWidth,c=isFinite(c)?c:0,g.remove()}return c},scrollbarPadding:function(a){a=this.getRawNode(a);var c=b.getComputedStyle(a),d=this.parseStyle(c.paddingRight),e=this.parseStyle(c.paddingBottom),f=this.scrollParent(a,!1,!0),h=this.scrollbarWidth(g.test(f.tagName));
return{scrollbarWidth:h,widthOverflow:f.scrollWidth>f.clientWidth,right:d+h,originalRight:d,heightOverflow:f.scrollHeight>f.clientHeight,bottom:e+h,originalBottom:e}},isScrollable:function(a,c){a=this.getRawNode(a);var d=c?e.hidden:e.normal,f=b.getComputedStyle(a);return d.test(f.overflow+f.overflowY+f.overflowX)},scrollParent:function(c,d,f){c=this.getRawNode(c);var g=d?e.hidden:e.normal,h=a[0].documentElement,i=b.getComputedStyle(c);if(f&&g.test(i.overflow+i.overflowY+i.overflowX))return c;var j="absolute"===i.position,k=c.parentElement||h;if(k===h||"fixed"===i.position)return h;for(;k.parentElement&&k!==h;){var l=b.getComputedStyle(k);if(j&&"static"!==l.position&&(j=!1),!j&&g.test(l.overflow+l.overflowY+l.overflowX))break;k=k.parentElement}return k},position:function(c,d){c=this.getRawNode(c);var e=this.offset(c);if(d){var f=b.getComputedStyle(c);e.top-=this.parseStyle(f.marginTop),e.left-=this.parseStyle(f.marginLeft)}var g=this.offsetParent(c),h={top:0,left:0};return g!==a[0].documentElement&&(h=this.offset(g),h.top+=g.clientTop-g.scrollTop,h.left+=g.clientLeft-g.scrollLeft),{width:Math.round(angular.isNumber(e.width)?e.width:c.offsetWidth),height:Math.round(angular.isNumber(e.height)?e.height:c.offsetHeight),top:Math.round(e.top-h.top),left:Math.round(e.left-h.left)}},offset:function(c){c=this.getRawNode(c);var d=c.getBoundingClientRect();return{width:Math.round(angular.isNumber(d.width)?d.width:c.offsetWidth),height:Math.round(angular.isNumber(d.height)?d.height:c.offsetHeight),top:Math.round(d.top+(b.pageYOffset||a[0].documentElement.scrollTop)),left:Math.round(d.left+(b.pageXOffset||a[0].documentElement.scrollLeft))}},viewportOffset:function(c,d,e){c=this.getRawNode(c),e=e!==!1;var f=c.getBoundingClientRect(),g={top:0,left:0,bottom:0,right:0},h=d?a[0].documentElement:this.scrollParent(c),i=h.getBoundingClientRect();if(g.top=i.top+h.clientTop,g.left=i.left+h.clientLeft,h===a[0].documentElement&&(g.top+=b.pageYOffset,g.left+=b.pageXOffset),g.bottom=g.top+h.clientHeight,g.right=g.left+h.clientWidth,e){var j=b.getComputedStyle(h);g.top+=this.parseStyle(j.paddingTop),g.bottom-=this.parseStyle(j.paddingBottom),g.left+=this.parseStyle(j.paddingLeft),g.right-=this.parseStyle(j.paddingRight)}return{top:Math.round(f.top-g.top),bottom:Math.round(g.bottom-f.bottom),left:Math.round(f.left-g.left),right:Math.round(g.right-f.right)}},parsePlacement:function(a){var b=f.auto.test(a);return b&&(a=a.replace(f.auto,"")),a=a.split("-"),a[0]=a[0]||"top",f.primary.test(a[0])||(a[0]="top"),a[1]=a[1]||"center",f.secondary.test(a[1])||(a[1]="center"),b?a[2]=!0:a[2]=!1,a},positionElements:function(a,c,d,e){a=this.getRawNode(a),c=this.getRawNode(c);var g=angular.isDefined(c.offsetWidth)?c.offsetWidth:c.prop("offsetWidth"),h=angular.isDefined(c.offsetHeight)?c.offsetHeight:c.prop("offsetHeight");d=this.parsePlacement(d);var i=e?this.offset(a):this.position(a),j={top:0,left:0,placement:""};if(d[2]){var k=this.viewportOffset(a,e),l=b.getComputedStyle(c),m={width:g+Math.round(Math.abs(this.parseStyle(l.marginLeft)+this.parseStyle(l.marginRight))),height:h+Math.round(Math.abs(this.parseStyle(l.marginTop)+this.parseStyle(l.marginBottom)))};if(d[0]="top"===d[0]&&m.height>k.top&&m.height<=k.bottom?"bottom":"bottom"===d[0]&&m.height>k.bottom&&m.height<=k.top?"top":"left"===d[0]&&m.width>k.left&&m.width<=k.right?"right":"right"===d[0]&&m.width>k.right&&m.width<=k.left?"left":d[0],d[1]="top"===d[1]&&m.height-i.height>k.bottom&&m.height-i.height<=k.top?"bottom":"bottom"===d[1]&&m.height-i.height>k.top&&m.height-i.height<=k.bottom?"top":"left"===d[1]&&m.width-i.width>k.right&&m.width-i.width<=k.left?"right":"right"===d[1]&&m.width-i.width>k.left&&m.width-i.width<=k.right?"left":d[1],"center"===d[1])if(f.vertical.test(d[0])){var n=i.width/2-g/2;k.left+n<0&&m.width-i.width<=k.right?d[1]="left":k.right+n<0&&m.width-i.width<=k.left&&(d[1]="right")}else{var o=i.height/2-m.height/2;k.top+o<0&&m.height-i.height<=k.bottom?d[1]="top":k.bottom+o<0&&m.height-i.height<=k.top&&(d[1]="bottom")}}switch(d[0]){case"top":j.top=i.top-h;break;case"bottom":j.top=i.top+i.height;break;case"left":j.left=i.left-g;break;case"right":j.left=i.left+i.width}switch(d[1]){case"top":j.top=i.top;break;case"bottom":j.top=i.top+i.height-h;break;case"left":j.left=i.left;break;case"right":j.left=i.left+i.width-g;break;case"center":f.vertical.test(d[0])?j.left=i.left+i.width/2-g/2:j.top=i.top+i.height/2-h/2}return j.top=Math.round(j.top),j.left=Math.round(j.left),j.placement="center"===d[1]?d[0]:d[0]+"-"+d[1],j},adjustTop:function(a,b,c,d){return-1!==a.indexOf("top")&&c!==d?{top:b.top-d+"px"}:void 0},positionArrow:function(a,c){a=this.getRawNode(a);var d=a.querySelector(".tooltip-inner, .popover-inner");if(d){var e=angular.element(d).hasClass("tooltip-inner"),g=e?a.querySelector(".tooltip-arrow"):a.querySelector(".arrow");if(g){var h={top:"",bottom:"",left:"",right:""};if(c=this.parsePlacement(c),"center"===c[1])return void angular.element(g).css(h);var i="border-"+c[0]+"-width",j=b.getComputedStyle(g)[i],k="border-";k+=f.vertical.test(c[0])?c[0]+"-"+c[1]:c[1]+"-"+c[0],k+="-radius";var l=b.getComputedStyle(e?d:a)[k];switch(c[0]){case"top":h.bottom=e?"0":"-"+j;break;case"bottom":h.top=e?"0":"-"+j;break;case"left":h.right=e?"0":"-"+j;break;case"right":h.left=e?"0":"-"+j}h[c[1]]=l,angular.element(g).css(h)}}}}}]),angular.module("ui.bootstrap.datepickerPopup",["ui.bootstrap.datepicker","ui.bootstrap.position"]).value("$datepickerPopupLiteralWarning",!0).constant("uibDatepickerPopupConfig",{altInputFormats:[],appendToBody:!1,clearText:"Clear",closeOnDateSelection:!0,closeText:"Done",currentText:"Today",datepickerPopup:"yyyy-MM-dd",datepickerPopupTemplateUrl:"uib/template/datepickerPopup/popup.html",datepickerTemplateUrl:"uib/template/datepicker/datepicker.html",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},onOpenFocus:!0,showButtonBar:!0,placement:"auto bottom-left"}).controller("UibDatepickerPopupController",["$scope","$element","$attrs","$compile","$log","$parse","$window","$document","$rootScope","$uibPosition","dateFilter","uibDateParser","uibDatepickerPopupConfig","$timeout","uibDatepickerConfig","$datepickerPopupLiteralWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){function q(b){var c=l.parse(b,w,a.date);if(isNaN(c))for(var d=0;d<I.length;d++)if(c=l.parse(b,I[d],a.date),!isNaN(c))return c;return c}function r(a){if(angular.isNumber(a)&&(a=new Date(a)),!a)return null;if(angular.isDate(a)&&!isNaN(a))return a;if(angular.isString(a)){var b=q(a);if(!isNaN(b))return l.fromTimezone(b,G.timezone)}return F.$options&&F.$options.allowInvalid?a:void 0}function s(a,b){var d=a||b;return c.ngRequired||d?(angular.isNumber(d)&&(d=new Date(d)),d?angular.isDate(d)&&!isNaN(d)?!0:angular.isString(d)?!isNaN(q(d)):!1:!0):!0}function t(c){if(a.isOpen||!a.disabled){var d=H[0],e=b[0].contains(c.target),f=void 0!==d.contains&&d.contains(c.target);!a.isOpen||e||f||a.$apply(function(){a.isOpen=!1})}}function u(c){27===c.which&&a.isOpen?(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!1}),b[0].focus()):40!==c.which||a.isOpen||(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!0}))}function v(){if(a.isOpen){var d=angular.element(H[0].querySelector(".uib-datepicker-popup")),e=c.popupPlacement?c.popupPlacement:m.placement,f=j.positionElements(b,d,e,y);d.css({top:f.top+"px",left:f.left+"px"}),d.hasClass("uib-position-measure")&&d.removeClass("uib-position-measure")}}var w,x,y,z,A,B,C,D,E,F,G,H,I,J=!1,K=[];this.init=function(e){if(F=e,G=angular.isObject(e.$options)?e.$options:{timezone:null},x=angular.isDefined(c.closeOnDateSelection)?a.$parent.$eval(c.closeOnDateSelection):m.closeOnDateSelection,y=angular.isDefined(c.datepickerAppendToBody)?a.$parent.$eval(c.datepickerAppendToBody):m.appendToBody,z=angular.isDefined(c.onOpenFocus)?a.$parent.$eval(c.onOpenFocus):m.onOpenFocus,A=angular.isDefined(c.datepickerPopupTemplateUrl)?c.datepickerPopupTemplateUrl:m.datepickerPopupTemplateUrl,B=angular.isDefined(c.datepickerTemplateUrl)?c.datepickerTemplateUrl:m.datepickerTemplateUrl,I=angular.isDefined(c.altInputFormats)?a.$parent.$eval(c.altInputFormats):m.altInputFormats,a.showButtonBar=angular.isDefined(c.showButtonBar)?a.$parent.$eval(c.showButtonBar):m.showButtonBar,m.html5Types[c.type]?(w=m.html5Types[c.type],J=!0):(w=c.uibDatepickerPopup||m.datepickerPopup,c.$observe("uibDatepickerPopup",function(a,b){var c=a||m.datepickerPopup;if(c!==w&&(w=c,F.$modelValue=null,!w))throw new Error("uibDatepickerPopup must have a date format specified.")})),!w)throw new Error("uibDatepickerPopup must have a date format specified.");if(J&&c.uibDatepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");C=angular.element("<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>"),C.attr({"ng-model":"date","ng-change":"dateSelection(date)","template-url":A}),D=angular.element(C.children()[0]),D.attr("template-url",B),a.datepickerOptions||(a.datepickerOptions={}),J&&"month"===c.type&&(a.datepickerOptions.datepickerMode="month",a.datepickerOptions.minMode="month"),D.attr("datepicker-options","datepickerOptions"),J?F.$formatters.push(function(b){return a.date=l.fromTimezone(b,G.timezone),b}):(F.$$parserName="date",F.$validators.date=s,F.$parsers.unshift(r),F.$formatters.push(function(b){return F.$isEmpty(b)?(a.date=b,b):(angular.isNumber(b)&&(b=new Date(b)),a.date=l.fromTimezone(b,G.timezone),l.filter(a.date,w))})),F.$viewChangeListeners.push(function(){a.date=q(F.$viewValue)}),b.on("keydown",u),H=d(C)(a),C.remove(),y?h.find("body").append(H):b.after(H),a.$on("$destroy",function(){for(a.isOpen===!0&&(i.$$phase||a.$apply(function(){a.isOpen=!1})),H.remove(),b.off("keydown",u),h.off("click",t),E&&E.off("scroll",v),angular.element(g).off("resize",v);K.length;)K.shift()()})},a.getText=function(b){return a[b+"Text"]||m[b+"Text"]},a.isDisabled=function(b){"today"===b&&(b=l.fromTimezone(new Date,G.timezone));var c={};return angular.forEach(["minDate","maxDate"],function(b){a.datepickerOptions[b]?angular.isDate(a.datepickerOptions[b])?c[b]=new Date(a.datepickerOptions[b]):(p&&e.warn("Literal date support has been deprecated, please switch to date object usage"),c[b]=new Date(k(a.datepickerOptions[b],"medium"))):c[b]=null}),a.datepickerOptions&&c.minDate&&a.compare(b,c.minDate)<0||c.maxDate&&a.compare(b,c.maxDate)>0},a.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},a.dateSelection=function(c){a.date=c;var d=a.date?l.filter(a.date,w):null;b.val(d),F.$setViewValue(d),x&&(a.isOpen=!1,b[0].focus())},a.keydown=function(c){27===c.which&&(c.stopPropagation(),a.isOpen=!1,b[0].focus())},a.select=function(b,c){if(c.stopPropagation(),"today"===b){var d=new Date;angular.isDate(a.date)?(b=new Date(a.date),b.setFullYear(d.getFullYear(),d.getMonth(),d.getDate())):(b=l.fromTimezone(d,G.timezone),b.setHours(0,0,0,0))}a.dateSelection(b)},a.close=function(c){c.stopPropagation(),a.isOpen=!1,b[0].focus()},a.disabled=angular.isDefined(c.disabled)||!1,c.ngDisabled&&K.push(a.$parent.$watch(f(c.ngDisabled),function(b){a.disabled=b})),a.$watch("isOpen",function(d){d?a.disabled?a.isOpen=!1:n(function(){v(),z&&a.$broadcast("uib:datepicker.focus"),h.on("click",t);var d=c.popupPlacement?c.popupPlacement:m.placement;y||j.parsePlacement(d)[2]?(E=E||angular.element(j.scrollParent(b)),E&&E.on("scroll",v)):E=null,angular.element(g).on("resize",v)},0,!1):(h.off("click",t),E&&E.off("scroll",v),angular.element(g).off("resize",v))}),a.$on("uib:datepicker.mode",function(){n(v,0,!1)})}]).directive("uibDatepickerPopup",function(){return{require:["ngModel","uibDatepickerPopup"],controller:"UibDatepickerPopupController",scope:{datepickerOptions:"=?",isOpen:"=?",currentText:"@",clearText:"@",closeText:"@"},link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibDatepickerPopupWrap",function(){return{restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/datepickerPopup/popup.html"}}}),angular.module("ui.bootstrap.debounce",[]).factory("$$debounce",["$timeout",function(a){return function(b,c){var d;return function(){var e=this,f=Array.prototype.slice.call(arguments);d&&a.cancel(d),d=a(function(){b.apply(e,f)},c)}}}]),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("uibDropdownConfig",{appendToOpenClass:"uib-dropdown-open",openClass:"open"}).service("uibDropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b,e){c||a.on("click",d),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b,e){c===b&&(a.off("click",d),a.off("keydown",this.keybindFilter),c=null)};var d=function(a){if(c&&!(a&&"disabled"===c.getAutoClose()||a&&3===a.which)){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getDropdownElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.focusToggleElement(),c.isOpen=!1,b.$$phase||c.$apply())}}};this.keybindFilter=function(a){if(c){var b=c.getDropdownElement(),e=c.getToggleElement(),f=b&&b[0].contains(a.target),g=e&&e[0].contains(a.target);27===a.which?(a.stopPropagation(),c.focusToggleElement(),d()):c.isKeynavEnabled()&&-1!==[38,40].indexOf(a.which)&&c.isOpen&&(f||g)&&(a.preventDefault(),a.stopPropagation(),c.focusDropdownEntry(a.which))}}}]).controller("UibDropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest",function(a,b,c,d,e,f,g,h,i,j,k){var l,m,n=this,o=a.$new(),p=e.appendToOpenClass,q=e.openClass,r=angular.noop,s=c.onToggle?d(c.onToggle):angular.noop,t=!1,u=null,v=!1,w=i.find("body");b.addClass("dropdown"),this.init=function(){if(c.isOpen&&(m=d(c.isOpen),r=m.assign,a.$watch(m,function(a){o.isOpen=!!a})),angular.isDefined(c.dropdownAppendTo)){var e=d(c.dropdownAppendTo)(o);e&&(u=angular.element(e))}t=angular.isDefined(c.dropdownAppendToBody),v=angular.isDefined(c.keyboardNav),t&&!u&&(u=w),u&&n.dropdownMenu&&(u.append(n.dropdownMenu),b.on("$destroy",function(){n.dropdownMenu.remove()}))},this.toggle=function(a){return o.isOpen=arguments.length?!!a:!o.isOpen,angular.isFunction(r)&&r(o,o.isOpen),o.isOpen},this.isOpen=function(){return o.isOpen},o.getToggleElement=function(){return n.toggleElement},o.getAutoClose=function(){return c.autoClose||"always"},o.getElement=function(){return b},o.isKeynavEnabled=function(){return v},o.focusDropdownEntry=function(a){var c=n.dropdownMenu?angular.element(n.dropdownMenu).find("a"):b.find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(n.selectedOption)?n.selectedOption=n.selectedOption===c.length-1?n.selectedOption:n.selectedOption+1:n.selectedOption=0;break;case 38:angular.isNumber(n.selectedOption)?n.selectedOption=0===n.selectedOption?0:n.selectedOption-1:n.selectedOption=c.length-1}c[n.selectedOption].focus()},o.getDropdownElement=function(){return n.dropdownMenu},o.focusToggleElement=function(){n.toggleElement&&n.toggleElement[0].focus()},o.$watch("isOpen",function(c,d){if(u&&n.dropdownMenu){var e,m,v,w=h.positionElements(b,n.dropdownMenu,"bottom-left",!0),x=0;if(e={top:w.top+"px",display:c?"block":"none"},m=n.dropdownMenu.hasClass("dropdown-menu-right"),m?(e.left="auto",v=h.scrollbarPadding(u),v.heightOverflow&&v.scrollbarWidth&&(x=v.scrollbarWidth),e.right=window.innerWidth-x-(w.left+b.prop("offsetWidth"))+"px"):(e.left=w.left+"px",e.right="auto"),!t){var y=h.offset(u);e.top=w.top-y.top+"px",m?e.right=window.innerWidth-(w.left-y.left+b.prop("offsetWidth"))+"px":e.left=w.left-y.left+"px"}n.dropdownMenu.css(e)}var z=u?u:b,A=z.hasClass(u?p:q);if(A===!c&&g[c?"addClass":"removeClass"](z,u?p:q).then(function(){angular.isDefined(c)&&c!==d&&s(a,{open:!!c})}),c)n.dropdownMenuTemplateUrl?k(n.dropdownMenuTemplateUrl).then(function(a){l=o.$new(),j(a.trim())(l,function(a){var b=a;n.dropdownMenu.replaceWith(b),n.dropdownMenu=b,i.on("keydown",f.keybindFilter)})}):i.on("keydown",f.keybindFilter),o.focusToggleElement(),f.open(o,b);else{if(f.close(o,b),n.dropdownMenuTemplateUrl){l&&l.$destroy();var B=angular.element('<ul class="dropdown-menu"></ul>');n.dropdownMenu.replaceWith(B),n.dropdownMenu=B}n.selectedOption=null}angular.isFunction(r)&&r(a,c)})}]).directive("uibDropdown",function(){return{controller:"UibDropdownController",link:function(a,b,c,d){d.init()}}}).directive("uibDropdownMenu",function(){return{restrict:"A",require:"?^uibDropdown",link:function(a,b,c,d){if(d&&!angular.isDefined(c.dropdownNested)){b.addClass("dropdown-menu");var e=c.templateUrl;e&&(d.dropdownMenuTemplateUrl=e),d.dropdownMenu||(d.dropdownMenu=b)}}}}).directive("uibDropdownToggle",function(){return{require:"?^uibDropdown",link:function(a,b,c,d){if(d){b.addClass("dropdown-toggle"),d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b===a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b===a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.pop()},length:function(){return a.length}}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.stackedMap","ui.bootstrap.position"]).factory("$$multiMap",function(){return{createNew:function(){var a={};return{entries:function(){return Object.keys(a).map(function(b){return{key:b,value:a[b]}})},get:function(b){return a[b]},hasKey:function(b){return!!a[b]},keys:function(){return Object.keys(a)},put:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},remove:function(b,c){var d=a[b];if(d){var e=d.indexOf(c);-1!==e&&d.splice(e,1),d.length||delete a[b]}}}}}}).provider("$uibResolve",function(){var a=this;this.resolver=null,this.setResolver=function(a){this.resolver=a},this.$get=["$injector","$q",function(b,c){var d=a.resolver?b.get(a.resolver):null;return{resolve:function(a,e,f,g){if(d)return d.resolve(a,e,f,g);var h=[];return angular.forEach(a,function(a){angular.isFunction(a)||angular.isArray(a)?h.push(c.resolve(b.invoke(a))):angular.isString(a)?h.push(c.resolve(b.get(a))):h.push(c.resolve(a))}),c.all(h).then(function(b){var c={},d=0;return angular.forEach(a,function(a,e){c[e]=b[d++]}),c})}}}]}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(a,b,c){function d(b,d,e){e.modalInClass&&(a.addClass(d,e.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(c,f){var g=f();b.modalOptions.animation?a.removeClass(d,e.modalInClass).then(g):g()}))}return{restrict:"A",compile:function(a,b){return a.addClass(b.backdropClass),d}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animateCss","$document",function(a,b,c,d){return{scope:{index:"@"},restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/modal/window.html"},link:function(e,f,g){f.addClass(g.windowTopClass||""),e.size=g.size,e.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},f.on("click",e.close),e.$isRendered=!0;var h=b.defer();e.$$postDigest(function(){h.resolve()}),h.promise.then(function(){var h=null;g.modalInClass&&(h=c(f,{addClass:g.modalInClass}).start(),e.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();c(f,{removeClass:g.modalInClass}).start().then(d)})),b.when(h).then(function(){var b=a.getTop();if(b&&a.modalRendered(b.key),!d[0].activeElement||!f[0].contains(d[0].activeElement)){var c=f[0].querySelector("[autofocus]");c?c.focus():f[0].focus()}})})}}}]).directive("uibModalAnimationClass",function(){return{compile:function(a,b){b.modalAnimation&&a.addClass(b.uibModalAnimationClass)}}}).directive("uibModalTransclude",["$animate",function(a){return{link:function(b,c,d,e,f){f(b.$parent,function(b){c.empty(),a.enter(b,c)})}}}]).factory("$uibModalStack",["$animate","$animateCss","$document","$compile","$rootScope","$q","$$multiMap","$$stackedMap","$uibPosition",function(a,b,c,d,e,f,g,h,i){function j(a){var b="-";return a.replace(E,function(a,c){return(c?b:"")+a.toLowerCase()})}function k(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)}function l(){for(var a=-1,b=x.keys(),c=0;c<b.length;c++)x.get(b[c]).value.backdrop&&(a=c);return a>-1&&A>a&&(a=A),a}function m(a,b){var c=x.get(a).value,d=c.appendTo;x.remove(a),B=x.top(),B&&(A=parseInt(B.value.modalDomEl.attr("index"),10)),p(c.modalDomEl,c.modalScope,function(){var b=c.openedClass||w;y.remove(b,a);var e=y.hasKey(b);d.toggleClass(b,e),!e&&v&&v.heightOverflow&&v.scrollbarWidth&&(v.originalRight?d.css({paddingRight:v.originalRight+"px"}):d.css({paddingRight:""}),v=null),n(!0)},c.closedDeferred),o(),b&&b.focus?b.focus():d.focus&&d.focus()}function n(a){var b;x.length()>0&&(b=x.top().value,b.modalDomEl.toggleClass(b.windowTopClass||"",a))}function o(){if(t&&-1===l()){var a=u;p(t,u,function(){a=null}),t=void 0,u=void 0}}function p(b,c,d,e){function g(){g.done||(g.done=!0,a.leave(b).then(function(){d&&d(),b.remove(),e&&e.resolve()}),c.$destroy())}var h,i=null,j=function(){return h||(h=f.defer(),i=h.promise),function(){h.resolve()}};return c.$broadcast(z.NOW_CLOSING_EVENT,j),f.when(i).then(g)}function q(a){if(a.isDefaultPrevented())return a;var b=x.top();if(b)switch(a.which){case 27:b.value.keyboard&&(a.preventDefault(),e.$apply(function(){z.dismiss(b.key,"escape key press")}));break;case 9:var c=z.loadFocusElementList(b),d=!1;a.shiftKey?(z.isFocusInFirstItem(a,c)||z.isModalFocused(a,b))&&(d=z.focusLastFocusableElement(c)):z.isFocusInLastItem(a,c)&&(d=z.focusFirstFocusableElement(c)),d&&(a.preventDefault(),a.stopPropagation())}}function r(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}function s(){Array.prototype.forEach.call(document.querySelectorAll("["+C+"]"),function(a){var b=parseInt(a.getAttribute(C),10),c=b-1;a.setAttribute(C,c),c||(a.removeAttribute(C),a.removeAttribute("aria-hidden"))})}var t,u,v,w="modal-open",x=h.createNew(),y=g.createNew(),z={NOW_CLOSING_EVENT:"modal.stack.now-closing"},A=0,B=null,C="data-bootstrap-modal-aria-hidden-count",D="a[href], area[href], input:not([disabled]):not([tabindex='-1']), button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']), textarea:not([disabled]):not([tabindex='-1']), iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]",E=/[A-Z]/g;return e.$watch(l,function(a){u&&(u.index=a)}),c.on("keydown",q),e.$on("$destroy",function(){c.off("keydown",q)}),z.open=function(b,f){function g(a){function b(a){var b=a.parent()?a.parent().children():[];return Array.prototype.filter.call(b,function(b){return b!==a[0]})}if(a&&"BODY"!==a[0].tagName)return b(a).forEach(function(a){var b="true"===a.getAttribute("aria-hidden"),c=parseInt(a.getAttribute(C),10);c||(c=b?1:0),a.setAttribute(C,c+1),a.setAttribute("aria-hidden","true")}),g(a.parent())}var h=c[0].activeElement,k=f.openedClass||w;n(!1),B=x.top(),x.add(b,{deferred:f.deferred,renderDeferred:f.renderDeferred,closedDeferred:f.closedDeferred,modalScope:f.scope,backdrop:f.backdrop,keyboard:f.keyboard,openedClass:f.openedClass,windowTopClass:f.windowTopClass,animation:f.animation,appendTo:f.appendTo}),y.put(k,b);var m=f.appendTo,o=l();if(!m.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");o>=0&&!t&&(u=e.$new(!0),u.modalOptions=f,u.index=o,t=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>'),t.attr({"class":"modal-backdrop","ng-style":"{'z-index': 1040 + (index && 1 || 0) + index*10}","uib-modal-animation-class":"fade","modal-in-class":"in"}),f.backdropClass&&t.addClass(f.backdropClass),f.animation&&t.attr("modal-animation","true"),d(t)(u),a.enter(t,m),i.isScrollable(m)&&(v=i.scrollbarPadding(m),v.heightOverflow&&v.scrollbarWidth&&m.css({paddingRight:v.right+"px"})));var p;f.component?(p=document.createElement(j(f.component.name)),p=angular.element(p),p.attr({resolve:"$resolve","modal-instance":"$uibModalInstance",close:"$close($value)",dismiss:"$dismiss($value)"})):p=f.content,A=B?parseInt(B.value.modalDomEl.attr("index"),10)+1:0;var q=angular.element('<div uib-modal-window="modal-window"></div>');q.attr({"class":"modal","template-url":f.windowTemplateUrl,"window-top-class":f.windowTopClass,role:"dialog","aria-labelledby":f.ariaLabelledBy,"aria-describedby":f.ariaDescribedBy,size:f.size,index:A,animate:"animate","ng-style":"{'z-index': 1050 + $$topModalIndex*10, display: 'block'}",tabindex:-1,"uib-modal-animation-class":"fade","modal-in-class":"in"}).append(p),f.windowClass&&q.addClass(f.windowClass),f.animation&&q.attr("modal-animation","true"),m.addClass(k),f.scope&&(f.scope.$$topModalIndex=A),a.enter(d(q)(f.scope),m),x.top().value.modalDomEl=q,x.top().value.modalOpener=h,g(q)},z.close=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!0)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.resolve(b),m(a,c.value.modalOpener),!0):!c},z.dismiss=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!1)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.reject(b),m(a,c.value.modalOpener),!0):!c},z.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},z.getTop=function(){return x.top()},z.modalRendered=function(a){var b=x.get(a);z.focusFirstFocusableElement(z.loadFocusElementList(b)),b&&b.value.renderDeferred.resolve()},z.focusFirstFocusableElement=function(a){return a.length>0?(a[0].focus(),!0):!1},z.focusLastFocusableElement=function(a){return a.length>0?(a[a.length-1].focus(),!0):!1},z.isModalFocused=function(a,b){if(a&&b){var c=b.value.modalDomEl;if(c&&c.length)return(a.target||a.srcElement)===c[0]}return!1},z.isFocusInFirstItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[0]:!1},z.isFocusInLastItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[b.length-1]:!1},z.loadFocusElementList=function(a){if(a){var b=a.value.modalDomEl;if(b&&b.length){var c=b[0].querySelectorAll(D);return c?Array.prototype.filter.call(c,function(a){return k(a)}):c}}},z}]).provider("$uibModal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$uibResolve","$uibModalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?c.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}var j={},k=null;return j.getPromiseChain=function(){return k},j.open=function(e){function j(){return q}var l=c.defer(),m=c.defer(),n=c.defer(),o=c.defer(),p={result:l.promise,opened:m.promise,closed:n.promise,rendered:o.promise,close:function(a){return h.close(p,a)},dismiss:function(a){return h.dismiss(p,a)}};if(e=angular.extend({},a.options,e),e.resolve=e.resolve||{},e.appendTo=e.appendTo||d.find("body").eq(0),!e.component&&!e.template&&!e.templateUrl)throw new Error("One of component or template or templateUrl options is required.");var q;q=e.component?c.when(g.resolve(e.resolve,{},null,null)):c.all([i(e),g.resolve(e.resolve,{},null,null)]);var r;return r=k=c.all([k]).then(j,j).then(function(a){function c(b,c,d,e){b.$scope=g,b.$scope.$resolve={},d?b.$scope.$uibModalInstance=p:b.$uibModalInstance=p;var f=c?a[1]:a;angular.forEach(f,function(a,c){e&&(b[c]=a),b.$scope.$resolve[c]=a})}var d=e.scope||b,g=d.$new();g.$close=p.close,g.$dismiss=p.dismiss,g.$on("$destroy",function(){g.$$uibDestructionScheduled||g.$dismiss("$uibUnscheduledDestruction")});var i,j,k={scope:g,deferred:l,renderDeferred:o,closedDeferred:n,animation:e.animation,backdrop:e.backdrop,keyboard:e.keyboard,backdropClass:e.backdropClass,windowTopClass:e.windowTopClass,windowClass:e.windowClass,windowTemplateUrl:e.windowTemplateUrl,ariaLabelledBy:e.ariaLabelledBy,ariaDescribedBy:e.ariaDescribedBy,size:e.size,openedClass:e.openedClass,appendTo:e.appendTo},q={},r={};e.component?(c(q,!1,!0,!1),q.name=e.component,k.component=q):e.controller&&(c(r,!0,!1,!0),j=f(e.controller,r,!0,e.controllerAs),e.controllerAs&&e.bindToController&&(i=j.instance,i.$close=g.$close,i.$dismiss=g.$dismiss,angular.extend(i,{$resolve:r.$scope.$resolve},d)),i=j(),angular.isFunction(i.$onInit)&&i.$onInit()),e.component||(k.content=a[0]),h.open(p,k),m.resolve(!0)},function(a){m.reject(a),l.reject(a)})["finally"](function(){k===r&&(k=null)}),p},j}]};return a}),angular.module("ui.bootstrap.paging",[]).factory("uibPaging",["$parse",function(a){return{create:function(b,c,d){b.setNumPages=d.numPages?a(d.numPages).assign:angular.noop,b.ngModelCtrl={$setViewValue:angular.noop},b._watchers=[],b.init=function(a,e){b.ngModelCtrl=a,b.config=e,a.$render=function(){b.render()},d.itemsPerPage?b._watchers.push(c.$parent.$watch(d.itemsPerPage,function(a){b.itemsPerPage=parseInt(a,10),c.totalPages=b.calculateTotalPages(),b.updatePage()})):b.itemsPerPage=e.itemsPerPage,c.$watch("totalItems",function(a,d){(angular.isDefined(a)||a!==d)&&(c.totalPages=b.calculateTotalPages(),b.updatePage())})},b.calculateTotalPages=function(){var a=b.itemsPerPage<1?1:Math.ceil(c.totalItems/b.itemsPerPage);return Math.max(a||0,1)},b.render=function(){c.page=parseInt(b.ngModelCtrl.$viewValue,10)||1},c.selectPage=function(a,d){d&&d.preventDefault();var e=!c.ngDisabled||!d;e&&c.page!==a&&a>0&&a<=c.totalPages&&(d&&d.target&&d.target.blur(),b.ngModelCtrl.$setViewValue(a),b.ngModelCtrl.$render())},c.getText=function(a){return c[a+"Text"]||b.config[a+"Text"]},c.noPrevious=function(){return 1===c.page},c.noNext=function(){return c.page===c.totalPages},b.updatePage=function(){b.setNumPages(c.$parent,c.totalPages),c.page>c.totalPages?c.selectPage(c.totalPages):b.ngModelCtrl.$render()},c.$on("$destroy",function(){for(;b._watchers.length;)b._watchers.shift()()})}}}]),angular.module("ui.bootstrap.pager",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPagerController",["$scope","$attrs","uibPaging","uibPagerConfig",function(a,b,c,d){a.align=angular.isDefined(b.align)?a.$parent.$eval(b.align):d.align,c.create(this,a,b)}]).constant("uibPagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("uibPager",["uibPagerConfig",function(a){return{scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["uibPager","?ngModel"],restrict:"A",controller:"UibPagerController",controllerAs:"pager",templateUrl:function(a,b){return b.templateUrl||"uib/template/pager/pager.html"},link:function(b,c,d,e){c.addClass("pager");var f=e[0],g=e[1];g&&f.init(g,a)}}}]),angular.module("ui.bootstrap.pagination",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPaginationController",["$scope","$attrs","$parse","uibPaging","uibPaginationConfig",function(a,b,c,d,e){function f(a,b,c){return{number:a,text:b,active:c}}function g(a,b){var c=[],d=1,e=b,g=angular.isDefined(i)&&b>i;g&&(j?(d=Math.max(a-Math.floor(i/2),1),e=d+i-1,e>b&&(e=b,d=e-i+1)):(d=(Math.ceil(a/i)-1)*i+1,e=Math.min(d+i-1,b)));for(var h=d;e>=h;h++){var n=f(h,m(h),h===a);c.push(n)}if(g&&i>0&&(!j||k||l)){if(d>1){if(!l||d>3){var o=f(d-1,"...",!1);c.unshift(o)}if(l){if(3===d){var p=f(2,"2",!1);c.unshift(p)}var q=f(1,"1",!1);c.unshift(q)}}if(b>e){if(!l||b-2>e){var r=f(e+1,"...",!1);c.push(r)}if(l){if(e===b-2){var s=f(b-1,b-1,!1);c.push(s)}var t=f(b,b,!1);c.push(t)}}}return c}var h=this,i=angular.isDefined(b.maxSize)?a.$parent.$eval(b.maxSize):e.maxSize,j=angular.isDefined(b.rotate)?a.$parent.$eval(b.rotate):e.rotate,k=angular.isDefined(b.forceEllipses)?a.$parent.$eval(b.forceEllipses):e.forceEllipses,l=angular.isDefined(b.boundaryLinkNumbers)?a.$parent.$eval(b.boundaryLinkNumbers):e.boundaryLinkNumbers,m=angular.isDefined(b.pageLabel)?function(c){
return a.$parent.$eval(b.pageLabel,{$page:c})}:angular.identity;a.boundaryLinks=angular.isDefined(b.boundaryLinks)?a.$parent.$eval(b.boundaryLinks):e.boundaryLinks,a.directionLinks=angular.isDefined(b.directionLinks)?a.$parent.$eval(b.directionLinks):e.directionLinks,d.create(this,a,b),b.maxSize&&h._watchers.push(a.$parent.$watch(c(b.maxSize),function(a){i=parseInt(a,10),h.render()}));var n=this.render;this.render=function(){n(),a.page>0&&a.page<=a.totalPages&&(a.pages=g(a.page,a.totalPages))}}]).constant("uibPaginationConfig",{itemsPerPage:10,boundaryLinks:!1,boundaryLinkNumbers:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0,forceEllipses:!1}).directive("uibPagination",["$parse","uibPaginationConfig",function(a,b){return{scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["uibPagination","?ngModel"],restrict:"A",controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"uib/template/pagination/pagination.html"},link:function(a,c,d,e){c.addClass("pagination");var f=e[0],g=e[1];g&&f.init(g,b)}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.stackedMap"]).provider("$uibTooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",placementClassPrefix:"",animation:!0,popupDelay:0,popupCloseDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",outsideClick:"outsideClick",focus:"blur",none:""},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$uibPosition","$interpolate","$rootScope","$parse","$$stackedMap",function(e,f,g,h,i,j,k,l,m){function n(a){if(27===a.which){var b=o.top();b&&(b.value.close(),b=null)}}var o=m.createNew();return h.on("keyup",n),k.$on("$destroy",function(){h.off("keyup",n)}),function(e,k,m,n){function p(a){var b=(a||n.trigger||m).split(" "),d=b.map(function(a){return c[a]||a});return{show:b,hide:d}}n=angular.extend({},b,d,n);var q=a(e),r=j.startSymbol(),s=j.endSymbol(),t="<div "+q+'-popup uib-title="'+r+"title"+s+'" '+(n.useContentExp?'content-exp="contentExp()" ':'content="'+r+"content"+s+'" ')+'origin-scope="origScope" class="uib-position-measure '+k+'" tooltip-animation-class="fade"uib-tooltip-classes ng-class="{ in: isOpen }" ></div>';return{compile:function(a,b){var c=f(t);return function(a,b,d,f){function j(){O.isOpen?q():m()}function m(){N&&!a.$eval(d[k+"Enable"])||(u(),x(),O.popupDelay?G||(G=g(r,O.popupDelay,!1)):r())}function q(){s(),O.popupCloseDelay?H||(H=g(t,O.popupCloseDelay,!1)):t()}function r(){return s(),u(),O.content?(v(),void O.$evalAsync(function(){O.isOpen=!0,y(!0),T()})):angular.noop}function s(){G&&(g.cancel(G),G=null),I&&(g.cancel(I),I=null)}function t(){O&&O.$evalAsync(function(){O&&(O.isOpen=!1,y(!1),O.animation?F||(F=g(w,150,!1)):w())})}function u(){H&&(g.cancel(H),H=null),F&&(g.cancel(F),F=null)}function v(){D||(E=O.$new(),D=c(E,function(a){L?h.find("body").append(a):b.after(a)}),o.add(O,{close:t}),z())}function w(){s(),u(),A(),D&&(D.remove(),D=null,J&&g.cancel(J)),o.remove(O),E&&(E.$destroy(),E=null)}function x(){O.title=d[k+"Title"],R?O.content=R(a):O.content=d[e],O.popupClass=d[k+"Class"],O.placement=angular.isDefined(d[k+"Placement"])?d[k+"Placement"]:n.placement;var b=i.parsePlacement(O.placement);K=b[1]?b[0]+"-"+b[1]:b[0];var c=parseInt(d[k+"PopupDelay"],10),f=parseInt(d[k+"PopupCloseDelay"],10);O.popupDelay=isNaN(c)?n.popupDelay:c,O.popupCloseDelay=isNaN(f)?n.popupCloseDelay:f}function y(b){Q&&angular.isFunction(Q.assign)&&Q.assign(a,b)}function z(){S.length=0,R?(S.push(a.$watch(R,function(a){O.content=a,!a&&O.isOpen&&t()})),S.push(E.$watch(function(){P||(P=!0,E.$$postDigest(function(){P=!1,O&&O.isOpen&&T()}))}))):S.push(d.$observe(e,function(a){O.content=a,!a&&O.isOpen?t():T()})),S.push(d.$observe(k+"Title",function(a){O.title=a,O.isOpen&&T()})),S.push(d.$observe(k+"Placement",function(a){O.placement=a?a:n.placement,O.isOpen&&T()}))}function A(){S.length&&(angular.forEach(S,function(a){a()}),S.length=0)}function B(a){O&&O.isOpen&&D&&(b[0].contains(a.target)||D[0].contains(a.target)||q())}function C(){var c=[],e=[],f=a.$eval(d[k+"Trigger"]);U(),angular.isObject(f)?(Object.keys(f).forEach(function(a){c.push(a),e.push(f[a])}),M={show:c,hide:e}):M=p(f),"none"!==M.show&&M.show.forEach(function(a,c){"outsideClick"===a?(b.on("click",j),h.on("click",B)):a===M.hide[c]?b.on(a,j):a&&(b.on(a,m),b.on(M.hide[c],q)),b.on("keypress",function(a){27===a.which&&q()})})}var D,E,F,G,H,I,J,K,L=angular.isDefined(n.appendToBody)?n.appendToBody:!1,M=p(void 0),N=angular.isDefined(d[k+"Enable"]),O=a.$new(!0),P=!1,Q=angular.isDefined(d[k+"IsOpen"])?l(d[k+"IsOpen"]):!1,R=n.useContentExp?l(d[e]):!1,S=[],T=function(){D&&D.html()&&(I||(I=g(function(){var a=i.positionElements(b,D,O.placement,L),c=angular.isDefined(D.offsetHeight)?D.offsetHeight:D.prop("offsetHeight"),d=L?i.offset(b):i.position(b);D.css({top:a.top+"px",left:a.left+"px"});var e=a.placement.split("-");D.hasClass(e[0])||(D.removeClass(K.split("-")[0]),D.addClass(e[0])),D.hasClass(n.placementClassPrefix+a.placement)||(D.removeClass(n.placementClassPrefix+K),D.addClass(n.placementClassPrefix+a.placement)),J=g(function(){var a=angular.isDefined(D.offsetHeight)?D.offsetHeight:D.prop("offsetHeight"),b=i.adjustTop(e,d,c,a);b&&D.css(b),J=null},0,!1),D.hasClass("uib-position-measure")?(i.positionArrow(D,a.placement),D.removeClass("uib-position-measure")):K!==a.placement&&i.positionArrow(D,a.placement),K=a.placement,I=null},0,!1)))};O.origScope=a,O.isOpen=!1,O.contentExp=function(){return O.content},d.$observe("disabled",function(a){a&&s(),a&&O.isOpen&&t()}),Q&&a.$watch(Q,function(a){O&&!a===O.isOpen&&j()});var U=function(){M.show.forEach(function(a){"outsideClick"===a?b.off("click",j):(b.off(a,m),b.off(a,j))}),M.hide.forEach(function(a){"outsideClick"===a?h.off("click",B):b.off(a,q)})};C();var V=a.$eval(d[k+"Animation"]);O.animation=angular.isDefined(V)?!!V:n.animation;var W,X=k+"AppendToBody";W=X in d&&void 0===d[X]?!0:a.$eval(d[X]),L=angular.isDefined(W)?W:L,a.$on("$destroy",function(){U(),w(),O=null})}}}}}]}).directive("uibTooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.uibTooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("uibTooltipClasses",["$uibPosition",function(a){return{restrict:"A",link:function(b,c,d){if(b.placement){var e=a.parsePlacement(b.placement);c.addClass(e[0])}b.popupClass&&c.addClass(b.popupClass),b.animation&&c.addClass(d.tooltipAnimationClass)}}}]).directive("uibTooltipPopup",function(){return{restrict:"A",scope:{content:"@"},templateUrl:"uib/template/tooltip/tooltip-popup.html"}}).directive("uibTooltip",["$uibTooltip",function(a){return a("uibTooltip","tooltip","mouseenter")}]).directive("uibTooltipTemplatePopup",function(){return{restrict:"A",scope:{contentExp:"&",originScope:"&"},templateUrl:"uib/template/tooltip/tooltip-template-popup.html"}}).directive("uibTooltipTemplate",["$uibTooltip",function(a){return a("uibTooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("uibTooltipHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&"},templateUrl:"uib/template/tooltip/tooltip-html-popup.html"}}).directive("uibTooltipHtml",["$uibTooltip",function(a){return a("uibTooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("uibPopoverTemplatePopup",function(){return{restrict:"A",scope:{uibTitle:"@",contentExp:"&",originScope:"&"},templateUrl:"uib/template/popover/popover-template.html"}}).directive("uibPopoverTemplate",["$uibTooltip",function(a){return a("uibPopoverTemplate","popover","click",{useContentExp:!0})}]).directive("uibPopoverHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&",uibTitle:"@"},templateUrl:"uib/template/popover/popover-html.html"}}).directive("uibPopoverHtml",["$uibTooltip",function(a){return a("uibPopoverHtml","popover","click",{useContentExp:!0})}]).directive("uibPopoverPopup",function(){return{restrict:"A",scope:{uibTitle:"@",content:"@"},templateUrl:"uib/template/popover/popover.html"}}).directive("uibPopover",["$uibTooltip",function(a){return a("uibPopover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("uibProgressConfig",{animate:!0,max:100}).controller("UibProgressController",["$scope","$attrs","uibProgressConfig",function(a,b,c){function d(){return angular.isDefined(a.maxParam)?a.maxParam:c.max}var e=this,f=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=d(),this.addBar=function(a,b,c){f||b.css({transition:"none"}),this.bars.push(a),a.max=d(),a.title=c&&angular.isDefined(c.title)?c.title:"progressbar",a.$watch("value",function(b){a.recalculatePercentage()}),a.recalculatePercentage=function(){var b=e.bars.reduce(function(a,b){return b.percent=+(100*b.value/b.max).toFixed(2),a+b.percent},0);b>100&&(a.percent-=b-100)},a.$on("$destroy",function(){b=null,e.removeBar(a)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1),this.bars.forEach(function(a){a.recalculatePercentage()})},a.$watch("maxParam",function(a){e.bars.forEach(function(a){a.max=d(),a.recalculatePercentage()})})}]).directive("uibProgress",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",require:"uibProgress",scope:{maxParam:"=?max"},templateUrl:"uib/template/progressbar/progress.html"}}).directive("uibBar",function(){return{replace:!0,transclude:!0,require:"^uibProgress",scope:{value:"=",type:"@"},templateUrl:"uib/template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b,c)}}}).directive("uibProgressbar",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",scope:{value:"=",maxParam:"=?max",type:"@"},templateUrl:"uib/template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]),{title:c.title})}}}),angular.module("ui.bootstrap.rating",[]).constant("uibRatingConfig",{max:5,stateOn:null,stateOff:null,enableReset:!0,titles:["one","two","three","four","five"]}).controller("UibRatingController",["$scope","$attrs","uibRatingConfig",function(a,b,c){var d={$setViewValue:angular.noop},e=this;this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff,this.enableReset=angular.isDefined(b.enableReset)?a.$parent.$eval(b.enableReset):c.enableReset;var f=angular.isDefined(b.titles)?a.$parent.$eval(b.titles):c.titles;this.titles=angular.isArray(f)&&f.length>0?f:c.titles;var g=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(g)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff,title:this.getTitle(b)},a[b]);return a},this.getTitle=function(a){return a>=this.titles.length?a+1:this.titles[a]},a.rate=function(b){if(!a.readonly&&b>=0&&b<=a.range.length){var c=e.enableReset&&d.$viewValue===b?0:b;d.$setViewValue(c),d.$render()}},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue,a.title=e.getTitle(a.value-1)}}]).directive("uibRating",function(){return{require:["uibRating","ngModel"],restrict:"A",scope:{readonly:"=?readOnly",onHover:"&",onLeave:"&"},controller:"UibRatingController",templateUrl:"uib/template/rating/rating.html",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(a){function b(a){for(var b=0;b<d.tabs.length;b++)if(d.tabs[b].index===a)return b}var c,d=this;d.tabs=[],d.select=function(a,f){if(!e){var g=b(c),h=d.tabs[g];if(h){if(h.tab.onDeselect({$event:f,$selectedIndex:a}),f&&f.isDefaultPrevented())return;h.tab.active=!1}var i=d.tabs[a];i?(i.tab.onSelect({$event:f}),i.tab.active=!0,d.active=i.index,c=i.index):!i&&angular.isDefined(c)&&(d.active=null,c=null)}},d.addTab=function(a){if(d.tabs.push({tab:a,index:a.index}),d.tabs.sort(function(a,b){return a.index>b.index?1:a.index<b.index?-1:0}),a.index===d.active||!angular.isDefined(d.active)&&1===d.tabs.length){var c=b(a.index);d.select(c)}},d.removeTab=function(a){for(var b,c=0;c<d.tabs.length;c++)if(d.tabs[c].tab===a){b=c;break}if(d.tabs[b].index===d.active){var e=b===d.tabs.length-1?b-1:b+1%d.tabs.length;d.select(e)}d.tabs.splice(b,1)},a.$watch("tabset.active",function(a){angular.isDefined(a)&&a!==c&&d.select(b(a))});var e;a.$on("$destroy",function(){e=!0})}]).directive("uibTabset",function(){return{transclude:!0,replace:!0,scope:{},bindToController:{active:"=?",type:"@"},controller:"UibTabsetController",controllerAs:"tabset",templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tabset.html"},link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("uibTab",["$parse",function(a){return{require:"^uibTabset",replace:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tab.html"},transclude:!0,scope:{heading:"@",index:"=?",classes:"@?",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},controllerAs:"tab",link:function(b,c,d,e,f){b.disabled=!1,d.disable&&b.$parent.$watch(a(d.disable),function(a){b.disabled=!!a}),angular.isUndefined(d.index)&&(e.tabs&&e.tabs.length?b.index=Math.max.apply(null,e.tabs.map(function(a){return a.index}))+1:b.index=0),angular.isUndefined(d.classes)&&(b.classes=""),b.select=function(a){if(!b.disabled){for(var c,d=0;d<e.tabs.length;d++)if(e.tabs[d].tab===b){c=d;break}e.select(c,a)}},e.addTab(b),b.$on("$destroy",function(){e.removeTab(b)}),b.$transcludeFn=f}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:"^uibTab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}).directive("uibTabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("uib-tab-heading")||a.hasAttribute("data-uib-tab-heading")||a.hasAttribute("x-uib-tab-heading")||"uib-tab-heading"===a.tagName.toLowerCase()||"data-uib-tab-heading"===a.tagName.toLowerCase()||"x-uib-tab-heading"===a.tagName.toLowerCase()||"uib:tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^uibTabset",link:function(b,c,d){var e=b.$eval(d.uibTabContentTransclude).tab;e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("uibTimepickerConfig",{hourStep:1,minuteStep:1,secondStep:1,showMeridian:!0,showSeconds:!1,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0,showSpinners:!0,templateUrl:"uib/template/timepicker/timepicker.html"}).controller("UibTimepickerController",["$scope","$element","$attrs","$parse","$log","$locale","uibTimepickerConfig",function(a,b,c,d,e,f,g){function h(){var b=+a.hours,c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c&&""!==a.hours?(a.showMeridian&&(12===b&&(b=0),a.meridian===y[1]&&(b+=12)),b):void 0}function i(){var b=+a.minutes,c=b>=0&&60>b;return c&&""!==a.minutes?b:void 0}function j(){var b=+a.seconds;return b>=0&&60>b?b:void 0}function k(a,b){return null===a?"":angular.isDefined(a)&&a.toString().length<2&&!b?"0"+a:a.toString()}function l(a){m(),x.$setViewValue(new Date(v)),n(a)}function m(){s&&s.$setValidity("hours",!0),t&&t.$setValidity("minutes",!0),u&&u.$setValidity("seconds",!0),x.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1,a.invalidSeconds=!1}function n(b){if(x.$modelValue){var c=v.getHours(),d=v.getMinutes(),e=v.getSeconds();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:k(c,!z),"m"!==b&&(a.minutes=k(d)),a.meridian=v.getHours()<12?y[0]:y[1],"s"!==b&&(a.seconds=k(e)),a.meridian=v.getHours()<12?y[0]:y[1]}else a.hours=null,a.minutes=null,a.seconds=null,a.meridian=y[0]}function o(a){v=q(v,a),l()}function p(a,b){return q(a,60*b)}function q(a,b){var c=new Date(a.getTime()+1e3*b),d=new Date(a);return d.setHours(c.getHours(),c.getMinutes(),c.getSeconds()),d}function r(){return(null===a.hours||""===a.hours)&&(null===a.minutes||""===a.minutes)&&(!a.showSeconds||a.showSeconds&&(null===a.seconds||""===a.seconds))}var s,t,u,v=new Date,w=[],x={$setViewValue:angular.noop},y=angular.isDefined(c.meridians)?a.$parent.$eval(c.meridians):g.meridians||f.DATETIME_FORMATS.AMPMS,z=angular.isDefined(c.padHours)?a.$parent.$eval(c.padHours):!0;a.tabindex=angular.isDefined(c.tabindex)?c.tabindex:0,b.removeAttr("tabindex"),this.init=function(b,d){x=b,x.$render=this.render,x.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),f=d.eq(1),h=d.eq(2);s=e.controller("ngModel"),t=f.controller("ngModel"),u=h.controller("ngModel");var i=angular.isDefined(c.mousewheel)?a.$parent.$eval(c.mousewheel):g.mousewheel;i&&this.setupMousewheelEvents(e,f,h);var j=angular.isDefined(c.arrowkeys)?a.$parent.$eval(c.arrowkeys):g.arrowkeys;j&&this.setupArrowkeyEvents(e,f,h),a.readonlyInput=angular.isDefined(c.readonlyInput)?a.$parent.$eval(c.readonlyInput):g.readonlyInput,this.setupInputEvents(e,f,h)};var A=g.hourStep;c.hourStep&&w.push(a.$parent.$watch(d(c.hourStep),function(a){A=+a}));var B=g.minuteStep;c.minuteStep&&w.push(a.$parent.$watch(d(c.minuteStep),function(a){B=+a}));var C;w.push(a.$parent.$watch(d(c.min),function(a){var b=new Date(a);C=isNaN(b)?void 0:b}));var D;w.push(a.$parent.$watch(d(c.max),function(a){var b=new Date(a);D=isNaN(b)?void 0:b}));var E=!1;c.ngDisabled&&w.push(a.$parent.$watch(d(c.ngDisabled),function(a){E=a})),a.noIncrementHours=function(){var a=p(v,60*A);return E||a>D||v>a&&C>a},a.noDecrementHours=function(){var a=p(v,60*-A);return E||C>a||a>v&&a>D},a.noIncrementMinutes=function(){var a=p(v,B);return E||a>D||v>a&&C>a},a.noDecrementMinutes=function(){var a=p(v,-B);return E||C>a||a>v&&a>D},a.noIncrementSeconds=function(){var a=q(v,F);return E||a>D||v>a&&C>a},a.noDecrementSeconds=function(){var a=q(v,-F);return E||C>a||a>v&&a>D},a.noToggleMeridian=function(){return v.getHours()<12?E||p(v,720)>D:E||p(v,-720)<C};var F=g.secondStep;c.secondStep&&w.push(a.$parent.$watch(d(c.secondStep),function(a){F=+a})),a.showSeconds=g.showSeconds,c.showSeconds&&w.push(a.$parent.$watch(d(c.showSeconds),function(b){a.showSeconds=!!b})),a.showMeridian=g.showMeridian,c.showMeridian&&w.push(a.$parent.$watch(d(c.showMeridian),function(b){if(a.showMeridian=!!b,x.$error.time){var c=h(),d=i();angular.isDefined(c)&&angular.isDefined(d)&&(v.setHours(c),l())}else n()})),this.setupMousewheelEvents=function(b,c,d){var e=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()}),d.bind("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementSeconds():a.decrementSeconds()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c,d){b.bind("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply()))}),c.bind("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply()))}),d.bind("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementSeconds(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementSeconds(),a.$apply()))})},this.setupInputEvents=function(b,c,d){if(a.readonlyInput)return a.updateHours=angular.noop,a.updateMinutes=angular.noop,void(a.updateSeconds=angular.noop);var e=function(b,c,d){x.$setViewValue(null),x.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b,s&&s.$setValidity("hours",!1)),angular.isDefined(c)&&(a.invalidMinutes=c,t&&t.$setValidity("minutes",!1)),angular.isDefined(d)&&(a.invalidSeconds=d,u&&u.$setValidity("seconds",!1))};a.updateHours=function(){var a=h(),b=i();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(a),v.setMinutes(b),C>v||v>D?e(!0):l("h")):e(!0)},b.bind("blur",function(b){x.$setTouched(),r()?m():null===a.hours||""===a.hours?e(!0):!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=k(a.hours,!z)})}),a.updateMinutes=function(){var a=i(),b=h();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(b),v.setMinutes(a),C>v||v>D?e(void 0,!0):l("m")):e(void 0,!0)},c.bind("blur",function(b){x.$setTouched(),r()?m():null===a.minutes?e(void 0,!0):!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=k(a.minutes)})}),a.updateSeconds=function(){var a=j();x.$setDirty(),angular.isDefined(a)?(v.setSeconds(a),l("s")):e(void 0,void 0,!0)},d.bind("blur",function(b){r()?m():!a.invalidSeconds&&a.seconds<10&&a.$apply(function(){a.seconds=k(a.seconds)})})},this.render=function(){var b=x.$viewValue;isNaN(b)?(x.$setValidity("time",!1),e.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(b&&(v=b),C>v||v>D?(x.$setValidity("time",!1),a.invalidHours=!0,a.invalidMinutes=!0):m(),n())},a.showSpinners=angular.isDefined(c.showSpinners)?a.$parent.$eval(c.showSpinners):g.showSpinners,a.incrementHours=function(){a.noIncrementHours()||o(60*A*60)},a.decrementHours=function(){a.noDecrementHours()||o(60*-A*60)},a.incrementMinutes=function(){a.noIncrementMinutes()||o(60*B)},a.decrementMinutes=function(){a.noDecrementMinutes()||o(60*-B)},a.incrementSeconds=function(){a.noIncrementSeconds()||o(F)},a.decrementSeconds=function(){a.noDecrementSeconds()||o(-F)},a.toggleMeridian=function(){var b=i(),c=h();a.noToggleMeridian()||(angular.isDefined(b)&&angular.isDefined(c)?o(720*(v.getHours()<12?60:-60)):a.meridian=a.meridian===y[0]?y[1]:y[0])},a.blur=function(){x.$setTouched()},a.$on("$destroy",function(){for(;w.length;)w.shift()()})}]).directive("uibTimepicker",["uibTimepickerConfig",function(a){return{require:["uibTimepicker","?^ngModel"],restrict:"A",controller:"UibTimepickerController",controllerAs:"timepicker",scope:{},templateUrl:function(b,c){return c.templateUrl||a.templateUrl},link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.debounce","ui.bootstrap.position"]).factory("uibTypeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).controller("UibTypeaheadController",["$scope","$element","$attrs","$compile","$parse","$q","$timeout","$document","$window","$rootScope","$$debounce","$uibPosition","uibTypeaheadParser",function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(){O.moveInProgress||(O.moveInProgress=!0,O.$digest()),Z()}function o(){O.position=E?l.offset(b):l.position(b),O.position.top+=b.prop("offsetHeight")}var p,q,r=[9,13,27,38,40],s=200,t=a.$eval(c.typeaheadMinLength);t||0===t||(t=1),a.$watch(c.typeaheadMinLength,function(a){t=a||0===a?a:1});var u=a.$eval(c.typeaheadWaitMs)||0,v=a.$eval(c.typeaheadEditable)!==!1;a.$watch(c.typeaheadEditable,function(a){v=a!==!1});var w,x,y=e(c.typeaheadLoading).assign||angular.noop,z=c.typeaheadShouldSelect?e(c.typeaheadShouldSelect):function(a,b){var c=b.$event;return 13===c.which||9===c.which},A=e(c.typeaheadOnSelect),B=angular.isDefined(c.typeaheadSelectOnBlur)?a.$eval(c.typeaheadSelectOnBlur):!1,C=e(c.typeaheadNoResults).assign||angular.noop,D=c.typeaheadInputFormatter?e(c.typeaheadInputFormatter):void 0,E=c.typeaheadAppendToBody?a.$eval(c.typeaheadAppendToBody):!1,F=c.typeaheadAppendTo?a.$eval(c.typeaheadAppendTo):null,G=a.$eval(c.typeaheadFocusFirst)!==!1,H=c.typeaheadSelectOnExact?a.$eval(c.typeaheadSelectOnExact):!1,I=e(c.typeaheadIsOpen).assign||angular.noop,J=a.$eval(c.typeaheadShowHint)||!1,K=e(c.ngModel),L=e(c.ngModel+"($$$p)"),M=function(b,c){return angular.isFunction(K(a))&&q&&q.$options&&q.$options.getterSetter?L(b,{$$$p:c}):K.assign(b,c)},N=m.parse(c.uibTypeahead),O=a.$new(),P=a.$on("$destroy",function(){O.$destroy()});O.$on("$destroy",P);var Q="typeahead-"+O.$id+"-"+Math.floor(1e4*Math.random());b.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":Q});var R,S;J&&(R=angular.element("<div></div>"),R.css("position","relative"),b.after(R),S=b.clone(),S.attr("placeholder",""),S.attr("tabindex","-1"),S.val(""),S.css({position:"absolute",top:"0px",left:"0px","border-color":"transparent","box-shadow":"none",opacity:1,background:"none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)",color:"#999"}),b.css({position:"relative","vertical-align":"top","background-color":"transparent"}),S.attr("id")&&S.removeAttr("id"),R.append(S),S.after(b));var T=angular.element("<div uib-typeahead-popup></div>");T.attr({id:Q,matches:"matches",active:"activeIdx",select:"select(activeIdx, evt)","move-in-progress":"moveInProgress",query:"query",position:"position","assign-is-open":"assignIsOpen(isOpen)",debounce:"debounceUpdate"}),angular.isDefined(c.typeaheadTemplateUrl)&&T.attr("template-url",c.typeaheadTemplateUrl),angular.isDefined(c.typeaheadPopupTemplateUrl)&&T.attr("popup-template-url",c.typeaheadPopupTemplateUrl);var U=function(){J&&S.val("")},V=function(){O.matches=[],O.activeIdx=-1,b.attr("aria-expanded",!1),U()},W=function(a){return Q+"-option-"+a};O.$watch("activeIdx",function(a){0>a?b.removeAttr("aria-activedescendant"):b.attr("aria-activedescendant",W(a))});var X=function(a,b){return O.matches.length>b&&a?a.toUpperCase()===O.matches[b].label.toUpperCase():!1},Y=function(c,d){var e={$viewValue:c};y(a,!0),C(a,!1),f.when(N.source(a,e)).then(function(f){var g=c===p.$viewValue;if(g&&w)if(f&&f.length>0){O.activeIdx=G?0:-1,C(a,!1),O.matches.length=0;for(var h=0;h<f.length;h++)e[N.itemName]=f[h],O.matches.push({id:W(h),label:N.viewMapper(O,e),model:f[h]});if(O.query=c,o(),b.attr("aria-expanded",!0),H&&1===O.matches.length&&X(c,0)&&(angular.isNumber(O.debounceUpdate)||angular.isObject(O.debounceUpdate)?k(function(){O.select(0,d)},angular.isNumber(O.debounceUpdate)?O.debounceUpdate:O.debounceUpdate["default"]):O.select(0,d)),J){var i=O.matches[0].label;angular.isString(c)&&c.length>0&&i.slice(0,c.length).toUpperCase()===c.toUpperCase()?S.val(c+i.slice(c.length)):S.val("")}}else V(),C(a,!0);g&&y(a,!1)},function(){V(),y(a,!1),C(a,!0)})};E&&(angular.element(i).on("resize",n),h.find("body").on("scroll",n));var Z=k(function(){O.matches.length&&o(),O.moveInProgress=!1},s);O.moveInProgress=!1,O.query=void 0;var $,_=function(a){$=g(function(){Y(a)},u)},aa=function(){$&&g.cancel($)};V(),O.assignIsOpen=function(b){I(a,b)},O.select=function(d,e){var f,h,i={};x=!0,i[N.itemName]=h=O.matches[d].model,f=N.modelMapper(a,i),M(a,f),p.$setValidity("editable",!0),p.$setValidity("parse",!0),A(a,{$item:h,$model:f,$label:N.viewMapper(a,i),$event:e}),V(),O.$eval(c.typeaheadFocusOnSelect)!==!1&&g(function(){b[0].focus()},0,!1)},b.on("keydown",function(b){if(0!==O.matches.length&&-1!==r.indexOf(b.which)){var c=z(a,{$event:b});if(-1===O.activeIdx&&c||9===b.which&&b.shiftKey)return V(),void O.$digest();b.preventDefault();var d;switch(b.which){case 27:b.stopPropagation(),V(),a.$digest();break;case 38:O.activeIdx=(O.activeIdx>0?O.activeIdx:O.matches.length)-1,O.$digest(),d=T[0].querySelectorAll(".uib-typeahead-match")[O.activeIdx],d.parentNode.scrollTop=d.offsetTop;break;case 40:O.activeIdx=(O.activeIdx+1)%O.matches.length,O.$digest(),d=T[0].querySelectorAll(".uib-typeahead-match")[O.activeIdx],d.parentNode.scrollTop=d.offsetTop;break;default:c&&O.$apply(function(){angular.isNumber(O.debounceUpdate)||angular.isObject(O.debounceUpdate)?k(function(){O.select(O.activeIdx,b)},angular.isNumber(O.debounceUpdate)?O.debounceUpdate:O.debounceUpdate["default"]):O.select(O.activeIdx,b)})}}}),b.bind("focus",function(a){w=!0,0!==t||p.$viewValue||g(function(){Y(p.$viewValue,a)},0)}),b.bind("blur",function(a){B&&O.matches.length&&-1!==O.activeIdx&&!x&&(x=!0,O.$apply(function(){angular.isObject(O.debounceUpdate)&&angular.isNumber(O.debounceUpdate.blur)?k(function(){O.select(O.activeIdx,a)},O.debounceUpdate.blur):O.select(O.activeIdx,a)})),!v&&p.$error.editable&&(p.$setViewValue(),O.$apply(function(){p.$setValidity("editable",!0),p.$setValidity("parse",!0)}),b.val("")),w=!1,x=!1});var ba=function(c){b[0]!==c.target&&3!==c.which&&0!==O.matches.length&&(V(),j.$$phase||a.$digest())};h.on("click",ba),a.$on("$destroy",function(){h.off("click",ba),(E||F)&&ca.remove(),E&&(angular.element(i).off("resize",n),h.find("body").off("scroll",n)),T.remove(),J&&R.remove()});var ca=d(T)(O);E?h.find("body").append(ca):F?angular.element(F).eq(0).append(ca):b.after(ca),this.init=function(b,c){p=b,q=c,O.debounceUpdate=p.$options&&e(p.$options.debounce)(a),p.$parsers.unshift(function(b){return w=!0,0===t||b&&b.length>=t?u>0?(aa(),_(b)):Y(b):(y(a,!1),aa(),V()),v?b:b?void p.$setValidity("editable",!1):(p.$setValidity("editable",!0),null)}),p.$formatters.push(function(b){var c,d,e={};return v||p.$setValidity("editable",!0),D?(e.$model=b,D(a,e)):(e[N.itemName]=b,c=N.viewMapper(a,e),e[N.itemName]=void 0,d=N.viewMapper(a,e),c!==d?c:b)})}}]).directive("uibTypeahead",function(){return{controller:"UibTypeaheadController",require:["ngModel","^?ngModelOptions","uibTypeahead"],link:function(a,b,c,d){d[2].init(d[0],d[1])}}}).directive("uibTypeaheadPopup",["$$debounce",function(a){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&",assignIsOpen:"&",debounce:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"uib/template/typeahead/typeahead-popup.html"},link:function(b,c,d){b.templateUrl=d.templateUrl,b.isOpen=function(){var a=b.matches.length>0;return b.assignIsOpen({isOpen:a}),a},b.isActive=function(a){return b.active===a},b.selectActive=function(a){b.active=a},b.selectMatch=function(c,d){var e=b.debounce();angular.isNumber(e)||angular.isObject(e)?a(function(){b.select({activeIdx:c,evt:d})},angular.isNumber(e)?e:e["default"]):b.select({activeIdx:c,evt:d})}}}}]).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"uib/template/typeahead/typeahead-match.html";a(g).then(function(a){var c=angular.element(a.trim());e.replaceWith(c),b(c)(d)})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(a,b,c){function d(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function e(a){return/<.*>/g.test(a)}var f;
return f=b.has("$sanitize"),function(b,g){return!f&&e(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=g?(""+b).replace(new RegExp(d(g),"gi"),"<strong>$&</strong>"):b,f||(b=a.trustAsHtml(b)),b}}]),angular.module("ui.bootstrap.carousel").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibCarouselCss&&angular.element(document).find("head").prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'),angular.$$uibCarouselCss=!0}),angular.module("ui.bootstrap.datepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'),angular.$$uibDatepickerCss=!0}),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'),angular.$$uibPositionCss=!0}),angular.module("ui.bootstrap.datepickerPopup").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerpopupCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'),angular.$$uibDatepickerpopupCss=!0}),angular.module("ui.bootstrap.tooltip").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTooltipCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'),angular.$$uibTooltipCss=!0}),angular.module("ui.bootstrap.timepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTimepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-time input{width:50px;}</style>'),angular.$$uibTimepickerCss=!0}),angular.module("ui.bootstrap.typeahead").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTypeaheadCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'),angular.$$uibTypeaheadCss=!0});
define("uibootstrap", ["angular"], function(){});

vendors/angular-bootstrap/ui-bootstrap-tpls.min.js
/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 2.2.0 - 2016-10-10
 * License: MIT
 */angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.collapse","ui.bootstrap.tabindex","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.isClass","ui.bootstrap.datepicker","ui.bootstrap.position","ui.bootstrap.datepickerPopup","ui.bootstrap.debounce","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.paging","ui.bootstrap.pager","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["uib/template/accordion/accordion-group.html","uib/template/accordion/accordion.html","uib/template/alert/alert.html","uib/template/carousel/carousel.html","uib/template/carousel/slide.html","uib/template/datepicker/datepicker.html","uib/template/datepicker/day.html","uib/template/datepicker/month.html","uib/template/datepicker/year.html","uib/template/datepickerPopup/popup.html","uib/template/modal/window.html","uib/template/pager/pager.html","uib/template/pagination/pagination.html","uib/template/tooltip/tooltip-html-popup.html","uib/template/tooltip/tooltip-popup.html","uib/template/tooltip/tooltip-template-popup.html","uib/template/popover/popover-html.html","uib/template/popover/popover-template.html","uib/template/popover/popover.html","uib/template/progressbar/bar.html","uib/template/progressbar/progress.html","uib/template/progressbar/progressbar.html","uib/template/rating/rating.html","uib/template/tabs/tab.html","uib/template/tabs/tabset.html","uib/template/timepicker/timepicker.html","uib/template/typeahead/typeahead-match.html","uib/template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$q","$parse","$injector",function(a,b,c,d){var e=d.has("$animateCss")?d.get("$animateCss"):null;return{link:function(d,f,g){function h(){r=!!("horizontal"in g),r?(s={width:""},t={width:"0"}):(s={height:""},t={height:"0"}),d.$eval(g.uibCollapse)||f.addClass("in").addClass("collapse").attr("aria-expanded",!0).attr("aria-hidden",!1).css(s)}function i(a){return r?{width:a.scrollWidth+"px"}:{height:a.scrollHeight+"px"}}function j(){f.hasClass("collapse")&&f.hasClass("in")||b.resolve(n(d)).then(function(){f.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),e?e(f,{addClass:"in",easing:"ease",css:{overflow:"hidden"},to:i(f[0])}).start()["finally"](k):a.addClass(f,"in",{css:{overflow:"hidden"},to:i(f[0])}).then(k)})}function k(){f.removeClass("collapsing").addClass("collapse").css(s),o(d)}function l(){return f.hasClass("collapse")||f.hasClass("in")?void b.resolve(p(d)).then(function(){f.css(i(f[0])).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),e?e(f,{removeClass:"in",to:t}).start()["finally"](m):a.removeClass(f,"in",{to:t}).then(m)}):m()}function m(){f.css(t),f.removeClass("collapsing").addClass("collapse"),q(d)}var n=c(g.expanding),o=c(g.expanded),p=c(g.collapsing),q=c(g.collapsed),r=!1,s={},t={};h(),d.$watch(g.uibCollapse,function(a){a?l():j()})}}}]),angular.module("ui.bootstrap.tabindex",[]).directive("uibTabindexToggle",function(){return{restrict:"A",link:function(a,b,c){c.$observe("disabled",function(a){c.$set("tabindex",a?-1:null)})}}}),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse","ui.bootstrap.tabindex"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(c){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/accordion/accordion-group.html"},scope:{heading:"@",panelClass:"@?",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){b.addClass("panel"),d.addGroup(a),a.openClass=c.openClass||"panel-open",a.panelClass=c.panelClass||"panel-default",a.$watch("isOpen",function(c){b.toggleClass(a.openClass,!!c),c&&d.closeOthers(a)}),a.toggleOpen=function(b){a.isDisabled||b&&32!==b.which||(a.isOpen=!a.isOpen)};var e="accordiongroup-"+a.$id+"-"+Math.floor(1e4*Math.random());a.headingId=e+"-tab",a.panelId=e+"-panel"}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("uibAccordionTransclude",function(){function a(){return"uib-accordion-header,data-uib-accordion-header,x-uib-accordion-header,uib\\:accordion-header,[uib-accordion-header],[data-uib-accordion-header],[x-uib-accordion-header]"}return{require:"^uibAccordionGroup",link:function(b,c,d,e){b.$watch(function(){return e[d.uibAccordionTransclude]},function(b){if(b){var d=angular.element(c[0].querySelector(a()));d.html(""),d.append(b)}})}}}),angular.module("ui.bootstrap.alert",[]).controller("UibAlertController",["$scope","$element","$attrs","$interpolate","$timeout",function(a,b,c,d,e){a.closeable=!!c.close,b.addClass("alert"),c.$set("role","alert"),a.closeable&&b.addClass("alert-dismissible");var f=angular.isDefined(c.dismissOnTimeout)?d(c.dismissOnTimeout)(a.$parent):null;f&&e(function(){a.close()},parseInt(f,10))}]).directive("uibAlert",function(){return{controller:"UibAlertController",controllerAs:"alert",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/alert/alert.html"},transclude:!0,scope:{close:"&"}}}),angular.module("ui.bootstrap.buttons",[]).constant("uibButtonConfig",{activeClass:"active",toggleEvent:"click"}).controller("UibButtonsController",["uibButtonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("uibBtnRadio",["$parse",function(a){return{require:["uibBtnRadio","ngModel"],controller:"UibButtonsController",controllerAs:"buttons",link:function(b,c,d,e){var f=e[0],g=e[1],h=a(d.uibUncheckable);c.find("input").css({display:"none"}),g.$render=function(){c.toggleClass(f.activeClass,angular.equals(g.$modelValue,b.$eval(d.uibBtnRadio)))},c.on(f.toggleEvent,function(){if(!d.disabled){var a=c.hasClass(f.activeClass);a&&!angular.isDefined(d.uncheckable)||b.$apply(function(){g.$setViewValue(a?null:b.$eval(d.uibBtnRadio)),g.$render()})}}),d.uibUncheckable&&b.$watch(h,function(a){d.$set("uncheckable",a?"":void 0)})}}}]).directive("uibBtnCheckbox",function(){return{require:["uibBtnCheckbox","ngModel"],controller:"UibButtonsController",controllerAs:"button",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){return angular.isDefined(b)?a.$eval(b):c}var h=d[0],i=d[1];b.find("input").css({display:"none"}),i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.on(h.toggleEvent,function(){c.disabled||a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",[]).controller("UibCarouselController",["$scope","$element","$interval","$timeout","$animate",function(a,b,c,d,e){function f(){for(;t.length;)t.shift()}function g(a){for(var b=0;b<q.length;b++)q[b].slide.active=b===a}function h(c,d,i){if(!u){if(angular.extend(c,{direction:i}),angular.extend(q[s].slide||{},{direction:i}),e.enabled(b)&&!a.$currentTransition&&q[d].element&&p.slides.length>1){q[d].element.data(r,c.direction);var j=p.getCurrentIndex();angular.isNumber(j)&&q[j].element&&q[j].element.data(r,c.direction),a.$currentTransition=!0,e.on("addClass",q[d].element,function(b,c){if("close"===c&&(a.$currentTransition=null,e.off("addClass",b),t.length)){var d=t.pop().slide,g=d.index,i=g>p.getCurrentIndex()?"next":"prev";f(),h(d,g,i)}})}a.active=c.index,s=c.index,g(d),l()}}function i(a){for(var b=0;b<q.length;b++)if(q[b].slide===a)return b}function j(){n&&(c.cancel(n),n=null)}function k(b){b.length||(a.$currentTransition=null,f())}function l(){j();var b=+a.interval;!isNaN(b)&&b>0&&(n=c(m,b))}function m(){var b=+a.interval;o&&!isNaN(b)&&b>0&&q.length?a.next():a.pause()}var n,o,p=this,q=p.slides=a.slides=[],r="uib-slideDirection",s=a.active,t=[],u=!1;b.addClass("carousel"),p.addSlide=function(b,c){q.push({slide:b,element:c}),q.sort(function(a,b){return+a.slide.index-+b.slide.index}),(b.index===a.active||1===q.length&&!angular.isNumber(a.active))&&(a.$currentTransition&&(a.$currentTransition=null),s=b.index,a.active=b.index,g(s),p.select(q[i(b)]),1===q.length&&a.play())},p.getCurrentIndex=function(){for(var a=0;a<q.length;a++)if(q[a].slide.index===s)return a},p.next=a.next=function(){var b=(p.getCurrentIndex()+1)%q.length;return 0===b&&a.noWrap()?void a.pause():p.select(q[b],"next")},p.prev=a.prev=function(){var b=p.getCurrentIndex()-1<0?q.length-1:p.getCurrentIndex()-1;return a.noWrap()&&b===q.length-1?void a.pause():p.select(q[b],"prev")},p.removeSlide=function(b){var c=i(b),d=t.indexOf(q[c]);-1!==d&&t.splice(d,1),q.splice(c,1),q.length>0&&s===c?c>=q.length?(s=q.length-1,a.active=s,g(s),p.select(q[q.length-1])):(s=c,a.active=s,g(s),p.select(q[c])):s>c&&(s--,a.active=s),0===q.length&&(s=null,a.active=null,f())},p.select=a.select=function(b,c){var d=i(b.slide);void 0===c&&(c=d>p.getCurrentIndex()?"next":"prev"),b.slide.index===s||a.$currentTransition?b&&b.slide.index!==s&&a.$currentTransition&&t.push(q[d]):h(b.slide,d,c)},a.indexOfSlide=function(a){return+a.slide.index},a.isActive=function(b){return a.active===b.slide.index},a.isPrevDisabled=function(){return 0===a.active&&a.noWrap()},a.isNextDisabled=function(){return a.active===q.length-1&&a.noWrap()},a.pause=function(){a.noPause||(o=!1,j())},a.play=function(){o||(o=!0,l())},b.on("mouseenter",a.pause),b.on("mouseleave",a.play),a.$on("$destroy",function(){u=!0,j()}),a.$watch("noTransition",function(a){e.enabled(b,!a)}),a.$watch("interval",l),a.$watchCollection("slides",k),a.$watch("active",function(a){if(angular.isNumber(a)&&s!==a){for(var b=0;b<q.length;b++)if(q[b].slide.index===a){a=b;break}var c=q[a];c&&(g(a),p.select(q[a]),s=a)}})}]).directive("uibCarousel",function(){return{transclude:!0,controller:"UibCarouselController",controllerAs:"carousel",restrict:"A",templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/carousel.html"},scope:{active:"=",interval:"=",noTransition:"=",noPause:"=",noWrap:"&"}}}).directive("uibSlide",["$animate",function(a){return{require:"^uibCarousel",restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/carousel/slide.html"},scope:{actual:"=?",index:"=?"},link:function(b,c,d,e){c.addClass("item"),e.addSlide(b,c),b.$on("$destroy",function(){e.removeSlide(b)}),b.$watch("active",function(b){a[b?"addClass":"removeClass"](c,"active")})}}}]).animation(".item",["$animateCss",function(a){function b(a,b,c){a.removeClass(b),c&&c()}var c="uib-slideDirection";return{beforeAddClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i+" "+h,f);return d.addClass(h),a(d,{addClass:i}).start().done(j),function(){g=!0}}f()},beforeRemoveClass:function(d,e,f){if("active"===e){var g=!1,h=d.data(c),i="next"===h?"left":"right",j=b.bind(this,d,i,f);return a(d,{addClass:i}).start().done(j),function(){g=!0}}f()}}}]),angular.module("ui.bootstrap.dateparser",[]).service("uibDateParser",["$log","$locale","dateFilter","orderByFilter",function(a,b,c,d){function e(a){var b=[],c=a.split(""),e=a.indexOf("'");if(e>-1){var f=!1;a=a.split("");for(var g=e;g<a.length;g++)f?("'"===a[g]&&(g+1<a.length&&"'"===a[g+1]?(a[g+1]="$",c[g+1]=""):(c[g]="",f=!1)),a[g]="$"):"'"===a[g]&&(a[g]="$",c[g]="",f=!0);a=a.join("")}return angular.forEach(q,function(d){var e=a.indexOf(d.key);if(e>-1){a=a.split(""),c[e]="("+d.regex+")",a[e]="$";for(var f=e+1,g=e+d.key.length;g>f;f++)c[f]="",a[f]="$";a=a.join(""),b.push({index:e,key:d.key,apply:d.apply,matcher:d.regex})}}),{regex:new RegExp("^"+c.join("")+"$"),map:d(b,"index")}}function f(a){for(var b,c,d=[],e=0;e<a.length;)if(angular.isNumber(c)){if("'"===a.charAt(e))(e+1>=a.length||"'"!==a.charAt(e+1))&&(d.push(g(a,c,e)),c=null);else if(e===a.length)for(;c<a.length;)b=h(a,c),d.push(b),c=b.endIdx;e++}else"'"!==a.charAt(e)?(b=h(a,e),d.push(b.parser),e=b.endIdx):(c=e,e++);return d}function g(a,b,c){return function(){return a.substr(b+1,c-b-1)}}function h(a,b){for(var c=a.substr(b),d=0;d<q.length;d++)if(new RegExp("^"+q[d].key).test(c)){var e=q[d];return{endIdx:b+e.key.length,parser:e.formatter}}return{endIdx:b+1,parser:function(){return c.charAt(0)}}}function i(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}function j(a){return parseInt(a,10)}function k(a,b){return a&&b?o(a,b):a}function l(a,b){return a&&b?o(a,b,!0):a}function m(a,b){a=a.replace(/:/g,"");var c=Date.parse("Jan 01, 1970 00:00:00 "+a)/6e4;return isNaN(c)?b:c}function n(a,b){return a=new Date(a.getTime()),a.setMinutes(a.getMinutes()+b),a}function o(a,b,c){c=c?-1:1;var d=a.getTimezoneOffset(),e=m(b,d);return n(a,c*(e-d))}var p,q,r=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.init=function(){p=b.id,this.parsers={},this.formatters={},q=[{key:"yyyy",regex:"\\d{4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yyyy")}},{key:"yy",regex:"\\d{2}",apply:function(a){a=+a,this.year=69>a?a+2e3:a+1900},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"yy")}},{key:"y",regex:"\\d{1,4}",apply:function(a){this.year=+a},formatter:function(a){var b=new Date;return b.setFullYear(Math.abs(a.getFullYear())),c(b,"y")}},{key:"M!",regex:"0?[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){var b=a.getMonth();return/^[0-9]$/.test(b)?c(a,"MM"):c(a,"M")}},{key:"MMMM",regex:b.DATETIME_FORMATS.MONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.MONTH.indexOf(a)},formatter:function(a){return c(a,"MMMM")}},{key:"MMM",regex:b.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.SHORTMONTH.indexOf(a)},formatter:function(a){return c(a,"MMM")}},{key:"MM",regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"MM")}},{key:"M",regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1},formatter:function(a){return c(a,"M")}},{key:"d!",regex:"[0-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){var b=a.getDate();return/^[1-9]$/.test(b)?c(a,"dd"):c(a,"d")}},{key:"dd",regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"dd")}},{key:"d",regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a},formatter:function(a){return c(a,"d")}},{key:"EEEE",regex:b.DATETIME_FORMATS.DAY.join("|"),formatter:function(a){return c(a,"EEEE")}},{key:"EEE",regex:b.DATETIME_FORMATS.SHORTDAY.join("|"),formatter:function(a){return c(a,"EEE")}},{key:"HH",regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"HH")}},{key:"hh",regex:"0[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"hh")}},{key:"H",regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"H")}},{key:"h",regex:"[0-9]|1[0-2]",apply:function(a){this.hours=+a},formatter:function(a){return c(a,"h")}},{key:"mm",regex:"[0-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"mm")}},{key:"m",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a},formatter:function(a){return c(a,"m")}},{key:"sss",regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a},formatter:function(a){return c(a,"sss")}},{key:"ss",regex:"[0-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"ss")}},{key:"s",regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a},formatter:function(a){return c(a,"s")}},{key:"a",regex:b.DATETIME_FORMATS.AMPMS.join("|"),apply:function(a){12===this.hours&&(this.hours=0),"PM"===a&&(this.hours+=12)},formatter:function(a){return c(a,"a")}},{key:"Z",regex:"[+-]\\d{4}",apply:function(a){var b=a.match(/([+-])(\d{2})(\d{2})/),c=b[1],d=b[2],e=b[3];this.hours+=j(c+d),this.minutes+=j(c+e)},formatter:function(a){return c(a,"Z")}},{key:"ww",regex:"[0-4][0-9]|5[0-3]",formatter:function(a){return c(a,"ww")}},{key:"w",regex:"[0-9]|[1-4][0-9]|5[0-3]",formatter:function(a){return c(a,"w")}},{key:"GGGG",regex:b.DATETIME_FORMATS.ERANAMES.join("|").replace(/\s/g,"\\s"),formatter:function(a){return c(a,"GGGG")}},{key:"GGG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GGG")}},{key:"GG",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"GG")}},{key:"G",regex:b.DATETIME_FORMATS.ERAS.join("|"),formatter:function(a){return c(a,"G")}}]},this.init(),this.filter=function(a,c){if(!angular.isDate(a)||isNaN(a)||!c)return"";c=b.DATETIME_FORMATS[c]||c,b.id!==p&&this.init(),this.formatters[c]||(this.formatters[c]=f(c));var d=this.formatters[c];return d.reduce(function(b,c){return b+c(a)},"")},this.parse=function(c,d,f){if(!angular.isString(c)||!d)return c;d=b.DATETIME_FORMATS[d]||d,d=d.replace(r,"\\$&"),b.id!==p&&this.init(),this.parsers[d]||(this.parsers[d]=e(d,"apply"));var g=this.parsers[d],h=g.regex,j=g.map,k=c.match(h),l=!1;if(k&&k.length){var m,n;angular.isDate(f)&&!isNaN(f.getTime())?m={year:f.getFullYear(),month:f.getMonth(),date:f.getDate(),hours:f.getHours(),minutes:f.getMinutes(),seconds:f.getSeconds(),milliseconds:f.getMilliseconds()}:(f&&a.warn("dateparser:","baseDate is not a valid date"),m={year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0});for(var o=1,q=k.length;q>o;o++){var s=j[o-1];"Z"===s.matcher&&(l=!0),s.apply&&s.apply.call(m,k[o])}var t=l?Date.prototype.setUTCFullYear:Date.prototype.setFullYear,u=l?Date.prototype.setUTCHours:Date.prototype.setHours;return i(m.year,m.month,m.date)&&(!angular.isDate(f)||isNaN(f.getTime())||l?(n=new Date(0),t.call(n,m.year,m.month,m.date),u.call(n,m.hours||0,m.minutes||0,m.seconds||0,m.milliseconds||0)):(n=new Date(f),t.call(n,m.year,m.month,m.date),u.call(n,m.hours,m.minutes,m.seconds,m.milliseconds))),n}},this.toTimezone=k,this.fromTimezone=l,this.timezoneToOffset=m,this.addDateMinutes=n,this.convertTimezoneToLocal=o}]),angular.module("ui.bootstrap.isClass",[]).directive("uibIsClass",["$animate",function(a){var b=/^\s*([\s\S]+?)\s+on\s+([\s\S]+?)\s*$/,c=/^\s*([\s\S]+?)\s+for\s+([\s\S]+?)\s*$/;return{restrict:"A",compile:function(d,e){function f(a,b,c){i.push(a),j.push({scope:a,element:b}),o.forEach(function(b,c){g(b,a)}),a.$on("$destroy",h)}function g(b,d){var e=b.match(c),f=d.$eval(e[1]),g=e[2],h=k[b];if(!h){var i=function(b){var c=null;j.some(function(a){var d=a.scope.$eval(m);return d===b?(c=a,!0):void 0}),h.lastActivated!==c&&(h.lastActivated&&a.removeClass(h.lastActivated.element,f),c&&a.addClass(c.element,f),h.lastActivated=c)};k[b]=h={lastActivated:null,scope:d,watchFn:i,compareWithExp:g,watcher:d.$watch(g,i)}}h.watchFn(d.$eval(g))}function h(a){var b=a.targetScope,c=i.indexOf(b);if(i.splice(c,1),j.splice(c,1),i.length){var d=i[0];angular.forEach(k,function(a){a.scope===b&&(a.watcher=d.$watch(a.compareWithExp,a.watchFn),a.scope=d)})}else k={}}var i=[],j=[],k={},l=e.uibIsClass.match(b),m=l[2],n=l[1],o=n.split(",");return f}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.isClass"]).value("$datepickerSuppressError",!1).value("$datepickerLiteralWarning",!0).constant("uibDatepickerConfig",{datepickerMode:"day",formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",maxDate:null,maxMode:"year",minDate:null,minMode:"day",monthColumns:3,ngModelOptions:{},shortcutPropagation:!1,showWeeks:!0,yearColumns:5,yearRows:4}).controller("UibDatepickerController",["$scope","$element","$attrs","$parse","$interpolate","$locale","$log","dateFilter","uibDatepickerConfig","$datepickerLiteralWarning","$datepickerSuppressError","uibDateParser",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(b){a.datepickerMode=b,a.datepickerOptions.datepickerMode=b}var n=this,o={$setViewValue:angular.noop},p={},q=[];b.addClass("uib-datepicker"),c.$set("role","application"),a.datepickerOptions||(a.datepickerOptions={}),this.modes=["day","month","year"],["customClass","dateDisabled","datepickerMode","formatDay","formatDayHeader","formatDayTitle","formatMonth","formatMonthTitle","formatYear","maxDate","maxMode","minDate","minMode","monthColumns","showWeeks","shortcutPropagation","startingDay","yearColumns","yearRows"].forEach(function(b){switch(b){case"customClass":case"dateDisabled":a[b]=a.datepickerOptions[b]||angular.noop;break;case"datepickerMode":a.datepickerMode=angular.isDefined(a.datepickerOptions.datepickerMode)?a.datepickerOptions.datepickerMode:i.datepickerMode;break;case"formatDay":case"formatDayHeader":case"formatDayTitle":case"formatMonth":case"formatMonthTitle":case"formatYear":n[b]=angular.isDefined(a.datepickerOptions[b])?e(a.datepickerOptions[b])(a.$parent):i[b];break;case"monthColumns":case"showWeeks":case"shortcutPropagation":case"yearColumns":case"yearRows":n[b]=angular.isDefined(a.datepickerOptions[b])?a.datepickerOptions[b]:i[b];break;case"startingDay":angular.isDefined(a.datepickerOptions.startingDay)?n.startingDay=a.datepickerOptions.startingDay:angular.isNumber(i.startingDay)?n.startingDay=i.startingDay:n.startingDay=(f.DATETIME_FORMATS.FIRSTDAYOFWEEK+8)%7;break;case"maxDate":case"minDate":a.$watch("datepickerOptions."+b,function(a){a?angular.isDate(a)?n[b]=l.fromTimezone(new Date(a),p.timezone):(j&&g.warn("Literal date support has been deprecated, please switch to date object usage"),n[b]=new Date(h(a,"medium"))):n[b]=i[b]?l.fromTimezone(new Date(i[b]),p.timezone):null,n.refreshView()});break;case"maxMode":case"minMode":a.datepickerOptions[b]?a.$watch(function(){return a.datepickerOptions[b]},function(c){n[b]=a[b]=angular.isDefined(c)?c:a.datepickerOptions[b],("minMode"===b&&n.modes.indexOf(a.datepickerOptions.datepickerMode)<n.modes.indexOf(n[b])||"maxMode"===b&&n.modes.indexOf(a.datepickerOptions.datepickerMode)>n.modes.indexOf(n[b]))&&(a.datepickerMode=n[b],a.datepickerOptions.datepickerMode=n[b])}):n[b]=a[b]=i[b]||null}}),a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),a.disabled=angular.isDefined(c.disabled)||!1,angular.isDefined(c.ngDisabled)&&q.push(a.$parent.$watch(c.ngDisabled,function(b){a.disabled=b,n.refreshView()})),a.isActive=function(b){return 0===n.compare(b.date,n.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(b){o=b,p=b.$options||a.datepickerOptions.ngModelOptions||i.ngModelOptions,a.datepickerOptions.initDate?(n.activeDate=l.fromTimezone(a.datepickerOptions.initDate,p.timezone)||new Date,a.$watch("datepickerOptions.initDate",function(a){a&&(o.$isEmpty(o.$modelValue)||o.$invalid)&&(n.activeDate=l.fromTimezone(a,p.timezone),n.refreshView())})):n.activeDate=new Date;var c=o.$modelValue?new Date(o.$modelValue):new Date;this.activeDate=isNaN(c)?l.fromTimezone(new Date,p.timezone):l.fromTimezone(c,p.timezone),o.$render=function(){n.render()}},this.render=function(){if(o.$viewValue){var a=new Date(o.$viewValue),b=!isNaN(a);b?this.activeDate=l.fromTimezone(a,p.timezone):k||g.error('Datepicker directive: "ng-model" value must be a Date object')}this.refreshView()},this.refreshView=function(){if(this.element){a.selectedDt=null,this._refreshView(),a.activeDt&&(a.activeDateId=a.activeDt.uid);var b=o.$viewValue?new Date(o.$viewValue):null;b=l.fromTimezone(b,p.timezone),o.$setValidity("dateDisabled",!b||this.element&&!this.isDisabled(b))}},this.createDateObject=function(b,c){var d=o.$viewValue?new Date(o.$viewValue):null;d=l.fromTimezone(d,p.timezone);var e=new Date;e=l.fromTimezone(e,p.timezone);var f=this.compare(b,e),g={date:b,label:l.filter(b,c),selected:d&&0===this.compare(b,d),disabled:this.isDisabled(b),past:0>f,current:0===f,future:f>0,customClass:this.customClass(b)||null};return d&&0===this.compare(b,d)&&(a.selectedDt=g),n.activeDate&&0===this.compare(g.date,n.activeDate)&&(a.activeDt=g),g},this.isDisabled=function(b){return a.disabled||this.minDate&&this.compare(b,this.minDate)<0||this.maxDate&&this.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===n.minMode){var c=o.$viewValue?l.fromTimezone(new Date(o.$viewValue),p.timezone):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),c=l.toTimezone(c,p.timezone),o.$setViewValue(c),o.$render()}else n.activeDate=b,m(n.modes[n.modes.indexOf(a.datepickerMode)-1]),a.$emit("uib:datepicker.mode");a.$broadcast("uib:datepicker.focus")},a.move=function(a){var b=n.activeDate.getFullYear()+a*(n.step.years||0),c=n.activeDate.getMonth()+a*(n.step.months||0);n.activeDate.setFullYear(b,c,1),n.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===n.maxMode&&1===b||a.datepickerMode===n.minMode&&-1===b||(m(n.modes[n.modes.indexOf(a.datepickerMode)+b]),a.$emit("uib:datepicker.mode"))},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var r=function(){n.element[0].focus()};a.$on("uib:datepicker.focus",r),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey&&!a.disabled)if(b.preventDefault(),n.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(n.isDisabled(n.activeDate))return;a.select(n.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(n.handleKeyDown(c,b),n.refreshView()):a.toggleMode("up"===c?1:-1)},b.on("keydown",function(b){a.$apply(function(){a.keydown(b)})}),a.$on("$destroy",function(){for(;q.length;)q.shift()()})}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;b>f;)c=new Date(e),d[f++]=c,e.setDate(e.getDate()+1);return d},this._refreshView=function(){var b=this.activeDate.getFullYear(),d=this.activeDate.getMonth(),f=new Date(this.activeDate);f.setFullYear(b,d,1);var g=this.startingDay-f.getDay(),h=g>0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;42>k;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;7>l;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;n>o;o++)a.weekNumbers.push(e(a.rows[o][m].date))}},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth(),a.getDate()),d=new Date(b.getFullYear(),b.getMonth(),b.getDate());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getDate();if("left"===a)c-=1;else if("up"===a)c-=7;else if("right"===a)c+=1;else if("down"===a)c+=7;else if("pageup"===a||"pagedown"===a){var e=this.activeDate.getMonth()+("pageup"===a?-1:1);this.activeDate.setMonth(e,1),c=Math.min(d(this.activeDate.getFullYear(),this.activeDate.getMonth()),c)}else"home"===a?c=1:"end"===a&&(c=d(this.activeDate.getFullYear(),this.activeDate.getMonth()));this.activeDate.setDate(c)}}]).controller("UibMonthpickerController",["$scope","$element","dateFilter",function(a,b,c){this.step={years:1},this.element=b,this.init=function(a){angular.extend(a,this),a.refreshView()},this._refreshView=function(){for(var b,d=new Array(12),e=this.activeDate.getFullYear(),f=0;12>f;f++)b=new Date(this.activeDate),b.setFullYear(e,f,1),d[f]=angular.extend(this.createDateObject(b,this.formatMonth),{uid:a.uniqueId+"-"+f});a.title=c(this.activeDate,this.formatMonthTitle),a.rows=this.split(d,this.monthColumns),a.yearHeaderColspan=this.monthColumns>3?this.monthColumns-2:1},this.compare=function(a,b){var c=new Date(a.getFullYear(),a.getMonth()),d=new Date(b.getFullYear(),b.getMonth());return c.setFullYear(a.getFullYear()),d.setFullYear(b.getFullYear()),c-d},this.handleKeyDown=function(a,b){var c=this.activeDate.getMonth();if("left"===a)c-=1;else if("up"===a)c-=this.monthColumns;else if("right"===a)c+=1;else if("down"===a)c+=this.monthColumns;else if("pageup"===a||"pagedown"===a){var d=this.activeDate.getFullYear()+("pageup"===a?-1:1);this.activeDate.setFullYear(d)}else"home"===a?c=0:"end"===a&&(c=11);this.activeDate.setMonth(c)}}]).controller("UibYearpickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a){return parseInt((a-1)/f,10)*f+1}var e,f;this.element=b,this.yearpickerInit=function(){e=this.yearColumns,f=this.yearRows*e,this.step={years:f}},this._refreshView=function(){for(var b,c=new Array(f),g=0,h=d(this.activeDate.getFullYear());f>g;g++)b=new Date(this.activeDate),b.setFullYear(h+g,0,1),c[g]=angular.extend(this.createDateObject(b,this.formatYear),{uid:a.uniqueId+"-"+g});a.title=[c[0].label,c[f-1].label].join(" - "),a.rows=this.split(c,e),a.columns=e},this.compare=function(a,b){return a.getFullYear()-b.getFullYear()},this.handleKeyDown=function(a,b){var c=this.activeDate.getFullYear();"left"===a?c-=1:"up"===a?c-=e:"right"===a?c+=1:"down"===a?c+=e:"pageup"===a||"pagedown"===a?c+=("pageup"===a?-1:1)*f:"home"===a?c=d(this.activeDate.getFullYear()):"end"===a&&(c=d(this.activeDate.getFullYear())+f-1),this.activeDate.setFullYear(c)}}]).directive("uibDatepicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/datepicker.html"},scope:{datepickerOptions:"=?"},require:["uibDatepicker","^ngModel"],restrict:"A",controller:"UibDatepickerController",controllerAs:"datepicker",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}).directive("uibDaypicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/day.html"},require:["^uibDatepicker","uibDaypicker"],restrict:"A",controller:"UibDaypickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibMonthpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/month.html"},require:["^uibDatepicker","uibMonthpicker"],restrict:"A",controller:"UibMonthpickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibYearpicker",function(){return{templateUrl:function(a,b){return b.templateUrl||"uib/template/datepicker/year.html"},require:["^uibDatepicker","uibYearpicker"],restrict:"A",controller:"UibYearpickerController",link:function(a,b,c,d){var e=d[0];angular.extend(e,d[1]),e.yearpickerInit(),e.refreshView()}}}),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(a,b){var c,d,e={normal:/(auto|scroll)/,
hidden:/(auto|scroll|hidden)/},f={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/},g=/(HTML|BODY)/;return{getRawNode:function(a){return a.nodeName?a:a[0]||a},parseStyle:function(a){return a=parseFloat(a),isFinite(a)?a:0},offsetParent:function(c){function d(a){return"static"===(b.getComputedStyle(a).position||"static")}c=this.getRawNode(c);for(var e=c.offsetParent||a[0].documentElement;e&&e!==a[0].documentElement&&d(e);)e=e.offsetParent;return e||a[0].documentElement},scrollbarWidth:function(e){if(e){if(angular.isUndefined(d)){var f=a.find("body");f.addClass("uib-position-body-scrollbar-measure"),d=b.innerWidth-f[0].clientWidth,d=isFinite(d)?d:0,f.removeClass("uib-position-body-scrollbar-measure")}return d}if(angular.isUndefined(c)){var g=angular.element('<div class="uib-position-scrollbar-measure"></div>');a.find("body").append(g),c=g[0].offsetWidth-g[0].clientWidth,c=isFinite(c)?c:0,g.remove()}return c},scrollbarPadding:function(a){a=this.getRawNode(a);var c=b.getComputedStyle(a),d=this.parseStyle(c.paddingRight),e=this.parseStyle(c.paddingBottom),f=this.scrollParent(a,!1,!0),h=this.scrollbarWidth(g.test(f.tagName));return{scrollbarWidth:h,widthOverflow:f.scrollWidth>f.clientWidth,right:d+h,originalRight:d,heightOverflow:f.scrollHeight>f.clientHeight,bottom:e+h,originalBottom:e}},isScrollable:function(a,c){a=this.getRawNode(a);var d=c?e.hidden:e.normal,f=b.getComputedStyle(a);return d.test(f.overflow+f.overflowY+f.overflowX)},scrollParent:function(c,d,f){c=this.getRawNode(c);var g=d?e.hidden:e.normal,h=a[0].documentElement,i=b.getComputedStyle(c);if(f&&g.test(i.overflow+i.overflowY+i.overflowX))return c;var j="absolute"===i.position,k=c.parentElement||h;if(k===h||"fixed"===i.position)return h;for(;k.parentElement&&k!==h;){var l=b.getComputedStyle(k);if(j&&"static"!==l.position&&(j=!1),!j&&g.test(l.overflow+l.overflowY+l.overflowX))break;k=k.parentElement}return k},position:function(c,d){c=this.getRawNode(c);var e=this.offset(c);if(d){var f=b.getComputedStyle(c);e.top-=this.parseStyle(f.marginTop),e.left-=this.parseStyle(f.marginLeft)}var g=this.offsetParent(c),h={top:0,left:0};return g!==a[0].documentElement&&(h=this.offset(g),h.top+=g.clientTop-g.scrollTop,h.left+=g.clientLeft-g.scrollLeft),{width:Math.round(angular.isNumber(e.width)?e.width:c.offsetWidth),height:Math.round(angular.isNumber(e.height)?e.height:c.offsetHeight),top:Math.round(e.top-h.top),left:Math.round(e.left-h.left)}},offset:function(c){c=this.getRawNode(c);var d=c.getBoundingClientRect();return{width:Math.round(angular.isNumber(d.width)?d.width:c.offsetWidth),height:Math.round(angular.isNumber(d.height)?d.height:c.offsetHeight),top:Math.round(d.top+(b.pageYOffset||a[0].documentElement.scrollTop)),left:Math.round(d.left+(b.pageXOffset||a[0].documentElement.scrollLeft))}},viewportOffset:function(c,d,e){c=this.getRawNode(c),e=e!==!1;var f=c.getBoundingClientRect(),g={top:0,left:0,bottom:0,right:0},h=d?a[0].documentElement:this.scrollParent(c),i=h.getBoundingClientRect();if(g.top=i.top+h.clientTop,g.left=i.left+h.clientLeft,h===a[0].documentElement&&(g.top+=b.pageYOffset,g.left+=b.pageXOffset),g.bottom=g.top+h.clientHeight,g.right=g.left+h.clientWidth,e){var j=b.getComputedStyle(h);g.top+=this.parseStyle(j.paddingTop),g.bottom-=this.parseStyle(j.paddingBottom),g.left+=this.parseStyle(j.paddingLeft),g.right-=this.parseStyle(j.paddingRight)}return{top:Math.round(f.top-g.top),bottom:Math.round(g.bottom-f.bottom),left:Math.round(f.left-g.left),right:Math.round(g.right-f.right)}},parsePlacement:function(a){var b=f.auto.test(a);return b&&(a=a.replace(f.auto,"")),a=a.split("-"),a[0]=a[0]||"top",f.primary.test(a[0])||(a[0]="top"),a[1]=a[1]||"center",f.secondary.test(a[1])||(a[1]="center"),b?a[2]=!0:a[2]=!1,a},positionElements:function(a,c,d,e){a=this.getRawNode(a),c=this.getRawNode(c);var g=angular.isDefined(c.offsetWidth)?c.offsetWidth:c.prop("offsetWidth"),h=angular.isDefined(c.offsetHeight)?c.offsetHeight:c.prop("offsetHeight");d=this.parsePlacement(d);var i=e?this.offset(a):this.position(a),j={top:0,left:0,placement:""};if(d[2]){var k=this.viewportOffset(a,e),l=b.getComputedStyle(c),m={width:g+Math.round(Math.abs(this.parseStyle(l.marginLeft)+this.parseStyle(l.marginRight))),height:h+Math.round(Math.abs(this.parseStyle(l.marginTop)+this.parseStyle(l.marginBottom)))};if(d[0]="top"===d[0]&&m.height>k.top&&m.height<=k.bottom?"bottom":"bottom"===d[0]&&m.height>k.bottom&&m.height<=k.top?"top":"left"===d[0]&&m.width>k.left&&m.width<=k.right?"right":"right"===d[0]&&m.width>k.right&&m.width<=k.left?"left":d[0],d[1]="top"===d[1]&&m.height-i.height>k.bottom&&m.height-i.height<=k.top?"bottom":"bottom"===d[1]&&m.height-i.height>k.top&&m.height-i.height<=k.bottom?"top":"left"===d[1]&&m.width-i.width>k.right&&m.width-i.width<=k.left?"right":"right"===d[1]&&m.width-i.width>k.left&&m.width-i.width<=k.right?"left":d[1],"center"===d[1])if(f.vertical.test(d[0])){var n=i.width/2-g/2;k.left+n<0&&m.width-i.width<=k.right?d[1]="left":k.right+n<0&&m.width-i.width<=k.left&&(d[1]="right")}else{var o=i.height/2-m.height/2;k.top+o<0&&m.height-i.height<=k.bottom?d[1]="top":k.bottom+o<0&&m.height-i.height<=k.top&&(d[1]="bottom")}}switch(d[0]){case"top":j.top=i.top-h;break;case"bottom":j.top=i.top+i.height;break;case"left":j.left=i.left-g;break;case"right":j.left=i.left+i.width}switch(d[1]){case"top":j.top=i.top;break;case"bottom":j.top=i.top+i.height-h;break;case"left":j.left=i.left;break;case"right":j.left=i.left+i.width-g;break;case"center":f.vertical.test(d[0])?j.left=i.left+i.width/2-g/2:j.top=i.top+i.height/2-h/2}return j.top=Math.round(j.top),j.left=Math.round(j.left),j.placement="center"===d[1]?d[0]:d[0]+"-"+d[1],j},adjustTop:function(a,b,c,d){return-1!==a.indexOf("top")&&c!==d?{top:b.top-d+"px"}:void 0},positionArrow:function(a,c){a=this.getRawNode(a);var d=a.querySelector(".tooltip-inner, .popover-inner");if(d){var e=angular.element(d).hasClass("tooltip-inner"),g=e?a.querySelector(".tooltip-arrow"):a.querySelector(".arrow");if(g){var h={top:"",bottom:"",left:"",right:""};if(c=this.parsePlacement(c),"center"===c[1])return void angular.element(g).css(h);var i="border-"+c[0]+"-width",j=b.getComputedStyle(g)[i],k="border-";k+=f.vertical.test(c[0])?c[0]+"-"+c[1]:c[1]+"-"+c[0],k+="-radius";var l=b.getComputedStyle(e?d:a)[k];switch(c[0]){case"top":h.bottom=e?"0":"-"+j;break;case"bottom":h.top=e?"0":"-"+j;break;case"left":h.right=e?"0":"-"+j;break;case"right":h.left=e?"0":"-"+j}h[c[1]]=l,angular.element(g).css(h)}}}}}]),angular.module("ui.bootstrap.datepickerPopup",["ui.bootstrap.datepicker","ui.bootstrap.position"]).value("$datepickerPopupLiteralWarning",!0).constant("uibDatepickerPopupConfig",{altInputFormats:[],appendToBody:!1,clearText:"Clear",closeOnDateSelection:!0,closeText:"Done",currentText:"Today",datepickerPopup:"yyyy-MM-dd",datepickerPopupTemplateUrl:"uib/template/datepickerPopup/popup.html",datepickerTemplateUrl:"uib/template/datepicker/datepicker.html",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},onOpenFocus:!0,showButtonBar:!0,placement:"auto bottom-left"}).controller("UibDatepickerPopupController",["$scope","$element","$attrs","$compile","$log","$parse","$window","$document","$rootScope","$uibPosition","dateFilter","uibDateParser","uibDatepickerPopupConfig","$timeout","uibDatepickerConfig","$datepickerPopupLiteralWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){function q(b){var c=l.parse(b,w,a.date);if(isNaN(c))for(var d=0;d<I.length;d++)if(c=l.parse(b,I[d],a.date),!isNaN(c))return c;return c}function r(a){if(angular.isNumber(a)&&(a=new Date(a)),!a)return null;if(angular.isDate(a)&&!isNaN(a))return a;if(angular.isString(a)){var b=q(a);if(!isNaN(b))return l.fromTimezone(b,G.timezone)}return F.$options&&F.$options.allowInvalid?a:void 0}function s(a,b){var d=a||b;return c.ngRequired||d?(angular.isNumber(d)&&(d=new Date(d)),d?angular.isDate(d)&&!isNaN(d)?!0:angular.isString(d)?!isNaN(q(d)):!1:!0):!0}function t(c){if(a.isOpen||!a.disabled){var d=H[0],e=b[0].contains(c.target),f=void 0!==d.contains&&d.contains(c.target);!a.isOpen||e||f||a.$apply(function(){a.isOpen=!1})}}function u(c){27===c.which&&a.isOpen?(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!1}),b[0].focus()):40!==c.which||a.isOpen||(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!0}))}function v(){if(a.isOpen){var d=angular.element(H[0].querySelector(".uib-datepicker-popup")),e=c.popupPlacement?c.popupPlacement:m.placement,f=j.positionElements(b,d,e,y);d.css({top:f.top+"px",left:f.left+"px"}),d.hasClass("uib-position-measure")&&d.removeClass("uib-position-measure")}}var w,x,y,z,A,B,C,D,E,F,G,H,I,J=!1,K=[];this.init=function(e){if(F=e,G=angular.isObject(e.$options)?e.$options:{timezone:null},x=angular.isDefined(c.closeOnDateSelection)?a.$parent.$eval(c.closeOnDateSelection):m.closeOnDateSelection,y=angular.isDefined(c.datepickerAppendToBody)?a.$parent.$eval(c.datepickerAppendToBody):m.appendToBody,z=angular.isDefined(c.onOpenFocus)?a.$parent.$eval(c.onOpenFocus):m.onOpenFocus,A=angular.isDefined(c.datepickerPopupTemplateUrl)?c.datepickerPopupTemplateUrl:m.datepickerPopupTemplateUrl,B=angular.isDefined(c.datepickerTemplateUrl)?c.datepickerTemplateUrl:m.datepickerTemplateUrl,I=angular.isDefined(c.altInputFormats)?a.$parent.$eval(c.altInputFormats):m.altInputFormats,a.showButtonBar=angular.isDefined(c.showButtonBar)?a.$parent.$eval(c.showButtonBar):m.showButtonBar,m.html5Types[c.type]?(w=m.html5Types[c.type],J=!0):(w=c.uibDatepickerPopup||m.datepickerPopup,c.$observe("uibDatepickerPopup",function(a,b){var c=a||m.datepickerPopup;if(c!==w&&(w=c,F.$modelValue=null,!w))throw new Error("uibDatepickerPopup must have a date format specified.")})),!w)throw new Error("uibDatepickerPopup must have a date format specified.");if(J&&c.uibDatepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");C=angular.element("<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>"),C.attr({"ng-model":"date","ng-change":"dateSelection(date)","template-url":A}),D=angular.element(C.children()[0]),D.attr("template-url",B),a.datepickerOptions||(a.datepickerOptions={}),J&&"month"===c.type&&(a.datepickerOptions.datepickerMode="month",a.datepickerOptions.minMode="month"),D.attr("datepicker-options","datepickerOptions"),J?F.$formatters.push(function(b){return a.date=l.fromTimezone(b,G.timezone),b}):(F.$$parserName="date",F.$validators.date=s,F.$parsers.unshift(r),F.$formatters.push(function(b){return F.$isEmpty(b)?(a.date=b,b):(angular.isNumber(b)&&(b=new Date(b)),a.date=l.fromTimezone(b,G.timezone),l.filter(a.date,w))})),F.$viewChangeListeners.push(function(){a.date=q(F.$viewValue)}),b.on("keydown",u),H=d(C)(a),C.remove(),y?h.find("body").append(H):b.after(H),a.$on("$destroy",function(){for(a.isOpen===!0&&(i.$$phase||a.$apply(function(){a.isOpen=!1})),H.remove(),b.off("keydown",u),h.off("click",t),E&&E.off("scroll",v),angular.element(g).off("resize",v);K.length;)K.shift()()})},a.getText=function(b){return a[b+"Text"]||m[b+"Text"]},a.isDisabled=function(b){"today"===b&&(b=l.fromTimezone(new Date,G.timezone));var c={};return angular.forEach(["minDate","maxDate"],function(b){a.datepickerOptions[b]?angular.isDate(a.datepickerOptions[b])?c[b]=new Date(a.datepickerOptions[b]):(p&&e.warn("Literal date support has been deprecated, please switch to date object usage"),c[b]=new Date(k(a.datepickerOptions[b],"medium"))):c[b]=null}),a.datepickerOptions&&c.minDate&&a.compare(b,c.minDate)<0||c.maxDate&&a.compare(b,c.maxDate)>0},a.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},a.dateSelection=function(c){a.date=c;var d=a.date?l.filter(a.date,w):null;b.val(d),F.$setViewValue(d),x&&(a.isOpen=!1,b[0].focus())},a.keydown=function(c){27===c.which&&(c.stopPropagation(),a.isOpen=!1,b[0].focus())},a.select=function(b,c){if(c.stopPropagation(),"today"===b){var d=new Date;angular.isDate(a.date)?(b=new Date(a.date),b.setFullYear(d.getFullYear(),d.getMonth(),d.getDate())):(b=l.fromTimezone(d,G.timezone),b.setHours(0,0,0,0))}a.dateSelection(b)},a.close=function(c){c.stopPropagation(),a.isOpen=!1,b[0].focus()},a.disabled=angular.isDefined(c.disabled)||!1,c.ngDisabled&&K.push(a.$parent.$watch(f(c.ngDisabled),function(b){a.disabled=b})),a.$watch("isOpen",function(d){d?a.disabled?a.isOpen=!1:n(function(){v(),z&&a.$broadcast("uib:datepicker.focus"),h.on("click",t);var d=c.popupPlacement?c.popupPlacement:m.placement;y||j.parsePlacement(d)[2]?(E=E||angular.element(j.scrollParent(b)),E&&E.on("scroll",v)):E=null,angular.element(g).on("resize",v)},0,!1):(h.off("click",t),E&&E.off("scroll",v),angular.element(g).off("resize",v))}),a.$on("uib:datepicker.mode",function(){n(v,0,!1)})}]).directive("uibDatepickerPopup",function(){return{require:["ngModel","uibDatepickerPopup"],controller:"UibDatepickerPopupController",scope:{datepickerOptions:"=?",isOpen:"=?",currentText:"@",clearText:"@",closeText:"@"},link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibDatepickerPopupWrap",function(){return{restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/datepickerPopup/popup.html"}}}),angular.module("ui.bootstrap.debounce",[]).factory("$$debounce",["$timeout",function(a){return function(b,c){var d;return function(){var e=this,f=Array.prototype.slice.call(arguments);d&&a.cancel(d),d=a(function(){b.apply(e,f)},c)}}}]),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("uibDropdownConfig",{appendToOpenClass:"uib-dropdown-open",openClass:"open"}).service("uibDropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b,e){c||a.on("click",d),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b,e){c===b&&(a.off("click",d),a.off("keydown",this.keybindFilter),c=null)};var d=function(a){if(c&&!(a&&"disabled"===c.getAutoClose()||a&&3===a.which)){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getDropdownElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.focusToggleElement(),c.isOpen=!1,b.$$phase||c.$apply())}}};this.keybindFilter=function(a){if(c){var b=c.getDropdownElement(),e=c.getToggleElement(),f=b&&b[0].contains(a.target),g=e&&e[0].contains(a.target);27===a.which?(a.stopPropagation(),c.focusToggleElement(),d()):c.isKeynavEnabled()&&-1!==[38,40].indexOf(a.which)&&c.isOpen&&(f||g)&&(a.preventDefault(),a.stopPropagation(),c.focusDropdownEntry(a.which))}}}]).controller("UibDropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest",function(a,b,c,d,e,f,g,h,i,j,k){var l,m,n=this,o=a.$new(),p=e.appendToOpenClass,q=e.openClass,r=angular.noop,s=c.onToggle?d(c.onToggle):angular.noop,t=!1,u=null,v=!1,w=i.find("body");b.addClass("dropdown"),this.init=function(){if(c.isOpen&&(m=d(c.isOpen),r=m.assign,a.$watch(m,function(a){o.isOpen=!!a})),angular.isDefined(c.dropdownAppendTo)){var e=d(c.dropdownAppendTo)(o);e&&(u=angular.element(e))}t=angular.isDefined(c.dropdownAppendToBody),v=angular.isDefined(c.keyboardNav),t&&!u&&(u=w),u&&n.dropdownMenu&&(u.append(n.dropdownMenu),b.on("$destroy",function(){n.dropdownMenu.remove()}))},this.toggle=function(a){return o.isOpen=arguments.length?!!a:!o.isOpen,angular.isFunction(r)&&r(o,o.isOpen),o.isOpen},this.isOpen=function(){return o.isOpen},o.getToggleElement=function(){return n.toggleElement},o.getAutoClose=function(){return c.autoClose||"always"},o.getElement=function(){return b},o.isKeynavEnabled=function(){return v},o.focusDropdownEntry=function(a){var c=n.dropdownMenu?angular.element(n.dropdownMenu).find("a"):b.find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(n.selectedOption)?n.selectedOption=n.selectedOption===c.length-1?n.selectedOption:n.selectedOption+1:n.selectedOption=0;break;case 38:angular.isNumber(n.selectedOption)?n.selectedOption=0===n.selectedOption?0:n.selectedOption-1:n.selectedOption=c.length-1}c[n.selectedOption].focus()},o.getDropdownElement=function(){return n.dropdownMenu},o.focusToggleElement=function(){n.toggleElement&&n.toggleElement[0].focus()},o.$watch("isOpen",function(c,d){if(u&&n.dropdownMenu){var e,m,v,w=h.positionElements(b,n.dropdownMenu,"bottom-left",!0),x=0;if(e={top:w.top+"px",display:c?"block":"none"},m=n.dropdownMenu.hasClass("dropdown-menu-right"),m?(e.left="auto",v=h.scrollbarPadding(u),v.heightOverflow&&v.scrollbarWidth&&(x=v.scrollbarWidth),e.right=window.innerWidth-x-(w.left+b.prop("offsetWidth"))+"px"):(e.left=w.left+"px",e.right="auto"),!t){var y=h.offset(u);e.top=w.top-y.top+"px",m?e.right=window.innerWidth-(w.left-y.left+b.prop("offsetWidth"))+"px":e.left=w.left-y.left+"px"}n.dropdownMenu.css(e)}var z=u?u:b,A=z.hasClass(u?p:q);if(A===!c&&g[c?"addClass":"removeClass"](z,u?p:q).then(function(){angular.isDefined(c)&&c!==d&&s(a,{open:!!c})}),c)n.dropdownMenuTemplateUrl?k(n.dropdownMenuTemplateUrl).then(function(a){l=o.$new(),j(a.trim())(l,function(a){var b=a;n.dropdownMenu.replaceWith(b),n.dropdownMenu=b,i.on("keydown",f.keybindFilter)})}):i.on("keydown",f.keybindFilter),o.focusToggleElement(),f.open(o,b);else{if(f.close(o,b),n.dropdownMenuTemplateUrl){l&&l.$destroy();var B=angular.element('<ul class="dropdown-menu"></ul>');n.dropdownMenu.replaceWith(B),n.dropdownMenu=B}n.selectedOption=null}angular.isFunction(r)&&r(a,c)})}]).directive("uibDropdown",function(){return{controller:"UibDropdownController",link:function(a,b,c,d){d.init()}}}).directive("uibDropdownMenu",function(){return{restrict:"A",require:"?^uibDropdown",link:function(a,b,c,d){if(d&&!angular.isDefined(c.dropdownNested)){b.addClass("dropdown-menu");var e=c.templateUrl;e&&(d.dropdownMenuTemplateUrl=e),d.dropdownMenu||(d.dropdownMenu=b)}}}}).directive("uibDropdownToggle",function(){return{require:"?^uibDropdown",link:function(a,b,c,d){if(d){b.addClass("dropdown-toggle"),d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b===a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b===a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.pop()},length:function(){return a.length}}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.stackedMap","ui.bootstrap.position"]).factory("$$multiMap",function(){return{createNew:function(){var a={};return{entries:function(){return Object.keys(a).map(function(b){return{key:b,value:a[b]}})},get:function(b){return a[b]},hasKey:function(b){return!!a[b]},keys:function(){return Object.keys(a)},put:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},remove:function(b,c){var d=a[b];if(d){var e=d.indexOf(c);-1!==e&&d.splice(e,1),d.length||delete a[b]}}}}}}).provider("$uibResolve",function(){var a=this;this.resolver=null,this.setResolver=function(a){this.resolver=a},this.$get=["$injector","$q",function(b,c){var d=a.resolver?b.get(a.resolver):null;return{resolve:function(a,e,f,g){if(d)return d.resolve(a,e,f,g);var h=[];return angular.forEach(a,function(a){angular.isFunction(a)||angular.isArray(a)?h.push(c.resolve(b.invoke(a))):angular.isString(a)?h.push(c.resolve(b.get(a))):h.push(c.resolve(a))}),c.all(h).then(function(b){var c={},d=0;return angular.forEach(a,function(a,e){c[e]=b[d++]}),c})}}}]}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(a,b,c){function d(b,d,e){e.modalInClass&&(a.addClass(d,e.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(c,f){var g=f();b.modalOptions.animation?a.removeClass(d,e.modalInClass).then(g):g()}))}return{restrict:"A",compile:function(a,b){return a.addClass(b.backdropClass),d}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animateCss","$document",function(a,b,c,d){return{scope:{index:"@"},restrict:"A",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/modal/window.html"},link:function(e,f,g){f.addClass(g.windowTopClass||""),e.size=g.size,e.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},f.on("click",e.close),e.$isRendered=!0;var h=b.defer();e.$$postDigest(function(){h.resolve()}),h.promise.then(function(){var h=null;g.modalInClass&&(h=c(f,{addClass:g.modalInClass}).start(),e.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();c(f,{removeClass:g.modalInClass}).start().then(d)})),b.when(h).then(function(){var b=a.getTop();if(b&&a.modalRendered(b.key),!d[0].activeElement||!f[0].contains(d[0].activeElement)){var c=f[0].querySelector("[autofocus]");c?c.focus():f[0].focus()}})})}}}]).directive("uibModalAnimationClass",function(){return{compile:function(a,b){b.modalAnimation&&a.addClass(b.uibModalAnimationClass)}}}).directive("uibModalTransclude",["$animate",function(a){return{link:function(b,c,d,e,f){f(b.$parent,function(b){c.empty(),a.enter(b,c)})}}}]).factory("$uibModalStack",["$animate","$animateCss","$document","$compile","$rootScope","$q","$$multiMap","$$stackedMap","$uibPosition",function(a,b,c,d,e,f,g,h,i){function j(a){var b="-";return a.replace(E,function(a,c){return(c?b:"")+a.toLowerCase()})}function k(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)}function l(){for(var a=-1,b=x.keys(),c=0;c<b.length;c++)x.get(b[c]).value.backdrop&&(a=c);return a>-1&&A>a&&(a=A),a}function m(a,b){var c=x.get(a).value,d=c.appendTo;x.remove(a),B=x.top(),B&&(A=parseInt(B.value.modalDomEl.attr("index"),10)),p(c.modalDomEl,c.modalScope,function(){var b=c.openedClass||w;y.remove(b,a);var e=y.hasKey(b);d.toggleClass(b,e),!e&&v&&v.heightOverflow&&v.scrollbarWidth&&(v.originalRight?d.css({paddingRight:v.originalRight+"px"}):d.css({paddingRight:""}),v=null),n(!0)},c.closedDeferred),o(),b&&b.focus?b.focus():d.focus&&d.focus()}function n(a){var b;x.length()>0&&(b=x.top().value,b.modalDomEl.toggleClass(b.windowTopClass||"",a))}function o(){if(t&&-1===l()){var a=u;p(t,u,function(){a=null}),t=void 0,u=void 0}}function p(b,c,d,e){function g(){g.done||(g.done=!0,a.leave(b).then(function(){d&&d(),b.remove(),e&&e.resolve()}),c.$destroy())}var h,i=null,j=function(){return h||(h=f.defer(),i=h.promise),function(){h.resolve()}};return c.$broadcast(z.NOW_CLOSING_EVENT,j),f.when(i).then(g)}function q(a){if(a.isDefaultPrevented())return a;var b=x.top();if(b)switch(a.which){case 27:b.value.keyboard&&(a.preventDefault(),e.$apply(function(){z.dismiss(b.key,"escape key press")}));break;case 9:var c=z.loadFocusElementList(b),d=!1;a.shiftKey?(z.isFocusInFirstItem(a,c)||z.isModalFocused(a,b))&&(d=z.focusLastFocusableElement(c)):z.isFocusInLastItem(a,c)&&(d=z.focusFirstFocusableElement(c)),d&&(a.preventDefault(),a.stopPropagation())}}function r(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}function s(){Array.prototype.forEach.call(document.querySelectorAll("["+C+"]"),function(a){var b=parseInt(a.getAttribute(C),10),c=b-1;a.setAttribute(C,c),c||(a.removeAttribute(C),a.removeAttribute("aria-hidden"))})}var t,u,v,w="modal-open",x=h.createNew(),y=g.createNew(),z={NOW_CLOSING_EVENT:"modal.stack.now-closing"},A=0,B=null,C="data-bootstrap-modal-aria-hidden-count",D="a[href], area[href], input:not([disabled]):not([tabindex='-1']), button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']), textarea:not([disabled]):not([tabindex='-1']), iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]",E=/[A-Z]/g;return e.$watch(l,function(a){u&&(u.index=a)}),c.on("keydown",q),e.$on("$destroy",function(){c.off("keydown",q)}),z.open=function(b,f){function g(a){function b(a){var b=a.parent()?a.parent().children():[];return Array.prototype.filter.call(b,function(b){return b!==a[0]})}if(a&&"BODY"!==a[0].tagName)return b(a).forEach(function(a){var b="true"===a.getAttribute("aria-hidden"),c=parseInt(a.getAttribute(C),10);c||(c=b?1:0),a.setAttribute(C,c+1),a.setAttribute("aria-hidden","true")}),g(a.parent())}var h=c[0].activeElement,k=f.openedClass||w;n(!1),B=x.top(),x.add(b,{deferred:f.deferred,renderDeferred:f.renderDeferred,closedDeferred:f.closedDeferred,modalScope:f.scope,backdrop:f.backdrop,keyboard:f.keyboard,openedClass:f.openedClass,windowTopClass:f.windowTopClass,animation:f.animation,appendTo:f.appendTo}),y.put(k,b);var m=f.appendTo,o=l();if(!m.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");o>=0&&!t&&(u=e.$new(!0),u.modalOptions=f,u.index=o,t=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>'),t.attr({"class":"modal-backdrop","ng-style":"{'z-index': 1040 + (index && 1 || 0) + index*10}","uib-modal-animation-class":"fade","modal-in-class":"in"}),f.backdropClass&&t.addClass(f.backdropClass),f.animation&&t.attr("modal-animation","true"),d(t)(u),a.enter(t,m),i.isScrollable(m)&&(v=i.scrollbarPadding(m),v.heightOverflow&&v.scrollbarWidth&&m.css({paddingRight:v.right+"px"})));var p;f.component?(p=document.createElement(j(f.component.name)),p=angular.element(p),p.attr({resolve:"$resolve","modal-instance":"$uibModalInstance",close:"$close($value)",dismiss:"$dismiss($value)"})):p=f.content,A=B?parseInt(B.value.modalDomEl.attr("index"),10)+1:0;var q=angular.element('<div uib-modal-window="modal-window"></div>');q.attr({"class":"modal","template-url":f.windowTemplateUrl,"window-top-class":f.windowTopClass,role:"dialog","aria-labelledby":f.ariaLabelledBy,"aria-describedby":f.ariaDescribedBy,size:f.size,index:A,animate:"animate","ng-style":"{'z-index': 1050 + $$topModalIndex*10, display: 'block'}",tabindex:-1,"uib-modal-animation-class":"fade","modal-in-class":"in"}).append(p),f.windowClass&&q.addClass(f.windowClass),f.animation&&q.attr("modal-animation","true"),m.addClass(k),f.scope&&(f.scope.$$topModalIndex=A),a.enter(d(q)(f.scope),m),x.top().value.modalDomEl=q,x.top().value.modalOpener=h,g(q)},z.close=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!0)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.resolve(b),m(a,c.value.modalOpener),!0):!c},z.dismiss=function(a,b){var c=x.get(a);return s(),c&&r(c,b,!1)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.reject(b),m(a,c.value.modalOpener),!0):!c},z.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},z.getTop=function(){return x.top()},z.modalRendered=function(a){var b=x.get(a);z.focusFirstFocusableElement(z.loadFocusElementList(b)),b&&b.value.renderDeferred.resolve()},z.focusFirstFocusableElement=function(a){return a.length>0?(a[0].focus(),!0):!1},z.focusLastFocusableElement=function(a){return a.length>0?(a[a.length-1].focus(),!0):!1},z.isModalFocused=function(a,b){if(a&&b){var c=b.value.modalDomEl;if(c&&c.length)return(a.target||a.srcElement)===c[0]}return!1},z.isFocusInFirstItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[0]:!1},z.isFocusInLastItem=function(a,b){return b.length>0?(a.target||a.srcElement)===b[b.length-1]:!1},z.loadFocusElementList=function(a){if(a){var b=a.value.modalDomEl;if(b&&b.length){var c=b[0].querySelectorAll(D);return c?Array.prototype.filter.call(c,function(a){return k(a)}):c}}},z}]).provider("$uibModal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$uibResolve","$uibModalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?c.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}var j={},k=null;return j.getPromiseChain=function(){return k},j.open=function(e){function j(){return q}var l=c.defer(),m=c.defer(),n=c.defer(),o=c.defer(),p={result:l.promise,opened:m.promise,closed:n.promise,rendered:o.promise,close:function(a){return h.close(p,a)},dismiss:function(a){return h.dismiss(p,a)}};if(e=angular.extend({},a.options,e),e.resolve=e.resolve||{},e.appendTo=e.appendTo||d.find("body").eq(0),!e.component&&!e.template&&!e.templateUrl)throw new Error("One of component or template or templateUrl options is required.");var q;q=e.component?c.when(g.resolve(e.resolve,{},null,null)):c.all([i(e),g.resolve(e.resolve,{},null,null)]);var r;return r=k=c.all([k]).then(j,j).then(function(a){function c(b,c,d,e){b.$scope=g,b.$scope.$resolve={},d?b.$scope.$uibModalInstance=p:b.$uibModalInstance=p;var f=c?a[1]:a;angular.forEach(f,function(a,c){e&&(b[c]=a),b.$scope.$resolve[c]=a})}var d=e.scope||b,g=d.$new();g.$close=p.close,g.$dismiss=p.dismiss,g.$on("$destroy",function(){g.$$uibDestructionScheduled||g.$dismiss("$uibUnscheduledDestruction")});var i,j,k={scope:g,deferred:l,renderDeferred:o,closedDeferred:n,animation:e.animation,backdrop:e.backdrop,keyboard:e.keyboard,backdropClass:e.backdropClass,windowTopClass:e.windowTopClass,windowClass:e.windowClass,windowTemplateUrl:e.windowTemplateUrl,ariaLabelledBy:e.ariaLabelledBy,ariaDescribedBy:e.ariaDescribedBy,size:e.size,openedClass:e.openedClass,appendTo:e.appendTo},q={},r={};e.component?(c(q,!1,!0,!1),q.name=e.component,k.component=q):e.controller&&(c(r,!0,!1,!0),j=f(e.controller,r,!0,e.controllerAs),e.controllerAs&&e.bindToController&&(i=j.instance,i.$close=g.$close,i.$dismiss=g.$dismiss,angular.extend(i,{$resolve:r.$scope.$resolve},d)),i=j(),angular.isFunction(i.$onInit)&&i.$onInit()),e.component||(k.content=a[0]),h.open(p,k),m.resolve(!0)},function(a){m.reject(a),l.reject(a)})["finally"](function(){k===r&&(k=null)}),p},j}]};return a}),angular.module("ui.bootstrap.paging",[]).factory("uibPaging",["$parse",function(a){return{create:function(b,c,d){b.setNumPages=d.numPages?a(d.numPages).assign:angular.noop,b.ngModelCtrl={$setViewValue:angular.noop},b._watchers=[],b.init=function(a,e){b.ngModelCtrl=a,b.config=e,a.$render=function(){b.render()},d.itemsPerPage?b._watchers.push(c.$parent.$watch(d.itemsPerPage,function(a){b.itemsPerPage=parseInt(a,10),c.totalPages=b.calculateTotalPages(),b.updatePage()})):b.itemsPerPage=e.itemsPerPage,c.$watch("totalItems",function(a,d){(angular.isDefined(a)||a!==d)&&(c.totalPages=b.calculateTotalPages(),b.updatePage())})},b.calculateTotalPages=function(){var a=b.itemsPerPage<1?1:Math.ceil(c.totalItems/b.itemsPerPage);return Math.max(a||0,1)},b.render=function(){c.page=parseInt(b.ngModelCtrl.$viewValue,10)||1},c.selectPage=function(a,d){d&&d.preventDefault();var e=!c.ngDisabled||!d;e&&c.page!==a&&a>0&&a<=c.totalPages&&(d&&d.target&&d.target.blur(),b.ngModelCtrl.$setViewValue(a),b.ngModelCtrl.$render())},c.getText=function(a){return c[a+"Text"]||b.config[a+"Text"]},c.noPrevious=function(){return 1===c.page},c.noNext=function(){return c.page===c.totalPages},b.updatePage=function(){b.setNumPages(c.$parent,c.totalPages),c.page>c.totalPages?c.selectPage(c.totalPages):b.ngModelCtrl.$render()},c.$on("$destroy",function(){for(;b._watchers.length;)b._watchers.shift()()})}}}]),angular.module("ui.bootstrap.pager",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPagerController",["$scope","$attrs","uibPaging","uibPagerConfig",function(a,b,c,d){a.align=angular.isDefined(b.align)?a.$parent.$eval(b.align):d.align,c.create(this,a,b)}]).constant("uibPagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("uibPager",["uibPagerConfig",function(a){return{scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["uibPager","?ngModel"],restrict:"A",controller:"UibPagerController",controllerAs:"pager",templateUrl:function(a,b){
return b.templateUrl||"uib/template/pager/pager.html"},link:function(b,c,d,e){c.addClass("pager");var f=e[0],g=e[1];g&&f.init(g,a)}}}]),angular.module("ui.bootstrap.pagination",["ui.bootstrap.paging","ui.bootstrap.tabindex"]).controller("UibPaginationController",["$scope","$attrs","$parse","uibPaging","uibPaginationConfig",function(a,b,c,d,e){function f(a,b,c){return{number:a,text:b,active:c}}function g(a,b){var c=[],d=1,e=b,g=angular.isDefined(i)&&b>i;g&&(j?(d=Math.max(a-Math.floor(i/2),1),e=d+i-1,e>b&&(e=b,d=e-i+1)):(d=(Math.ceil(a/i)-1)*i+1,e=Math.min(d+i-1,b)));for(var h=d;e>=h;h++){var n=f(h,m(h),h===a);c.push(n)}if(g&&i>0&&(!j||k||l)){if(d>1){if(!l||d>3){var o=f(d-1,"...",!1);c.unshift(o)}if(l){if(3===d){var p=f(2,"2",!1);c.unshift(p)}var q=f(1,"1",!1);c.unshift(q)}}if(b>e){if(!l||b-2>e){var r=f(e+1,"...",!1);c.push(r)}if(l){if(e===b-2){var s=f(b-1,b-1,!1);c.push(s)}var t=f(b,b,!1);c.push(t)}}}return c}var h=this,i=angular.isDefined(b.maxSize)?a.$parent.$eval(b.maxSize):e.maxSize,j=angular.isDefined(b.rotate)?a.$parent.$eval(b.rotate):e.rotate,k=angular.isDefined(b.forceEllipses)?a.$parent.$eval(b.forceEllipses):e.forceEllipses,l=angular.isDefined(b.boundaryLinkNumbers)?a.$parent.$eval(b.boundaryLinkNumbers):e.boundaryLinkNumbers,m=angular.isDefined(b.pageLabel)?function(c){return a.$parent.$eval(b.pageLabel,{$page:c})}:angular.identity;a.boundaryLinks=angular.isDefined(b.boundaryLinks)?a.$parent.$eval(b.boundaryLinks):e.boundaryLinks,a.directionLinks=angular.isDefined(b.directionLinks)?a.$parent.$eval(b.directionLinks):e.directionLinks,d.create(this,a,b),b.maxSize&&h._watchers.push(a.$parent.$watch(c(b.maxSize),function(a){i=parseInt(a,10),h.render()}));var n=this.render;this.render=function(){n(),a.page>0&&a.page<=a.totalPages&&(a.pages=g(a.page,a.totalPages))}}]).constant("uibPaginationConfig",{itemsPerPage:10,boundaryLinks:!1,boundaryLinkNumbers:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0,forceEllipses:!1}).directive("uibPagination",["$parse","uibPaginationConfig",function(a,b){return{scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["uibPagination","?ngModel"],restrict:"A",controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"uib/template/pagination/pagination.html"},link:function(a,c,d,e){c.addClass("pagination");var f=e[0],g=e[1];g&&f.init(g,b)}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.stackedMap"]).provider("$uibTooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",placementClassPrefix:"",animation:!0,popupDelay:0,popupCloseDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",outsideClick:"outsideClick",focus:"blur",none:""},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$uibPosition","$interpolate","$rootScope","$parse","$$stackedMap",function(e,f,g,h,i,j,k,l,m){function n(a){if(27===a.which){var b=o.top();b&&(b.value.close(),b=null)}}var o=m.createNew();return h.on("keyup",n),k.$on("$destroy",function(){h.off("keyup",n)}),function(e,k,m,n){function p(a){var b=(a||n.trigger||m).split(" "),d=b.map(function(a){return c[a]||a});return{show:b,hide:d}}n=angular.extend({},b,d,n);var q=a(e),r=j.startSymbol(),s=j.endSymbol(),t="<div "+q+'-popup uib-title="'+r+"title"+s+'" '+(n.useContentExp?'content-exp="contentExp()" ':'content="'+r+"content"+s+'" ')+'origin-scope="origScope" class="uib-position-measure '+k+'" tooltip-animation-class="fade"uib-tooltip-classes ng-class="{ in: isOpen }" ></div>';return{compile:function(a,b){var c=f(t);return function(a,b,d,f){function j(){O.isOpen?q():m()}function m(){N&&!a.$eval(d[k+"Enable"])||(u(),x(),O.popupDelay?G||(G=g(r,O.popupDelay,!1)):r())}function q(){s(),O.popupCloseDelay?H||(H=g(t,O.popupCloseDelay,!1)):t()}function r(){return s(),u(),O.content?(v(),void O.$evalAsync(function(){O.isOpen=!0,y(!0),T()})):angular.noop}function s(){G&&(g.cancel(G),G=null),I&&(g.cancel(I),I=null)}function t(){O&&O.$evalAsync(function(){O&&(O.isOpen=!1,y(!1),O.animation?F||(F=g(w,150,!1)):w())})}function u(){H&&(g.cancel(H),H=null),F&&(g.cancel(F),F=null)}function v(){D||(E=O.$new(),D=c(E,function(a){L?h.find("body").append(a):b.after(a)}),o.add(O,{close:t}),z())}function w(){s(),u(),A(),D&&(D.remove(),D=null,J&&g.cancel(J)),o.remove(O),E&&(E.$destroy(),E=null)}function x(){O.title=d[k+"Title"],R?O.content=R(a):O.content=d[e],O.popupClass=d[k+"Class"],O.placement=angular.isDefined(d[k+"Placement"])?d[k+"Placement"]:n.placement;var b=i.parsePlacement(O.placement);K=b[1]?b[0]+"-"+b[1]:b[0];var c=parseInt(d[k+"PopupDelay"],10),f=parseInt(d[k+"PopupCloseDelay"],10);O.popupDelay=isNaN(c)?n.popupDelay:c,O.popupCloseDelay=isNaN(f)?n.popupCloseDelay:f}function y(b){Q&&angular.isFunction(Q.assign)&&Q.assign(a,b)}function z(){S.length=0,R?(S.push(a.$watch(R,function(a){O.content=a,!a&&O.isOpen&&t()})),S.push(E.$watch(function(){P||(P=!0,E.$$postDigest(function(){P=!1,O&&O.isOpen&&T()}))}))):S.push(d.$observe(e,function(a){O.content=a,!a&&O.isOpen?t():T()})),S.push(d.$observe(k+"Title",function(a){O.title=a,O.isOpen&&T()})),S.push(d.$observe(k+"Placement",function(a){O.placement=a?a:n.placement,O.isOpen&&T()}))}function A(){S.length&&(angular.forEach(S,function(a){a()}),S.length=0)}function B(a){O&&O.isOpen&&D&&(b[0].contains(a.target)||D[0].contains(a.target)||q())}function C(){var c=[],e=[],f=a.$eval(d[k+"Trigger"]);U(),angular.isObject(f)?(Object.keys(f).forEach(function(a){c.push(a),e.push(f[a])}),M={show:c,hide:e}):M=p(f),"none"!==M.show&&M.show.forEach(function(a,c){"outsideClick"===a?(b.on("click",j),h.on("click",B)):a===M.hide[c]?b.on(a,j):a&&(b.on(a,m),b.on(M.hide[c],q)),b.on("keypress",function(a){27===a.which&&q()})})}var D,E,F,G,H,I,J,K,L=angular.isDefined(n.appendToBody)?n.appendToBody:!1,M=p(void 0),N=angular.isDefined(d[k+"Enable"]),O=a.$new(!0),P=!1,Q=angular.isDefined(d[k+"IsOpen"])?l(d[k+"IsOpen"]):!1,R=n.useContentExp?l(d[e]):!1,S=[],T=function(){D&&D.html()&&(I||(I=g(function(){var a=i.positionElements(b,D,O.placement,L),c=angular.isDefined(D.offsetHeight)?D.offsetHeight:D.prop("offsetHeight"),d=L?i.offset(b):i.position(b);D.css({top:a.top+"px",left:a.left+"px"});var e=a.placement.split("-");D.hasClass(e[0])||(D.removeClass(K.split("-")[0]),D.addClass(e[0])),D.hasClass(n.placementClassPrefix+a.placement)||(D.removeClass(n.placementClassPrefix+K),D.addClass(n.placementClassPrefix+a.placement)),J=g(function(){var a=angular.isDefined(D.offsetHeight)?D.offsetHeight:D.prop("offsetHeight"),b=i.adjustTop(e,d,c,a);b&&D.css(b),J=null},0,!1),D.hasClass("uib-position-measure")?(i.positionArrow(D,a.placement),D.removeClass("uib-position-measure")):K!==a.placement&&i.positionArrow(D,a.placement),K=a.placement,I=null},0,!1)))};O.origScope=a,O.isOpen=!1,O.contentExp=function(){return O.content},d.$observe("disabled",function(a){a&&s(),a&&O.isOpen&&t()}),Q&&a.$watch(Q,function(a){O&&!a===O.isOpen&&j()});var U=function(){M.show.forEach(function(a){"outsideClick"===a?b.off("click",j):(b.off(a,m),b.off(a,j))}),M.hide.forEach(function(a){"outsideClick"===a?h.off("click",B):b.off(a,q)})};C();var V=a.$eval(d[k+"Animation"]);O.animation=angular.isDefined(V)?!!V:n.animation;var W,X=k+"AppendToBody";W=X in d&&void 0===d[X]?!0:a.$eval(d[X]),L=angular.isDefined(W)?W:L,a.$on("$destroy",function(){U(),w(),O=null})}}}}}]}).directive("uibTooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.uibTooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("uibTooltipClasses",["$uibPosition",function(a){return{restrict:"A",link:function(b,c,d){if(b.placement){var e=a.parsePlacement(b.placement);c.addClass(e[0])}b.popupClass&&c.addClass(b.popupClass),b.animation&&c.addClass(d.tooltipAnimationClass)}}}]).directive("uibTooltipPopup",function(){return{restrict:"A",scope:{content:"@"},templateUrl:"uib/template/tooltip/tooltip-popup.html"}}).directive("uibTooltip",["$uibTooltip",function(a){return a("uibTooltip","tooltip","mouseenter")}]).directive("uibTooltipTemplatePopup",function(){return{restrict:"A",scope:{contentExp:"&",originScope:"&"},templateUrl:"uib/template/tooltip/tooltip-template-popup.html"}}).directive("uibTooltipTemplate",["$uibTooltip",function(a){return a("uibTooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("uibTooltipHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&"},templateUrl:"uib/template/tooltip/tooltip-html-popup.html"}}).directive("uibTooltipHtml",["$uibTooltip",function(a){return a("uibTooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("uibPopoverTemplatePopup",function(){return{restrict:"A",scope:{uibTitle:"@",contentExp:"&",originScope:"&"},templateUrl:"uib/template/popover/popover-template.html"}}).directive("uibPopoverTemplate",["$uibTooltip",function(a){return a("uibPopoverTemplate","popover","click",{useContentExp:!0})}]).directive("uibPopoverHtmlPopup",function(){return{restrict:"A",scope:{contentExp:"&",uibTitle:"@"},templateUrl:"uib/template/popover/popover-html.html"}}).directive("uibPopoverHtml",["$uibTooltip",function(a){return a("uibPopoverHtml","popover","click",{useContentExp:!0})}]).directive("uibPopoverPopup",function(){return{restrict:"A",scope:{uibTitle:"@",content:"@"},templateUrl:"uib/template/popover/popover.html"}}).directive("uibPopover",["$uibTooltip",function(a){return a("uibPopover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("uibProgressConfig",{animate:!0,max:100}).controller("UibProgressController",["$scope","$attrs","uibProgressConfig",function(a,b,c){function d(){return angular.isDefined(a.maxParam)?a.maxParam:c.max}var e=this,f=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=d(),this.addBar=function(a,b,c){f||b.css({transition:"none"}),this.bars.push(a),a.max=d(),a.title=c&&angular.isDefined(c.title)?c.title:"progressbar",a.$watch("value",function(b){a.recalculatePercentage()}),a.recalculatePercentage=function(){var b=e.bars.reduce(function(a,b){return b.percent=+(100*b.value/b.max).toFixed(2),a+b.percent},0);b>100&&(a.percent-=b-100)},a.$on("$destroy",function(){b=null,e.removeBar(a)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1),this.bars.forEach(function(a){a.recalculatePercentage()})},a.$watch("maxParam",function(a){e.bars.forEach(function(a){a.max=d(),a.recalculatePercentage()})})}]).directive("uibProgress",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",require:"uibProgress",scope:{maxParam:"=?max"},templateUrl:"uib/template/progressbar/progress.html"}}).directive("uibBar",function(){return{replace:!0,transclude:!0,require:"^uibProgress",scope:{value:"=",type:"@"},templateUrl:"uib/template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b,c)}}}).directive("uibProgressbar",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",scope:{value:"=",maxParam:"=?max",type:"@"},templateUrl:"uib/template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]),{title:c.title})}}}),angular.module("ui.bootstrap.rating",[]).constant("uibRatingConfig",{max:5,stateOn:null,stateOff:null,enableReset:!0,titles:["one","two","three","four","five"]}).controller("UibRatingController",["$scope","$attrs","uibRatingConfig",function(a,b,c){var d={$setViewValue:angular.noop},e=this;this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff,this.enableReset=angular.isDefined(b.enableReset)?a.$parent.$eval(b.enableReset):c.enableReset;var f=angular.isDefined(b.titles)?a.$parent.$eval(b.titles):c.titles;this.titles=angular.isArray(f)&&f.length>0?f:c.titles;var g=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(g)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff,title:this.getTitle(b)},a[b]);return a},this.getTitle=function(a){return a>=this.titles.length?a+1:this.titles[a]},a.rate=function(b){if(!a.readonly&&b>=0&&b<=a.range.length){var c=e.enableReset&&d.$viewValue===b?0:b;d.$setViewValue(c),d.$render()}},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue,a.title=e.getTitle(a.value-1)}}]).directive("uibRating",function(){return{require:["uibRating","ngModel"],restrict:"A",scope:{readonly:"=?readOnly",onHover:"&",onLeave:"&"},controller:"UibRatingController",templateUrl:"uib/template/rating/rating.html",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(a){function b(a){for(var b=0;b<d.tabs.length;b++)if(d.tabs[b].index===a)return b}var c,d=this;d.tabs=[],d.select=function(a,f){if(!e){var g=b(c),h=d.tabs[g];if(h){if(h.tab.onDeselect({$event:f,$selectedIndex:a}),f&&f.isDefaultPrevented())return;h.tab.active=!1}var i=d.tabs[a];i?(i.tab.onSelect({$event:f}),i.tab.active=!0,d.active=i.index,c=i.index):!i&&angular.isDefined(c)&&(d.active=null,c=null)}},d.addTab=function(a){if(d.tabs.push({tab:a,index:a.index}),d.tabs.sort(function(a,b){return a.index>b.index?1:a.index<b.index?-1:0}),a.index===d.active||!angular.isDefined(d.active)&&1===d.tabs.length){var c=b(a.index);d.select(c)}},d.removeTab=function(a){for(var b,c=0;c<d.tabs.length;c++)if(d.tabs[c].tab===a){b=c;break}if(d.tabs[b].index===d.active){var e=b===d.tabs.length-1?b-1:b+1%d.tabs.length;d.select(e)}d.tabs.splice(b,1)},a.$watch("tabset.active",function(a){angular.isDefined(a)&&a!==c&&d.select(b(a))});var e;a.$on("$destroy",function(){e=!0})}]).directive("uibTabset",function(){return{transclude:!0,replace:!0,scope:{},bindToController:{active:"=?",type:"@"},controller:"UibTabsetController",controllerAs:"tabset",templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tabset.html"},link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("uibTab",["$parse",function(a){return{require:"^uibTabset",replace:!0,templateUrl:function(a,b){return b.templateUrl||"uib/template/tabs/tab.html"},transclude:!0,scope:{heading:"@",index:"=?",classes:"@?",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},controllerAs:"tab",link:function(b,c,d,e,f){b.disabled=!1,d.disable&&b.$parent.$watch(a(d.disable),function(a){b.disabled=!!a}),angular.isUndefined(d.index)&&(e.tabs&&e.tabs.length?b.index=Math.max.apply(null,e.tabs.map(function(a){return a.index}))+1:b.index=0),angular.isUndefined(d.classes)&&(b.classes=""),b.select=function(a){if(!b.disabled){for(var c,d=0;d<e.tabs.length;d++)if(e.tabs[d].tab===b){c=d;break}e.select(c,a)}},e.addTab(b),b.$on("$destroy",function(){e.removeTab(b)}),b.$transcludeFn=f}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:"^uibTab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}).directive("uibTabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("uib-tab-heading")||a.hasAttribute("data-uib-tab-heading")||a.hasAttribute("x-uib-tab-heading")||"uib-tab-heading"===a.tagName.toLowerCase()||"data-uib-tab-heading"===a.tagName.toLowerCase()||"x-uib-tab-heading"===a.tagName.toLowerCase()||"uib:tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^uibTabset",link:function(b,c,d){var e=b.$eval(d.uibTabContentTransclude).tab;e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("uibTimepickerConfig",{hourStep:1,minuteStep:1,secondStep:1,showMeridian:!0,showSeconds:!1,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0,showSpinners:!0,templateUrl:"uib/template/timepicker/timepicker.html"}).controller("UibTimepickerController",["$scope","$element","$attrs","$parse","$log","$locale","uibTimepickerConfig",function(a,b,c,d,e,f,g){function h(){var b=+a.hours,c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c&&""!==a.hours?(a.showMeridian&&(12===b&&(b=0),a.meridian===y[1]&&(b+=12)),b):void 0}function i(){var b=+a.minutes,c=b>=0&&60>b;return c&&""!==a.minutes?b:void 0}function j(){var b=+a.seconds;return b>=0&&60>b?b:void 0}function k(a,b){return null===a?"":angular.isDefined(a)&&a.toString().length<2&&!b?"0"+a:a.toString()}function l(a){m(),x.$setViewValue(new Date(v)),n(a)}function m(){s&&s.$setValidity("hours",!0),t&&t.$setValidity("minutes",!0),u&&u.$setValidity("seconds",!0),x.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1,a.invalidSeconds=!1}function n(b){if(x.$modelValue){var c=v.getHours(),d=v.getMinutes(),e=v.getSeconds();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:k(c,!z),"m"!==b&&(a.minutes=k(d)),a.meridian=v.getHours()<12?y[0]:y[1],"s"!==b&&(a.seconds=k(e)),a.meridian=v.getHours()<12?y[0]:y[1]}else a.hours=null,a.minutes=null,a.seconds=null,a.meridian=y[0]}function o(a){v=q(v,a),l()}function p(a,b){return q(a,60*b)}function q(a,b){var c=new Date(a.getTime()+1e3*b),d=new Date(a);return d.setHours(c.getHours(),c.getMinutes(),c.getSeconds()),d}function r(){return(null===a.hours||""===a.hours)&&(null===a.minutes||""===a.minutes)&&(!a.showSeconds||a.showSeconds&&(null===a.seconds||""===a.seconds))}var s,t,u,v=new Date,w=[],x={$setViewValue:angular.noop},y=angular.isDefined(c.meridians)?a.$parent.$eval(c.meridians):g.meridians||f.DATETIME_FORMATS.AMPMS,z=angular.isDefined(c.padHours)?a.$parent.$eval(c.padHours):!0;a.tabindex=angular.isDefined(c.tabindex)?c.tabindex:0,b.removeAttr("tabindex"),this.init=function(b,d){x=b,x.$render=this.render,x.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),f=d.eq(1),h=d.eq(2);s=e.controller("ngModel"),t=f.controller("ngModel"),u=h.controller("ngModel");var i=angular.isDefined(c.mousewheel)?a.$parent.$eval(c.mousewheel):g.mousewheel;i&&this.setupMousewheelEvents(e,f,h);var j=angular.isDefined(c.arrowkeys)?a.$parent.$eval(c.arrowkeys):g.arrowkeys;j&&this.setupArrowkeyEvents(e,f,h),a.readonlyInput=angular.isDefined(c.readonlyInput)?a.$parent.$eval(c.readonlyInput):g.readonlyInput,this.setupInputEvents(e,f,h)};var A=g.hourStep;c.hourStep&&w.push(a.$parent.$watch(d(c.hourStep),function(a){A=+a}));var B=g.minuteStep;c.minuteStep&&w.push(a.$parent.$watch(d(c.minuteStep),function(a){B=+a}));var C;w.push(a.$parent.$watch(d(c.min),function(a){var b=new Date(a);C=isNaN(b)?void 0:b}));var D;w.push(a.$parent.$watch(d(c.max),function(a){var b=new Date(a);D=isNaN(b)?void 0:b}));var E=!1;c.ngDisabled&&w.push(a.$parent.$watch(d(c.ngDisabled),function(a){E=a})),a.noIncrementHours=function(){var a=p(v,60*A);return E||a>D||v>a&&C>a},a.noDecrementHours=function(){var a=p(v,60*-A);return E||C>a||a>v&&a>D},a.noIncrementMinutes=function(){var a=p(v,B);return E||a>D||v>a&&C>a},a.noDecrementMinutes=function(){var a=p(v,-B);return E||C>a||a>v&&a>D},a.noIncrementSeconds=function(){var a=q(v,F);return E||a>D||v>a&&C>a},a.noDecrementSeconds=function(){var a=q(v,-F);return E||C>a||a>v&&a>D},a.noToggleMeridian=function(){return v.getHours()<12?E||p(v,720)>D:E||p(v,-720)<C};var F=g.secondStep;c.secondStep&&w.push(a.$parent.$watch(d(c.secondStep),function(a){F=+a})),a.showSeconds=g.showSeconds,c.showSeconds&&w.push(a.$parent.$watch(d(c.showSeconds),function(b){a.showSeconds=!!b})),a.showMeridian=g.showMeridian,c.showMeridian&&w.push(a.$parent.$watch(d(c.showMeridian),function(b){if(a.showMeridian=!!b,x.$error.time){var c=h(),d=i();angular.isDefined(c)&&angular.isDefined(d)&&(v.setHours(c),l())}else n()})),this.setupMousewheelEvents=function(b,c,d){var e=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()}),d.bind("mousewheel wheel",function(b){E||a.$apply(e(b)?a.incrementSeconds():a.decrementSeconds()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c,d){b.bind("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply()))}),c.bind("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply()))}),d.bind("keydown",function(b){E||(38===b.which?(b.preventDefault(),a.incrementSeconds(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementSeconds(),a.$apply()))})},this.setupInputEvents=function(b,c,d){if(a.readonlyInput)return a.updateHours=angular.noop,a.updateMinutes=angular.noop,void(a.updateSeconds=angular.noop);var e=function(b,c,d){x.$setViewValue(null),x.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b,s&&s.$setValidity("hours",!1)),angular.isDefined(c)&&(a.invalidMinutes=c,t&&t.$setValidity("minutes",!1)),angular.isDefined(d)&&(a.invalidSeconds=d,u&&u.$setValidity("seconds",!1))};a.updateHours=function(){var a=h(),b=i();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(a),v.setMinutes(b),C>v||v>D?e(!0):l("h")):e(!0)},b.bind("blur",function(b){x.$setTouched(),r()?m():null===a.hours||""===a.hours?e(!0):!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=k(a.hours,!z)})}),a.updateMinutes=function(){var a=i(),b=h();x.$setDirty(),angular.isDefined(a)&&angular.isDefined(b)?(v.setHours(b),v.setMinutes(a),C>v||v>D?e(void 0,!0):l("m")):e(void 0,!0)},c.bind("blur",function(b){x.$setTouched(),r()?m():null===a.minutes?e(void 0,!0):!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=k(a.minutes)})}),a.updateSeconds=function(){var a=j();x.$setDirty(),angular.isDefined(a)?(v.setSeconds(a),l("s")):e(void 0,void 0,!0)},d.bind("blur",function(b){r()?m():!a.invalidSeconds&&a.seconds<10&&a.$apply(function(){a.seconds=k(a.seconds)})})},this.render=function(){var b=x.$viewValue;isNaN(b)?(x.$setValidity("time",!1),e.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(b&&(v=b),C>v||v>D?(x.$setValidity("time",!1),a.invalidHours=!0,a.invalidMinutes=!0):m(),n())},a.showSpinners=angular.isDefined(c.showSpinners)?a.$parent.$eval(c.showSpinners):g.showSpinners,a.incrementHours=function(){a.noIncrementHours()||o(60*A*60)},a.decrementHours=function(){a.noDecrementHours()||o(60*-A*60)},a.incrementMinutes=function(){a.noIncrementMinutes()||o(60*B)},a.decrementMinutes=function(){a.noDecrementMinutes()||o(60*-B)},a.incrementSeconds=function(){a.noIncrementSeconds()||o(F)},a.decrementSeconds=function(){a.noDecrementSeconds()||o(-F)},a.toggleMeridian=function(){var b=i(),c=h();a.noToggleMeridian()||(angular.isDefined(b)&&angular.isDefined(c)?o(720*(v.getHours()<12?60:-60)):a.meridian=a.meridian===y[0]?y[1]:y[0])},a.blur=function(){x.$setTouched()},a.$on("$destroy",function(){for(;w.length;)w.shift()()})}]).directive("uibTimepicker",["uibTimepickerConfig",function(a){return{require:["uibTimepicker","?^ngModel"],restrict:"A",controller:"UibTimepickerController",controllerAs:"timepicker",scope:{},templateUrl:function(b,c){return c.templateUrl||a.templateUrl},link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.debounce","ui.bootstrap.position"]).factory("uibTypeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).controller("UibTypeaheadController",["$scope","$element","$attrs","$compile","$parse","$q","$timeout","$document","$window","$rootScope","$$debounce","$uibPosition","uibTypeaheadParser",function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(){O.moveInProgress||(O.moveInProgress=!0,O.$digest()),Z()}function o(){O.position=E?l.offset(b):l.position(b),O.position.top+=b.prop("offsetHeight")}var p,q,r=[9,13,27,38,40],s=200,t=a.$eval(c.typeaheadMinLength);t||0===t||(t=1),a.$watch(c.typeaheadMinLength,function(a){t=a||0===a?a:1});var u=a.$eval(c.typeaheadWaitMs)||0,v=a.$eval(c.typeaheadEditable)!==!1;a.$watch(c.typeaheadEditable,function(a){v=a!==!1});var w,x,y=e(c.typeaheadLoading).assign||angular.noop,z=c.typeaheadShouldSelect?e(c.typeaheadShouldSelect):function(a,b){var c=b.$event;return 13===c.which||9===c.which},A=e(c.typeaheadOnSelect),B=angular.isDefined(c.typeaheadSelectOnBlur)?a.$eval(c.typeaheadSelectOnBlur):!1,C=e(c.typeaheadNoResults).assign||angular.noop,D=c.typeaheadInputFormatter?e(c.typeaheadInputFormatter):void 0,E=c.typeaheadAppendToBody?a.$eval(c.typeaheadAppendToBody):!1,F=c.typeaheadAppendTo?a.$eval(c.typeaheadAppendTo):null,G=a.$eval(c.typeaheadFocusFirst)!==!1,H=c.typeaheadSelectOnExact?a.$eval(c.typeaheadSelectOnExact):!1,I=e(c.typeaheadIsOpen).assign||angular.noop,J=a.$eval(c.typeaheadShowHint)||!1,K=e(c.ngModel),L=e(c.ngModel+"($$$p)"),M=function(b,c){return angular.isFunction(K(a))&&q&&q.$options&&q.$options.getterSetter?L(b,{$$$p:c}):K.assign(b,c)},N=m.parse(c.uibTypeahead),O=a.$new(),P=a.$on("$destroy",function(){O.$destroy()});O.$on("$destroy",P);var Q="typeahead-"+O.$id+"-"+Math.floor(1e4*Math.random());b.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":Q});var R,S;J&&(R=angular.element("<div></div>"),R.css("position","relative"),b.after(R),S=b.clone(),S.attr("placeholder",""),S.attr("tabindex","-1"),S.val(""),S.css({position:"absolute",top:"0px",left:"0px","border-color":"transparent","box-shadow":"none",opacity:1,background:"none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255)",color:"#999"}),b.css({position:"relative","vertical-align":"top","background-color":"transparent"}),S.attr("id")&&S.removeAttr("id"),R.append(S),S.after(b));var T=angular.element("<div uib-typeahead-popup></div>");T.attr({id:Q,matches:"matches",active:"activeIdx",select:"select(activeIdx, evt)","move-in-progress":"moveInProgress",query:"query",position:"position","assign-is-open":"assignIsOpen(isOpen)",debounce:"debounceUpdate"}),angular.isDefined(c.typeaheadTemplateUrl)&&T.attr("template-url",c.typeaheadTemplateUrl),angular.isDefined(c.typeaheadPopupTemplateUrl)&&T.attr("popup-template-url",c.typeaheadPopupTemplateUrl);var U=function(){J&&S.val("")},V=function(){O.matches=[],O.activeIdx=-1,b.attr("aria-expanded",!1),U()},W=function(a){return Q+"-option-"+a};O.$watch("activeIdx",function(a){0>a?b.removeAttr("aria-activedescendant"):b.attr("aria-activedescendant",W(a))});var X=function(a,b){return O.matches.length>b&&a?a.toUpperCase()===O.matches[b].label.toUpperCase():!1},Y=function(c,d){var e={$viewValue:c};y(a,!0),C(a,!1),f.when(N.source(a,e)).then(function(f){var g=c===p.$viewValue;if(g&&w)if(f&&f.length>0){O.activeIdx=G?0:-1,C(a,!1),O.matches.length=0;for(var h=0;h<f.length;h++)e[N.itemName]=f[h],O.matches.push({id:W(h),label:N.viewMapper(O,e),model:f[h]});if(O.query=c,o(),b.attr("aria-expanded",!0),H&&1===O.matches.length&&X(c,0)&&(angular.isNumber(O.debounceUpdate)||angular.isObject(O.debounceUpdate)?k(function(){O.select(0,d)},angular.isNumber(O.debounceUpdate)?O.debounceUpdate:O.debounceUpdate["default"]):O.select(0,d)),J){var i=O.matches[0].label;angular.isString(c)&&c.length>0&&i.slice(0,c.length).toUpperCase()===c.toUpperCase()?S.val(c+i.slice(c.length)):S.val("")}}else V(),C(a,!0);g&&y(a,!1)},function(){V(),y(a,!1),C(a,!0)})};E&&(angular.element(i).on("resize",n),h.find("body").on("scroll",n));var Z=k(function(){O.matches.length&&o(),O.moveInProgress=!1},s);O.moveInProgress=!1,O.query=void 0;var $,_=function(a){$=g(function(){Y(a)},u)},aa=function(){$&&g.cancel($)};V(),O.assignIsOpen=function(b){I(a,b)},O.select=function(d,e){var f,h,i={};x=!0,i[N.itemName]=h=O.matches[d].model,f=N.modelMapper(a,i),M(a,f),p.$setValidity("editable",!0),p.$setValidity("parse",!0),A(a,{$item:h,$model:f,$label:N.viewMapper(a,i),$event:e}),V(),O.$eval(c.typeaheadFocusOnSelect)!==!1&&g(function(){b[0].focus()},0,!1)},b.on("keydown",function(b){if(0!==O.matches.length&&-1!==r.indexOf(b.which)){var c=z(a,{$event:b});if(-1===O.activeIdx&&c||9===b.which&&b.shiftKey)return V(),void O.$digest();b.preventDefault();var d;switch(b.which){case 27:b.stopPropagation(),V(),a.$digest();break;case 38:O.activeIdx=(O.activeIdx>0?O.activeIdx:O.matches.length)-1,O.$digest(),d=T[0].querySelectorAll(".uib-typeahead-match")[O.activeIdx],d.parentNode.scrollTop=d.offsetTop;break;case 40:O.activeIdx=(O.activeIdx+1)%O.matches.length,O.$digest(),d=T[0].querySelectorAll(".uib-typeahead-match")[O.activeIdx],d.parentNode.scrollTop=d.offsetTop;break;default:c&&O.$apply(function(){angular.isNumber(O.debounceUpdate)||angular.isObject(O.debounceUpdate)?k(function(){O.select(O.activeIdx,b)},angular.isNumber(O.debounceUpdate)?O.debounceUpdate:O.debounceUpdate["default"]):O.select(O.activeIdx,b)})}}}),b.bind("focus",function(a){w=!0,0!==t||p.$viewValue||g(function(){Y(p.$viewValue,a)},0)}),b.bind("blur",function(a){B&&O.matches.length&&-1!==O.activeIdx&&!x&&(x=!0,O.$apply(function(){angular.isObject(O.debounceUpdate)&&angular.isNumber(O.debounceUpdate.blur)?k(function(){O.select(O.activeIdx,a)},O.debounceUpdate.blur):O.select(O.activeIdx,a)})),!v&&p.$error.editable&&(p.$setViewValue(),O.$apply(function(){p.$setValidity("editable",!0),p.$setValidity("parse",!0)}),b.val("")),w=!1,x=!1});var ba=function(c){b[0]!==c.target&&3!==c.which&&0!==O.matches.length&&(V(),j.$$phase||a.$digest())};h.on("click",ba),a.$on("$destroy",function(){h.off("click",ba),(E||F)&&ca.remove(),E&&(angular.element(i).off("resize",n),h.find("body").off("scroll",n)),T.remove(),J&&R.remove()});var ca=d(T)(O);E?h.find("body").append(ca):F?angular.element(F).eq(0).append(ca):b.after(ca),this.init=function(b,c){p=b,q=c,O.debounceUpdate=p.$options&&e(p.$options.debounce)(a),p.$parsers.unshift(function(b){return w=!0,0===t||b&&b.length>=t?u>0?(aa(),_(b)):Y(b):(y(a,!1),aa(),V()),v?b:b?void p.$setValidity("editable",!1):(p.$setValidity("editable",!0),null)}),p.$formatters.push(function(b){var c,d,e={};return v||p.$setValidity("editable",!0),D?(e.$model=b,D(a,e)):(e[N.itemName]=b,c=N.viewMapper(a,e),e[N.itemName]=void 0,d=N.viewMapper(a,e),c!==d?c:b)})}}]).directive("uibTypeahead",function(){return{controller:"UibTypeaheadController",require:["ngModel","^?ngModelOptions","uibTypeahead"],
link:function(a,b,c,d){d[2].init(d[0],d[1])}}}).directive("uibTypeaheadPopup",["$$debounce",function(a){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&",assignIsOpen:"&",debounce:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"uib/template/typeahead/typeahead-popup.html"},link:function(b,c,d){b.templateUrl=d.templateUrl,b.isOpen=function(){var a=b.matches.length>0;return b.assignIsOpen({isOpen:a}),a},b.isActive=function(a){return b.active===a},b.selectActive=function(a){b.active=a},b.selectMatch=function(c,d){var e=b.debounce();angular.isNumber(e)||angular.isObject(e)?a(function(){b.select({activeIdx:c,evt:d})},angular.isNumber(e)?e:e["default"]):b.select({activeIdx:c,evt:d})}}}}]).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"uib/template/typeahead/typeahead-match.html";a(g).then(function(a){var c=angular.element(a.trim());e.replaceWith(c),b(c)(d)})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(a,b,c){function d(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function e(a){return/<.*>/g.test(a)}var f;return f=b.has("$sanitize"),function(b,g){return!f&&e(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=g?(""+b).replace(new RegExp(d(g),"gi"),"<strong>$&</strong>"):b,f||(b=a.trustAsHtml(b)),b}}]),angular.module("uib/template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("uib/template/accordion/accordion-group.html",'<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">\n  <h4 class="panel-title">\n    <a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading" ng-disabled="isDisabled" uib-tabindex-toggle><span uib-accordion-header ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n  </h4>\n</div>\n<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">\n  <div class="panel-body" ng-transclude></div>\n</div>\n')}]),angular.module("uib/template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("uib/template/accordion/accordion.html",'<div role="tablist" class="panel-group" ng-transclude></div>')}]),angular.module("uib/template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("uib/template/alert/alert.html",'<button ng-show="closeable" type="button" class="close" ng-click="close({$event: $event})">\n  <span aria-hidden="true">&times;</span>\n  <span class="sr-only">Close</span>\n</button>\n<div ng-transclude></div>\n')}]),angular.module("uib/template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("uib/template/carousel/carousel.html",'<div class="carousel-inner" ng-transclude></div>\n<a role="button" href class="left carousel-control" ng-click="prev()" ng-class="{ disabled: isPrevDisabled() }" ng-show="slides.length > 1">\n  <span aria-hidden="true" class="glyphicon glyphicon-chevron-left"></span>\n  <span class="sr-only">previous</span>\n</a>\n<a role="button" href class="right carousel-control" ng-click="next()" ng-class="{ disabled: isNextDisabled() }" ng-show="slides.length > 1">\n  <span aria-hidden="true" class="glyphicon glyphicon-chevron-right"></span>\n  <span class="sr-only">next</span>\n</a>\n<ol class="carousel-indicators" ng-show="slides.length > 1">\n  <li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{ active: isActive(slide) }" ng-click="select(slide)">\n    <span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>\n  </li>\n</ol>\n')}]),angular.module("uib/template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("uib/template/carousel/slide.html",'<div class="text-center" ng-transclude></div>\n')}]),angular.module("uib/template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/datepicker.html",'<div ng-switch="datepickerMode">\n  <div uib-daypicker ng-switch-when="day" tabindex="0" class="uib-daypicker"></div>\n  <div uib-monthpicker ng-switch-when="month" tabindex="0" class="uib-monthpicker"></div>\n  <div uib-yearpicker ng-switch-when="year" tabindex="0" class="uib-yearpicker"></div>\n</div>\n')}]),angular.module("uib/template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/day.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>\n      <th colspan="{{::5 + showWeeks}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>\n    </tr>\n    <tr>\n      <th ng-if="showWeeks" class="text-center"></th>\n      <th ng-repeat="label in ::labels track by $index" class="text-center"><small aria-label="{{::label.full}}">{{::label.abbr}}</small></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr class="uib-weeks" ng-repeat="row in rows track by $index" role="row">\n      <td ng-if="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n      <td ng-repeat="dt in row" class="uib-day text-center" role="gridcell"\n        id="{{::dt.uid}}"\n        ng-class="::dt.customClass">\n        <button type="button" class="btn btn-default btn-sm"\n          uib-is-class="\n            \'btn-info\' for selectedDt,\n            \'active\' for activeDt\n            on dt"\n          ng-click="select(dt.date)"\n          ng-disabled="::dt.disabled"\n          tabindex="-1"><span ng-class="::{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{::dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("uib/template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/month.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>\n      <th colspan="{{::yearHeaderColspan}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></i></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr class="uib-months" ng-repeat="row in rows track by $index" role="row">\n      <td ng-repeat="dt in row" class="uib-month text-center" role="gridcell"\n        id="{{::dt.uid}}"\n        ng-class="::dt.customClass">\n        <button type="button" class="btn btn-default"\n          uib-is-class="\n            \'btn-info\' for selectedDt,\n            \'active\' for activeDt\n            on dt"\n          ng-click="select(dt.date)"\n          ng-disabled="::dt.disabled"\n          tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("uib/template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepicker/year.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>\n      <th colspan="{{::columns - 2}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr class="uib-years" ng-repeat="row in rows track by $index" role="row">\n      <td ng-repeat="dt in row" class="uib-year text-center" role="gridcell"\n        id="{{::dt.uid}}"\n        ng-class="::dt.customClass">\n        <button type="button" class="btn btn-default"\n          uib-is-class="\n            \'btn-info\' for selectedDt,\n            \'active\' for activeDt\n            on dt"\n          ng-click="select(dt.date)"\n          ng-disabled="::dt.disabled"\n          tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("uib/template/datepickerPopup/popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/datepickerPopup/popup.html",'<ul role="presentation" class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">\n  <li ng-transclude></li>\n  <li ng-if="showButtonBar" class="uib-button-bar">\n    <span class="btn-group pull-left">\n      <button type="button" class="btn btn-sm btn-info uib-datepicker-current" ng-click="select(\'today\', $event)" ng-disabled="isDisabled(\'today\')">{{ getText(\'current\') }}</button>\n      <button type="button" class="btn btn-sm btn-danger uib-clear" ng-click="select(null, $event)">{{ getText(\'clear\') }}</button>\n    </span>\n    <button type="button" class="btn btn-sm btn-success pull-right uib-close" ng-click="close($event)">{{ getText(\'close\') }}</button>\n  </li>\n</ul>\n')}]),angular.module("uib/template/modal/window.html",[]).run(["$templateCache",function(a){a.put("uib/template/modal/window.html","<div class=\"modal-dialog {{size ? 'modal-' + size : ''}}\"><div class=\"modal-content\" uib-modal-transclude></div></div>\n")}]),angular.module("uib/template/pager/pager.html",[]).run(["$templateCache",function(a){a.put("uib/template/pager/pager.html",'<li ng-class="{disabled: noPrevious()||ngDisabled, previous: align}"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText(\'previous\')}}</a></li>\n<li ng-class="{disabled: noNext()||ngDisabled, next: align}"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText(\'next\')}}</a></li>\n')}]),angular.module("uib/template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("uib/template/pagination/pagination.html",'<li ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText(\'first\')}}</a></li>\n<li ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText(\'previous\')}}</a></li>\n<li ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page"><a href ng-click="selectPage(page.number, $event)" ng-disabled="ngDisabled&&!page.active" uib-tabindex-toggle>{{page.text}}</a></li>\n<li ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText(\'next\')}}</a></li>\n<li ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText(\'last\')}}</a></li>\n')}]),angular.module("uib/template/tooltip/tooltip-html-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/tooltip/tooltip-html-popup.html",'<div class="tooltip-arrow"></div>\n<div class="tooltip-inner" ng-bind-html="contentExp()"></div>\n')}]),angular.module("uib/template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/tooltip/tooltip-popup.html",'<div class="tooltip-arrow"></div>\n<div class="tooltip-inner" ng-bind="content"></div>\n')}]),angular.module("uib/template/tooltip/tooltip-template-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/tooltip/tooltip-template-popup.html",'<div class="tooltip-arrow"></div>\n<div class="tooltip-inner"\n  uib-tooltip-template-transclude="contentExp()"\n  tooltip-template-transclude-scope="originScope()"></div>\n')}]),angular.module("uib/template/popover/popover-html.html",[]).run(["$templateCache",function(a){a.put("uib/template/popover/popover-html.html",'<div class="arrow"></div>\n\n<div class="popover-inner">\n    <h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>\n    <div class="popover-content" ng-bind-html="contentExp()"></div>\n</div>\n')}]),angular.module("uib/template/popover/popover-template.html",[]).run(["$templateCache",function(a){a.put("uib/template/popover/popover-template.html",'<div class="arrow"></div>\n\n<div class="popover-inner">\n    <h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>\n    <div class="popover-content"\n      uib-tooltip-template-transclude="contentExp()"\n      tooltip-template-transclude-scope="originScope()"></div>\n</div>\n')}]),angular.module("uib/template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("uib/template/popover/popover.html",'<div class="arrow"></div>\n\n<div class="popover-inner">\n    <h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>\n    <div class="popover-content" ng-bind="content"></div>\n</div>\n')}]),angular.module("uib/template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("uib/template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" ng-transclude></div>\n')}]),angular.module("uib/template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("uib/template/progressbar/progress.html",'<div class="progress" ng-transclude aria-labelledby="{{::title}}"></div>')}]),angular.module("uib/template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("uib/template/progressbar/progressbar.html",'<div class="progress">\n  <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" ng-transclude></div>\n</div>\n')}]),angular.module("uib/template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("uib/template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}" aria-valuetext="{{title}}">\n    <span ng-repeat-start="r in range track by $index" class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n    <i ng-repeat-end ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')" ng-attr-title="{{r.title}}"></i>\n</span>\n')}]),angular.module("uib/template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("uib/template/tabs/tab.html",'<li ng-class="[{active: active, disabled: disabled}, classes]" class="uib-tab nav-item">\n  <a href ng-click="select($event)" class="nav-link" uib-tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("uib/template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("uib/template/tabs/tabset.html",'<div>\n  <ul class="nav nav-{{tabset.type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n  <div class="tab-content">\n    <div class="tab-pane"\n         ng-repeat="tab in tabset.tabs"\n         ng-class="{active: tabset.active === tab.index}"\n         uib-tab-content-transclude="tab">\n    </div>\n  </div>\n</div>\n')}]),angular.module("uib/template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("uib/template/timepicker/timepicker.html",'<table class="uib-timepicker">\n  <tbody>\n    <tr class="text-center" ng-show="::showSpinners">\n      <td class="uib-increment hours"><a ng-click="incrementHours()" ng-class="{disabled: noIncrementHours()}" class="btn btn-link" ng-disabled="noIncrementHours()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n      <td>&nbsp;</td>\n      <td class="uib-increment minutes"><a ng-click="incrementMinutes()" ng-class="{disabled: noIncrementMinutes()}" class="btn btn-link" ng-disabled="noIncrementMinutes()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n      <td ng-show="showSeconds">&nbsp;</td>\n      <td ng-show="showSeconds" class="uib-increment seconds"><a ng-click="incrementSeconds()" ng-class="{disabled: noIncrementSeconds()}" class="btn btn-link" ng-disabled="noIncrementSeconds()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n      <td ng-show="showMeridian"></td>\n    </tr>\n    <tr>\n      <td class="form-group uib-time hours" ng-class="{\'has-error\': invalidHours}">\n        <input type="text" placeholder="HH" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="noIncrementHours()" ng-blur="blur()">\n      </td>\n      <td class="uib-separator">:</td>\n      <td class="form-group uib-time minutes" ng-class="{\'has-error\': invalidMinutes}">\n        <input type="text" placeholder="MM" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="noIncrementMinutes()" ng-blur="blur()">\n      </td>\n      <td ng-show="showSeconds" class="uib-separator">:</td>\n      <td class="form-group uib-time seconds" ng-class="{\'has-error\': invalidSeconds}" ng-show="showSeconds">\n        <input type="text" placeholder="SS" ng-model="seconds" ng-change="updateSeconds()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="noIncrementSeconds()" ng-blur="blur()">\n      </td>\n      <td ng-show="showMeridian" class="uib-time am-pm"><button type="button" ng-class="{disabled: noToggleMeridian()}" class="btn btn-default text-center" ng-click="toggleMeridian()" ng-disabled="noToggleMeridian()" tabindex="{{::tabindex}}">{{meridian}}</button></td>\n    </tr>\n    <tr class="text-center" ng-show="::showSpinners">\n      <td class="uib-decrement hours"><a ng-click="decrementHours()" ng-class="{disabled: noDecrementHours()}" class="btn btn-link" ng-disabled="noDecrementHours()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n      <td>&nbsp;</td>\n      <td class="uib-decrement minutes"><a ng-click="decrementMinutes()" ng-class="{disabled: noDecrementMinutes()}" class="btn btn-link" ng-disabled="noDecrementMinutes()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n      <td ng-show="showSeconds">&nbsp;</td>\n      <td ng-show="showSeconds" class="uib-decrement seconds"><a ng-click="decrementSeconds()" ng-class="{disabled: noDecrementSeconds()}" class="btn btn-link" ng-disabled="noDecrementSeconds()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n      <td ng-show="showMeridian"></td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("uib/template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-match.html",'<a href\n   tabindex="-1"\n   ng-bind-html="match.label | uibTypeaheadHighlight:query"\n   ng-attr-title="{{match.label}}"></a>\n')}]),angular.module("uib/template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("uib/template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-show="isOpen() && !moveInProgress" ng-style="{top: position().top+\'px\', left: position().left+\'px\'}" role="listbox" aria-hidden="{{!isOpen()}}">\n    <li class="uib-typeahead-match" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="{{::match.id}}">\n        <div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n    </li>\n</ul>\n')}]),angular.module("ui.bootstrap.carousel").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibCarouselCss&&angular.element(document).find("head").prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>'),angular.$$uibCarouselCss=!0}),angular.module("ui.bootstrap.datepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker .uib-title{width:100%;}.uib-day button,.uib-month button,.uib-year button{min-width:100%;}.uib-left,.uib-right{width:100%}</style>'),angular.$$uibDatepickerCss=!0}),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'),angular.$$uibPositionCss=!0}),angular.module("ui.bootstrap.datepickerPopup").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibDatepickerpopupCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-datepicker-popup.dropdown-menu{display:block;float:none;margin:0;}.uib-button-bar{padding:10px 9px 2px;}</style>'),angular.$$uibDatepickerpopupCss=!0}),angular.module("ui.bootstrap.tooltip").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTooltipCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,[uib-popover-popup].popover.top-left > .arrow,[uib-popover-popup].popover.top-right > .arrow,[uib-popover-popup].popover.bottom-left > .arrow,[uib-popover-popup].popover.bottom-right > .arrow,[uib-popover-popup].popover.left-top > .arrow,[uib-popover-popup].popover.left-bottom > .arrow,[uib-popover-popup].popover.right-top > .arrow,[uib-popover-popup].popover.right-bottom > .arrow,[uib-popover-html-popup].popover.top-left > .arrow,[uib-popover-html-popup].popover.top-right > .arrow,[uib-popover-html-popup].popover.bottom-left > .arrow,[uib-popover-html-popup].popover.bottom-right > .arrow,[uib-popover-html-popup].popover.left-top > .arrow,[uib-popover-html-popup].popover.left-bottom > .arrow,[uib-popover-html-popup].popover.right-top > .arrow,[uib-popover-html-popup].popover.right-bottom > .arrow,[uib-popover-template-popup].popover.top-left > .arrow,[uib-popover-template-popup].popover.top-right > .arrow,[uib-popover-template-popup].popover.bottom-left > .arrow,[uib-popover-template-popup].popover.bottom-right > .arrow,[uib-popover-template-popup].popover.left-top > .arrow,[uib-popover-template-popup].popover.left-bottom > .arrow,[uib-popover-template-popup].popover.right-top > .arrow,[uib-popover-template-popup].popover.right-bottom > .arrow{top:auto;bottom:auto;left:auto;right:auto;margin:0;}[uib-popover-popup].popover,[uib-popover-html-popup].popover,[uib-popover-template-popup].popover{display:block !important;}</style>'),angular.$$uibTooltipCss=!0}),angular.module("ui.bootstrap.timepicker").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTimepickerCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-time input{width:50px;}</style>'),angular.$$uibTimepickerCss=!0}),angular.module("ui.bootstrap.typeahead").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibTypeaheadCss&&angular.element(document).find("head").prepend('<style type="text/css">[uib-typeahead-popup].dropdown-menu{display:block;}</style>'),angular.$$uibTypeaheadCss=!0});
define("uibootstraptpls", ["uibootstrap"], function(){});

vendors/angular-sanitize/angular-sanitize.min.js
/*
 AngularJS v1.5.7
 (c) 2010-2016 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(q,e){'use strict';function A(a){var c=[];v(c,e.noop).chars(a);return c.join("")}function h(a,c){var b={},d=a.split(","),l;for(l=0;l<d.length;l++)b[c?e.lowercase(d[l]):d[l]]=!0;return b}function B(a,c){null===a||void 0===a?a="":"string"!==typeof a&&(a=""+a);g.innerHTML=a;var b=5;do{if(0===b)throw w("uinput");b--;q.document.documentMode&&r(g);a=g.innerHTML;g.innerHTML=a}while(a!==g.innerHTML);for(b=g.firstChild;b;){switch(b.nodeType){case 1:c.start(b.nodeName.toLowerCase(),C(b.attributes));
break;case 3:c.chars(b.textContent)}var d;if(!(d=b.firstChild)&&(1==b.nodeType&&c.end(b.nodeName.toLowerCase()),d=b.nextSibling,!d))for(;null==d;){b=b.parentNode;if(b===g)break;d=b.nextSibling;1==b.nodeType&&c.end(b.nodeName.toLowerCase())}b=d}for(;b=g.firstChild;)g.removeChild(b)}function C(a){for(var c={},b=0,d=a.length;b<d;b++){var l=a[b];c[l.name]=l.value}return c}function x(a){return a.replace(/&/g,"&amp;").replace(D,function(a){var b=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(b-55296)+
(a-56320)+65536)+";"}).replace(E,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function v(a,c){var b=!1,d=e.bind(a,a.push);return{start:function(a,f){a=e.lowercase(a);!b&&F[a]&&(b=a);b||!0!==n[a]||(d("<"),d(a),e.forEach(f,function(b,f){var g=e.lowercase(f),h="img"===a&&"src"===g||"background"===g;!0!==G[g]||!0===y[g]&&!c(b,h)||(d(" "),d(f),d('="'),d(x(b)),d('"'))}),d(">"))},end:function(a){a=e.lowercase(a);b||!0!==n[a]||!0===z[a]||(d("</"),d(a),d(">"));a==
b&&(b=!1)},chars:function(a){b||d(x(a))}}}function r(a){if(a.nodeType===q.Node.ELEMENT_NODE)for(var c=a.attributes,b=0,d=c.length;b<d;b++){var e=c[b],f=e.name.toLowerCase();if("xmlns:ns1"===f||0===f.lastIndexOf("ns1:",0))a.removeAttributeNode(e),b--,d--}(c=a.firstChild)&&r(c);(c=a.nextSibling)&&r(c)}var w=e.$$minErr("$sanitize"),D=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,E=/([^\#-~ |!])/g,z=h("area,br,col,hr,img,wbr"),m=h("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),k=h("rp,rt"),u=e.extend({},k,m),
m=e.extend({},m,h("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul")),k=e.extend({},k,h("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),H=h("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan"),
F=h("script,style"),n=e.extend({},z,m,k,u),y=h("background,cite,href,longdesc,src,xlink:href"),u=h("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,valign,value,vspace,width"),k=h("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan",
!0),G=e.extend({},y,k,u),g;(function(a){if(a.document&&a.document.implementation)a=a.document.implementation.createHTMLDocument("inert");else throw w("noinert");var c=(a.documentElement||a.getDocumentElement()).getElementsByTagName("body");1===c.length?g=c[0]:(c=a.createElement("html"),g=a.createElement("body"),c.appendChild(g),a.appendChild(c))})(q);e.module("ngSanitize",[]).provider("$sanitize",function(){var a=!1;this.$get=["$$sanitizeUri",function(c){a&&e.extend(n,H);return function(a){var d=
[];B(a,v(d,function(a,b){return!/^unsafe:/.test(c(a,b))}));return d.join("")}}];this.enableSvg=function(c){return e.isDefined(c)?(a=c,this):a}});e.module("ngSanitize").filter("linky",["$sanitize",function(a){var c=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,b=/^mailto:/i,d=e.$$minErr("linky"),g=e.isString;return function(f,h,k){function m(a){a&&p.push(A(a))}function q(a,b){var c,d=r(a);p.push("<a ");for(c in d)p.push(c+'="'+d[c]+'" ');!e.isDefined(h)||
"target"in d||p.push('target="',h,'" ');p.push('href="',a.replace(/"/g,"&quot;"),'">');m(b);p.push("</a>")}if(null==f||""===f)return f;if(!g(f))throw d("notstring",f);for(var r=e.isFunction(k)?k:e.isObject(k)?function(){return k}:function(){return{}},s=f,p=[],t,n;f=s.match(c);)t=f[0],f[2]||f[4]||(t=(f[3]?"http://":"mailto:")+t),n=f.index,m(s.substr(0,n)),q(t,f[0].replace(b,"")),s=s.substring(n+f[0].length);m(s);return a(p.join(""))}}])})(window,window.angular);
//# sourceMappingURL=angular-sanitize.min.js.map
;
define("angularSanitize", ["angular"], function(){});

vendors/angular-animate/angular-animate.min.js
/*
 AngularJS v1.5.7
 (c) 2010-2016 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(R,C){'use strict';function Aa(a,b,c){if(!a)throw Ma("areq",b||"?",c||"required");return a}function Ba(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;ca(a)&&(a=a.join(" "));ca(b)&&(b=b.join(" "));return a+" "+b}function Na(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function Y(a,b,c){var d="";a=ca(a)?a:a&&O(a)&&a.length?a.split(/\s+/):[];s(a,function(a,l){a&&0<a.length&&(d+=0<l?" ":"",d+=c?b+a:a+b)});return d}function Oa(a){if(a instanceof G)switch(a.length){case 0:return a;
case 1:if(1===a[0].nodeType)return a;break;default:return G(da(a))}if(1===a.nodeType)return G(a)}function da(a){if(!a[0])return a;for(var b=0;b<a.length;b++){var c=a[b];if(1==c.nodeType)return c}}function Pa(a,b,c){s(b,function(b){a.addClass(b,c)})}function Qa(a,b,c){s(b,function(b){a.removeClass(b,c)})}function V(a){return function(b,c){c.addClass&&(Pa(a,b,c.addClass),c.addClass=null);c.removeClass&&(Qa(a,b,c.removeClass),c.removeClass=null)}}function oa(a){a=a||{};if(!a.$$prepared){var b=a.domOperation||
Q;a.domOperation=function(){a.$$domOperationFired=!0;b();b=Q};a.$$prepared=!0}return a}function ha(a,b){Ca(a,b);Da(a,b)}function Ca(a,b){b.from&&(a.css(b.from),b.from=null)}function Da(a,b){b.to&&(a.css(b.to),b.to=null)}function W(a,b,c){var d=b.options||{};c=c.options||{};var e=(d.addClass||"")+" "+(c.addClass||""),l=(d.removeClass||"")+" "+(c.removeClass||"");a=Ra(a.attr("class"),e,l);c.preparationClasses&&(d.preparationClasses=Z(c.preparationClasses,d.preparationClasses),delete c.preparationClasses);
e=d.domOperation!==Q?d.domOperation:null;Ea(d,c);e&&(d.domOperation=e);d.addClass=a.addClass?a.addClass:null;d.removeClass=a.removeClass?a.removeClass:null;b.addClass=d.addClass;b.removeClass=d.removeClass;return d}function Ra(a,b,c){function d(a){O(a)&&(a=a.split(" "));var b={};s(a,function(a){a.length&&(b[a]=!0)});return b}var e={};a=d(a);b=d(b);s(b,function(a,b){e[b]=1});c=d(c);s(c,function(a,b){e[b]=1===e[b]?null:-1});var l={addClass:"",removeClass:""};s(e,function(b,c){var d,e;1===b?(d="addClass",
e=!a[c]):-1===b&&(d="removeClass",e=a[c]);e&&(l[d].length&&(l[d]+=" "),l[d]+=c)});return l}function z(a){return a instanceof C.element?a[0]:a}function Sa(a,b,c){var d="";b&&(d=Y(b,"ng-",!0));c.addClass&&(d=Z(d,Y(c.addClass,"-add")));c.removeClass&&(d=Z(d,Y(c.removeClass,"-remove")));d.length&&(c.preparationClasses=d,a.addClass(d))}function pa(a,b){var c=b?"-"+b+"s":"";la(a,[ma,c]);return[ma,c]}function ta(a,b){var c=b?"paused":"",d=$+"PlayState";la(a,[d,c]);return[d,c]}function la(a,b){a.style[b[0]]=
b[1]}function Z(a,b){return a?b?a+" "+b:a:b}function Fa(a,b,c){var d=Object.create(null),e=a.getComputedStyle(b)||{};s(c,function(a,b){var c=e[a];if(c){var g=c.charAt(0);if("-"===g||"+"===g||0<=g)c=Ta(c);0===c&&(c=null);d[b]=c}});return d}function Ta(a){var b=0;a=a.split(/\s*,\s*/);s(a,function(a){"s"==a.charAt(a.length-1)&&(a=a.substring(0,a.length-1));a=parseFloat(a)||0;b=b?Math.max(a,b):a});return b}function ua(a){return 0===a||null!=a}function Ga(a,b){var c=S,d=a+"s";b?c+="Duration":d+=" linear all";
return[c,d]}function Ha(){var a=Object.create(null);return{flush:function(){a=Object.create(null)},count:function(b){return(b=a[b])?b.total:0},get:function(b){return(b=a[b])&&b.value},put:function(b,c){a[b]?a[b].total++:a[b]={total:1,value:c}}}}function Ia(a,b,c){s(c,function(c){a[c]=ea(a[c])?a[c]:b.style.getPropertyValue(c)})}var Q=C.noop,Ja=C.copy,Ea=C.extend,G=C.element,s=C.forEach,ca=C.isArray,O=C.isString,va=C.isObject,I=C.isUndefined,ea=C.isDefined,Ka=C.isFunction,wa=C.isElement,S,xa,$,ya;I(R.ontransitionend)&&
ea(R.onwebkittransitionend)?(S="WebkitTransition",xa="webkitTransitionEnd transitionend"):(S="transition",xa="transitionend");I(R.onanimationend)&&ea(R.onwebkitanimationend)?($="WebkitAnimation",ya="webkitAnimationEnd animationend"):($="animation",ya="animationend");var qa=$+"Delay",za=$+"Duration",ma=S+"Delay",La=S+"Duration",Ma=C.$$minErr("ng"),Ua={transitionDuration:La,transitionDelay:ma,transitionProperty:S+"Property",animationDuration:za,animationDelay:qa,animationIterationCount:$+"IterationCount"},
Va={transitionDuration:La,transitionDelay:ma,animationDuration:za,animationDelay:qa};C.module("ngAnimate",[]).directive("ngAnimateSwap",["$animate","$rootScope",function(a,b){return{restrict:"A",transclude:"element",terminal:!0,priority:600,link:function(b,d,e,l,n){var H,g;b.$watchCollection(e.ngAnimateSwap||e["for"],function(e){H&&a.leave(H);g&&(g.$destroy(),g=null);if(e||0===e)g=b.$new(),n(g,function(b){H=b;a.enter(b,null,d)})})}}}]).directive("ngAnimateChildren",["$interpolate",function(a){return{link:function(b,
c,d){function e(a){c.data("$$ngAnimateChildren","on"===a||"true"===a)}var l=d.ngAnimateChildren;C.isString(l)&&0===l.length?c.data("$$ngAnimateChildren",!0):(e(a(l)(b)),d.$observe("ngAnimateChildren",e))}}}]).factory("$$rAFScheduler",["$$rAF",function(a){function b(a){d=d.concat(a);c()}function c(){if(d.length){for(var b=d.shift(),n=0;n<b.length;n++)b[n]();e||a(function(){e||c()})}}var d,e;d=b.queue=[];b.waitUntilQuiet=function(b){e&&e();e=a(function(){e=null;b();c()})};return b}]).provider("$$animateQueue",
["$animateProvider",function(a){function b(a){if(!a)return null;a=a.split(" ");var b=Object.create(null);s(a,function(a){b[a]=!0});return b}function c(a,c){if(a&&c){var d=b(c);return a.split(" ").some(function(a){return d[a]})}}function d(a,b,c,d){return l[a].some(function(a){return a(b,c,d)})}function e(a,b){var c=0<(a.addClass||"").length,d=0<(a.removeClass||"").length;return b?c&&d:c||d}var l=this.rules={skip:[],cancel:[],join:[]};l.join.push(function(a,b,c){return!b.structural&&e(b)});l.skip.push(function(a,
b,c){return!b.structural&&!e(b)});l.skip.push(function(a,b,c){return"leave"==c.event&&b.structural});l.skip.push(function(a,b,c){return c.structural&&2===c.state&&!b.structural});l.cancel.push(function(a,b,c){return c.structural&&b.structural});l.cancel.push(function(a,b,c){return 2===c.state&&b.structural});l.cancel.push(function(a,b,d){if(d.structural)return!1;a=b.addClass;b=b.removeClass;var e=d.addClass;d=d.removeClass;return I(a)&&I(b)||I(e)&&I(d)?!1:c(a,d)||c(b,e)});this.$get=["$$rAF","$rootScope",
"$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite","$$forceReflow",function(b,c,g,l,v,Wa,P,t,F,T){function J(){var a=!1;return function(b){a?b():c.$$postDigest(function(){a=!0;b()})}}function y(a,b,c){var f=z(b),d=z(a),N=[];(a=h[c])&&s(a,function(a){x.call(a.node,f)?N.push(a.callback):"leave"===c&&x.call(a.node,d)&&N.push(a.callback)});return N}function r(a,b,c){var f=da(b);return a.filter(function(a){return!(a.node===f&&(!c||a.callback===c))})}function p(a,
h,w){function r(c,f,d,h){sa(function(){var c=y(T,a,f);c.length?b(function(){s(c,function(b){b(a,d,h)});"close"!==d||a[0].parentNode||ra.off(a)}):"close"!==d||a[0].parentNode||ra.off(a)});c.progress(f,d,h)}function k(b){var c=a,f=m;f.preparationClasses&&(c.removeClass(f.preparationClasses),f.preparationClasses=null);f.activeClasses&&(c.removeClass(f.activeClasses),f.activeClasses=null);E(a,m);ha(a,m);m.domOperation();B.complete(!b)}var m=Ja(w),p,T;if(a=Oa(a))p=z(a),T=a.parent();var m=oa(m),B=new P,
sa=J();ca(m.addClass)&&(m.addClass=m.addClass.join(" "));m.addClass&&!O(m.addClass)&&(m.addClass=null);ca(m.removeClass)&&(m.removeClass=m.removeClass.join(" "));m.removeClass&&!O(m.removeClass)&&(m.removeClass=null);m.from&&!va(m.from)&&(m.from=null);m.to&&!va(m.to)&&(m.to=null);if(!p)return k(),B;w=[p.className,m.addClass,m.removeClass].join(" ");if(!Xa(w))return k(),B;var g=0<=["enter","move","leave"].indexOf(h),x=l[0].hidden,t=!f||x||N.get(p);w=!t&&A.get(p)||{};var F=!!w.state;t||F&&1==w.state||
(t=!M(a,T,h));if(t)return x&&r(B,h,"start"),k(),x&&r(B,h,"close"),B;g&&K(a);x={structural:g,element:a,event:h,addClass:m.addClass,removeClass:m.removeClass,close:k,options:m,runner:B};if(F){if(d("skip",a,x,w)){if(2===w.state)return k(),B;W(a,w,x);return w.runner}if(d("cancel",a,x,w))if(2===w.state)w.runner.end();else if(w.structural)w.close();else return W(a,w,x),w.runner;else if(d("join",a,x,w))if(2===w.state)W(a,x,{});else return Sa(a,g?h:null,m),h=x.event=w.event,m=W(a,w,x),w.runner}else W(a,x,
{});(F=x.structural)||(F="animate"===x.event&&0<Object.keys(x.options.to||{}).length||e(x));if(!F)return k(),ka(a),B;var v=(w.counter||0)+1;x.counter=v;L(a,1,x);c.$$postDigest(function(){var b=A.get(p),c=!b,b=b||{},f=0<(a.parent()||[]).length&&("animate"===b.event||b.structural||e(b));if(c||b.counter!==v||!f){c&&(E(a,m),ha(a,m));if(c||g&&b.event!==h)m.domOperation(),B.end();f||ka(a)}else h=!b.structural&&e(b,!0)?"setClass":b.event,L(a,2),b=Wa(a,h,b.options),B.setHost(b),r(B,h,"start",{}),b.done(function(b){k(!b);
(b=A.get(p))&&b.counter===v&&ka(z(a));r(B,h,"close",{})})});return B}function K(a){a=z(a).querySelectorAll("[data-ng-animate]");s(a,function(a){var b=parseInt(a.getAttribute("data-ng-animate")),c=A.get(a);if(c)switch(b){case 2:c.runner.end();case 1:A.remove(a)}})}function ka(a){a=z(a);a.removeAttribute("data-ng-animate");A.remove(a)}function k(a,b){return z(a)===z(b)}function M(a,b,c){c=G(l[0].body);var f=k(a,c)||"HTML"===a[0].nodeName,d=k(a,g),h=!1,r,e=N.get(z(a));(a=G.data(a[0],"$ngAnimatePin"))&&
(b=a);for(b=z(b);b;){d||(d=k(b,g));if(1!==b.nodeType)break;a=A.get(b)||{};if(!h){var p=N.get(b);if(!0===p&&!1!==e){e=!0;break}else!1===p&&(e=!1);h=a.structural}if(I(r)||!0===r)a=G.data(b,"$$ngAnimateChildren"),ea(a)&&(r=a);if(h&&!1===r)break;f||(f=k(b,c));if(f&&d)break;if(!d&&(a=G.data(b,"$ngAnimatePin"))){b=z(a);continue}b=b.parentNode}return(!h||r)&&!0!==e&&d&&f}function L(a,b,c){c=c||{};c.state=b;a=z(a);a.setAttribute("data-ng-animate",b);c=(b=A.get(a))?Ea(b,c):c;A.put(a,c)}var A=new v,N=new v,
f=null,B=c.$watch(function(){return 0===t.totalPendingRequests},function(a){a&&(B(),c.$$postDigest(function(){c.$$postDigest(function(){null===f&&(f=!0)})}))}),h={},sa=a.classNameFilter(),Xa=sa?function(a){return sa.test(a)}:function(){return!0},E=V(F),x=R.Node.prototype.contains||function(a){return this===a||!!(this.compareDocumentPosition(a)&16)},ra={on:function(a,b,c){var f=da(b);h[a]=h[a]||[];h[a].push({node:f,callback:c});G(b).on("$destroy",function(){A.get(f)||ra.off(a,b,c)})},off:function(a,
b,c){if(1!==arguments.length||C.isString(arguments[0])){var f=h[a];f&&(h[a]=1===arguments.length?null:r(f,b,c))}else for(f in b=arguments[0],h)h[f]=r(h[f],b)},pin:function(a,b){Aa(wa(a),"element","not an element");Aa(wa(b),"parentElement","not an element");a.data("$ngAnimatePin",b)},push:function(a,b,c,f){c=c||{};c.domOperation=f;return p(a,b,c)},enabled:function(a,b){var c=arguments.length;if(0===c)b=!!f;else if(wa(a)){var d=z(a),h=N.get(d);1===c?b=!h:N.put(d,!b)}else b=f=!!a;return b}};return ra}]}]).provider("$$animation",
["$animateProvider",function(a){var b=this.drivers=[];this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$HashMap","$$rAFScheduler",function(a,d,e,l,n,H){function g(a){function b(a){if(a.processed)return a;a.processed=!0;var d=a.domNode,p=d.parentNode;e.put(d,a);for(var K;p;){if(K=e.get(p)){K.processed||(K=b(K));break}p=p.parentNode}(K||c).children.push(a);return a}var c={children:[]},d,e=new n;for(d=0;d<a.length;d++){var g=a[d];e.put(g.domNode,a[d]={domNode:g.domNode,fn:g.fn,children:[]})}for(d=
0;d<a.length;d++)b(a[d]);return function(a){var b=[],c=[],d;for(d=0;d<a.children.length;d++)c.push(a.children[d]);a=c.length;var e=0,k=[];for(d=0;d<c.length;d++){var g=c[d];0>=a&&(a=e,e=0,b.push(k),k=[]);k.push(g.fn);g.children.forEach(function(a){e++;c.push(a)});a--}k.length&&b.push(k);return b}(c)}var u=[],v=V(a);return function(n,P,t){function F(a){a=a.hasAttribute("ng-animate-ref")?[a]:a.querySelectorAll("[ng-animate-ref]");var b=[];s(a,function(a){var c=a.getAttribute("ng-animate-ref");c&&c.length&&
b.push(a)});return b}function T(a){var b=[],c={};s(a,function(a,d){var h=z(a.element),e=0<=["enter","move"].indexOf(a.event),h=a.structural?F(h):[];if(h.length){var k=e?"to":"from";s(h,function(a){var b=a.getAttribute("ng-animate-ref");c[b]=c[b]||{};c[b][k]={animationID:d,element:G(a)}})}else b.push(a)});var d={},e={};s(c,function(c,k){var r=c.from,p=c.to;if(r&&p){var A=a[r.animationID],g=a[p.animationID],B=r.animationID.toString();if(!e[B]){var n=e[B]={structural:!0,beforeStart:function(){A.beforeStart();
g.beforeStart()},close:function(){A.close();g.close()},classes:J(A.classes,g.classes),from:A,to:g,anchors:[]};n.classes.length?b.push(n):(b.push(A),b.push(g))}e[B].anchors.push({out:r.element,"in":p.element})}else r=r?r.animationID:p.animationID,p=r.toString(),d[p]||(d[p]=!0,b.push(a[r]))});return b}function J(a,b){a=a.split(" ");b=b.split(" ");for(var c=[],d=0;d<a.length;d++){var e=a[d];if("ng-"!==e.substring(0,3))for(var r=0;r<b.length;r++)if(e===b[r]){c.push(e);break}}return c.join(" ")}function y(a){for(var c=
b.length-1;0<=c;c--){var d=e.get(b[c])(a);if(d)return d}}function r(a,b){function c(a){(a=a.data("$$animationRunner"))&&a.setHost(b)}a.from&&a.to?(c(a.from.element),c(a.to.element)):c(a.element)}function p(){var a=n.data("$$animationRunner");!a||"leave"===P&&t.$$domOperationFired||a.end()}function K(b){n.off("$destroy",p);n.removeData("$$animationRunner");v(n,t);ha(n,t);t.domOperation();L&&a.removeClass(n,L);n.removeClass("ng-animate");k.complete(!b)}t=oa(t);var ka=0<=["enter","move","leave"].indexOf(P),
k=new l({end:function(){K()},cancel:function(){K(!0)}});if(!b.length)return K(),k;n.data("$$animationRunner",k);var M=Ba(n.attr("class"),Ba(t.addClass,t.removeClass)),L=t.tempClasses;L&&(M+=" "+L,t.tempClasses=null);var A;ka&&(A="ng-"+P+"-prepare",a.addClass(n,A));u.push({element:n,classes:M,event:P,structural:ka,options:t,beforeStart:function(){n.addClass("ng-animate");L&&a.addClass(n,L);A&&(a.removeClass(n,A),A=null)},close:K});n.on("$destroy",p);if(1<u.length)return k;d.$$postDigest(function(){var a=
[];s(u,function(b){b.element.data("$$animationRunner")?a.push(b):b.close()});u.length=0;var b=T(a),c=[];s(b,function(a){c.push({domNode:z(a.from?a.from.element:a.element),fn:function(){a.beforeStart();var b,c=a.close;if((a.anchors?a.from.element||a.to.element:a.element).data("$$animationRunner")){var d=y(a);d&&(b=d.start)}b?(b=b(),b.done(function(a){c(!a)}),r(a,b)):c()}})});H(g(c))});return k}}]}]).provider("$animateCss",["$animateProvider",function(a){var b=Ha(),c=Ha();this.$get=["$window","$$jqLite",
"$$AnimateRunner","$timeout","$$forceReflow","$sniffer","$$rAFScheduler","$$animateQueue",function(a,e,l,n,H,g,u,v){function C(a,b){var c=a.parentNode;return(c.$$ngAnimateParentKey||(c.$$ngAnimateParentKey=++J))+"-"+a.getAttribute("class")+"-"+b}function P(r,p,g,n){var k;0<b.count(g)&&(k=c.get(g),k||(p=Y(p,"-stagger"),e.addClass(r,p),k=Fa(a,r,n),k.animationDuration=Math.max(k.animationDuration,0),k.transitionDuration=Math.max(k.transitionDuration,0),e.removeClass(r,p),c.put(g,k)));return k||{}}function t(a){y.push(a);
u.waitUntilQuiet(function(){b.flush();c.flush();for(var a=H(),d=0;d<y.length;d++)y[d](a);y.length=0})}function F(c,e,g){e=b.get(g);e||(e=Fa(a,c,Ua),"infinite"===e.animationIterationCount&&(e.animationIterationCount=1));b.put(g,e);c=e;g=c.animationDelay;e=c.transitionDelay;c.maxDelay=g&&e?Math.max(g,e):g||e;c.maxDuration=Math.max(c.animationDuration*c.animationIterationCount,c.transitionDuration);return c}var T=V(e),J=0,y=[];return function(a,c){function d(){k()}function u(){k(!0)}function k(b){if(!(x||
G&&J)){x=!0;J=!1;f.$$skipPreparationClasses||e.removeClass(a,ga);e.removeClass(a,ea);ta(h,!1);pa(h,!1);s(y,function(a){h.style[a[0]]=""});T(a,f);ha(a,f);Object.keys(B).length&&s(B,function(a,b){a?h.style.setProperty(b,a):h.style.removeProperty(b)});if(f.onDone)f.onDone();fa&&fa.length&&a.off(fa.join(" "),A);var c=a.data("$$animateCss");c&&(n.cancel(c[0].timer),a.removeData("$$animateCss"));I&&I.complete(!b)}}function M(a){q.blockTransition&&pa(h,a);q.blockKeyframeAnimation&&ta(h,!!a)}function L(){I=
new l({end:d,cancel:u});t(Q);k();return{$$willAnimate:!1,start:function(){return I},end:d}}function A(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-W,0)>=R&&b>=m&&(G=!0,k())}function N(){function b(){if(!x){M(!1);s(y,function(a){h.style[a[0]]=a[1]});T(a,f);e.addClass(a,ea);if(q.recalculateTimingStyles){na=h.className+" "+ga;ia=C(h,na);D=F(h,na,ia);aa=D.maxDelay;O=Math.max(aa,0);m=D.maxDuration;if(0===m){k();return}q.hasTransitions=
0<D.transitionDuration;q.hasAnimations=0<D.animationDuration}q.applyAnimationDelay&&(aa="boolean"!==typeof f.delay&&ua(f.delay)?parseFloat(f.delay):aa,O=Math.max(aa,0),D.animationDelay=aa,ba=[qa,aa+"s"],y.push(ba),h.style[ba[0]]=ba[1]);R=1E3*O;V=1E3*m;if(f.easing){var d,g=f.easing;q.hasTransitions&&(d=S+"TimingFunction",y.push([d,g]),h.style[d]=g);q.hasAnimations&&(d=$+"TimingFunction",y.push([d,g]),h.style[d]=g)}D.transitionDuration&&fa.push(xa);D.animationDuration&&fa.push(ya);W=Date.now();var p=
R+1.5*V;d=W+p;var g=a.data("$$animateCss")||[],N=!0;if(g.length){var l=g[0];(N=d>l.expectedEndTime)?n.cancel(l.timer):g.push(k)}N&&(p=n(c,p,!1),g[0]={timer:p,expectedEndTime:d},g.push(k),a.data("$$animateCss",g));if(fa.length)a.on(fa.join(" "),A);f.to&&(f.cleanupStyles&&Ia(B,h,Object.keys(f.to)),Da(a,f))}}function c(){var b=a.data("$$animateCss");if(b){for(var d=1;d<b.length;d++)b[d]();a.removeData("$$animateCss")}}if(!x)if(h.parentNode){var d=function(a){if(G)J&&a&&(J=!1,k());else if(J=!a,D.animationDuration)if(a=
ta(h,J),J)y.push(a);else{var b=y,c=b.indexOf(a);0<=a&&b.splice(c,1)}},g=0<da&&(D.transitionDuration&&0===X.transitionDuration||D.animationDuration&&0===X.animationDuration)&&Math.max(X.animationDelay,X.transitionDelay);g?n(b,Math.floor(g*da*1E3),!1):b();w.resume=function(){d(!0)};w.pause=function(){d(!1)}}else k()}var f=c||{};f.$$prepared||(f=oa(Ja(f)));var B={},h=z(a);if(!h||!h.parentNode||!v.enabled())return L();var y=[],H=a.attr("class"),E=Na(f),x,J,G,I,w,O,R,m,V,W,fa=[];if(0===f.duration||!g.animations&&
!g.transitions)return L();var ja=f.event&&ca(f.event)?f.event.join(" "):f.event,Z="",U="";ja&&f.structural?Z=Y(ja,"ng-",!0):ja&&(Z=ja);f.addClass&&(U+=Y(f.addClass,"-add"));f.removeClass&&(U.length&&(U+=" "),U+=Y(f.removeClass,"-remove"));f.applyClassesEarly&&U.length&&T(a,f);var ga=[Z,U].join(" ").trim(),na=H+" "+ga,ea=Y(ga,"-active"),H=E.to&&0<Object.keys(E.to).length;if(!(0<(f.keyframeStyle||"").length||H||ga))return L();var ia,X;0<f.stagger?(E=parseFloat(f.stagger),X={transitionDelay:E,animationDelay:E,
transitionDuration:0,animationDuration:0}):(ia=C(h,na),X=P(h,ga,ia,Va));f.$$skipPreparationClasses||e.addClass(a,ga);f.transitionStyle&&(E=[S,f.transitionStyle],la(h,E),y.push(E));0<=f.duration&&(E=0<h.style[S].length,E=Ga(f.duration,E),la(h,E),y.push(E));f.keyframeStyle&&(E=[$,f.keyframeStyle],la(h,E),y.push(E));var da=X?0<=f.staggerIndex?f.staggerIndex:b.count(ia):0;(ja=0===da)&&!f.skipBlocking&&pa(h,9999);var D=F(h,na,ia),aa=D.maxDelay;O=Math.max(aa,0);m=D.maxDuration;var q={};q.hasTransitions=
0<D.transitionDuration;q.hasAnimations=0<D.animationDuration;q.hasTransitionAll=q.hasTransitions&&"all"==D.transitionProperty;q.applyTransitionDuration=H&&(q.hasTransitions&&!q.hasTransitionAll||q.hasAnimations&&!q.hasTransitions);q.applyAnimationDuration=f.duration&&q.hasAnimations;q.applyTransitionDelay=ua(f.delay)&&(q.applyTransitionDuration||q.hasTransitions);q.applyAnimationDelay=ua(f.delay)&&q.hasAnimations;q.recalculateTimingStyles=0<U.length;if(q.applyTransitionDuration||q.applyAnimationDuration)m=
f.duration?parseFloat(f.duration):m,q.applyTransitionDuration&&(q.hasTransitions=!0,D.transitionDuration=m,E=0<h.style[S+"Property"].length,y.push(Ga(m,E))),q.applyAnimationDuration&&(q.hasAnimations=!0,D.animationDuration=m,y.push([za,m+"s"]));if(0===m&&!q.recalculateTimingStyles)return L();if(null!=f.delay){var ba;"boolean"!==typeof f.delay&&(ba=parseFloat(f.delay),O=Math.max(ba,0));q.applyTransitionDelay&&y.push([ma,ba+"s"]);q.applyAnimationDelay&&y.push([qa,ba+"s"])}null==f.duration&&0<D.transitionDuration&&
(q.recalculateTimingStyles=q.recalculateTimingStyles||ja);R=1E3*O;V=1E3*m;f.skipBlocking||(q.blockTransition=0<D.transitionDuration,q.blockKeyframeAnimation=0<D.animationDuration&&0<X.animationDelay&&0===X.animationDuration);f.from&&(f.cleanupStyles&&Ia(B,h,Object.keys(f.from)),Ca(a,f));q.blockTransition||q.blockKeyframeAnimation?M(m):f.skipBlocking||pa(h,!1);return{$$willAnimate:!0,end:d,start:function(){if(!x)return w={end:d,cancel:u,resume:null,pause:null},I=new l(w),t(N),I}}}}]}]).provider("$$animateCssDriver",
["$$animationProvider",function(a){a.drivers.push("$$animateCssDriver");this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$sniffer","$$jqLite","$document",function(a,c,d,e,l,n,H){function g(a){return a.replace(/\bng-\S+\b/g,"")}function u(a,b){O(a)&&(a=a.split(" "));O(b)&&(b=b.split(" "));return a.filter(function(a){return-1===b.indexOf(a)}).join(" ")}function v(c,e,n){function l(a){var b={},c=z(a).getBoundingClientRect();s(["width","height","top","left"],function(a){var d=c[a];
switch(a){case "top":d+=t.scrollTop;break;case "left":d+=t.scrollLeft}b[a]=Math.floor(d)+"px"});return b}function p(){var c=g(n.attr("class")||""),d=u(c,k),c=u(k,c),d=a(v,{to:l(n),addClass:"ng-anchor-in "+d,removeClass:"ng-anchor-out "+c,delay:!0});return d.$$willAnimate?d:null}function H(){v.remove();e.removeClass("ng-animate-shim");n.removeClass("ng-animate-shim")}var v=G(z(e).cloneNode(!0)),k=g(v.attr("class")||"");e.addClass("ng-animate-shim");n.addClass("ng-animate-shim");v.addClass("ng-anchor");
F.append(v);var M;c=function(){var c=a(v,{addClass:"ng-anchor-out",delay:!0,from:l(e)});return c.$$willAnimate?c:null}();if(!c&&(M=p(),!M))return H();var L=c||M;return{start:function(){function a(){c&&c.end()}var b,c=L.start();c.done(function(){c=null;if(!M&&(M=p()))return c=M.start(),c.done(function(){c=null;H();b.complete()}),c;H();b.complete()});return b=new d({end:a,cancel:a})}}}function C(a,b,c,e){var g=P(a,Q),n=P(b,Q),l=[];s(e,function(a){(a=v(c,a.out,a["in"]))&&l.push(a)});if(g||n||0!==l.length)return{start:function(){function a(){s(b,
function(a){a.end()})}var b=[];g&&b.push(g.start());n&&b.push(n.start());s(l,function(a){b.push(a.start())});var c=new d({end:a,cancel:a});d.all(b,function(a){c.complete(a)});return c}}}function P(c){var d=c.element,e=c.options||{};c.structural&&(e.event=c.event,e.structural=!0,e.applyClassesEarly=!0,"leave"===c.event&&(e.onDone=e.domOperation));e.preparationClasses&&(e.event=Z(e.event,e.preparationClasses));c=a(d,e);return c.$$willAnimate?c:null}if(!l.animations&&!l.transitions)return Q;var t=H[0].body;
c=z(e);var F=G(c.parentNode&&11===c.parentNode.nodeType||t.contains(c)?c:t);V(n);return function(a){return a.from&&a.to?C(a.from,a.to,a.classes,a.anchors):P(a)}}]}]).provider("$$animateJs",["$animateProvider",function(a){this.$get=["$injector","$$AnimateRunner","$$jqLite",function(b,c,d){function e(c){c=ca(c)?c:c.split(" ");for(var d=[],e={},l=0;l<c.length;l++){var v=c[l],s=a.$$registeredAnimations[v];s&&!e[v]&&(d.push(b.get(s)),e[v]=!0)}return d}var l=V(d);return function(a,b,d,u){function v(){u.domOperation();
l(a,u)}function C(a,b,d,e,f){switch(d){case "animate":b=[b,e.from,e.to,f];break;case "setClass":b=[b,G,J,f];break;case "addClass":b=[b,G,f];break;case "removeClass":b=[b,J,f];break;default:b=[b,f]}b.push(e);if(a=a.apply(a,b))if(Ka(a.start)&&(a=a.start()),a instanceof c)a.done(f);else if(Ka(a))return a;return Q}function z(a,b,d,e,f){var g=[];s(e,function(e){var k=e[f];k&&g.push(function(){var e,f,g=!1,h=function(a){g||(g=!0,(f||Q)(a),e.complete(!a))};e=new c({end:function(){h()},cancel:function(){h(!0)}});
f=C(k,a,b,d,function(a){h(!1===a)});return e})});return g}function t(a,b,d,e,f){var g=z(a,b,d,e,f);if(0===g.length){var h,k;"beforeSetClass"===f?(h=z(a,"removeClass",d,e,"beforeRemoveClass"),k=z(a,"addClass",d,e,"beforeAddClass")):"setClass"===f&&(h=z(a,"removeClass",d,e,"removeClass"),k=z(a,"addClass",d,e,"addClass"));h&&(g=g.concat(h));k&&(g=g.concat(k))}if(0!==g.length)return function(a){var b=[];g.length&&s(g,function(a){b.push(a())});b.length?c.all(b,a):a();return function(a){s(b,function(b){a?
b.cancel():b.end()})}}}var F=!1;3===arguments.length&&va(d)&&(u=d,d=null);u=oa(u);d||(d=a.attr("class")||"",u.addClass&&(d+=" "+u.addClass),u.removeClass&&(d+=" "+u.removeClass));var G=u.addClass,J=u.removeClass,y=e(d),r,p;if(y.length){var K,I;"leave"==b?(I="leave",K="afterLeave"):(I="before"+b.charAt(0).toUpperCase()+b.substr(1),K=b);"enter"!==b&&"move"!==b&&(r=t(a,b,u,y,I));p=t(a,b,u,y,K)}if(r||p){var k;return{$$willAnimate:!0,end:function(){k?k.end():(F=!0,v(),ha(a,u),k=new c,k.complete(!0));return k},
start:function(){function b(c){F=!0;v();ha(a,u);k.complete(c)}if(k)return k;k=new c;var d,e=[];r&&e.push(function(a){d=r(a)});e.length?e.push(function(a){v();a(!0)}):v();p&&e.push(function(a){d=p(a)});k.setHost({end:function(){F||((d||Q)(void 0),b(void 0))},cancel:function(){F||((d||Q)(!0),b(!0))}});c.chain(e,b);return k}}}}}]}]).provider("$$animateJsDriver",["$$animationProvider",function(a){a.drivers.push("$$animateJsDriver");this.$get=["$$animateJs","$$AnimateRunner",function(a,c){function d(c){return a(c.element,
c.event,c.classes,c.options)}return function(a){if(a.from&&a.to){var b=d(a.from),n=d(a.to);if(b||n)return{start:function(){function a(){return function(){s(d,function(a){a.end()})}}var d=[];b&&d.push(b.start());n&&d.push(n.start());c.all(d,function(a){e.complete(a)});var e=new c({end:a(),cancel:a()});return e}}}else return d(a)}}]}])})(window,window.angular);
//# sourceMappingURL=angular-animate.min.js.map
;
define("angularAnimate", ["angular"], function(){});

vendors/angular-cookies/angular-cookies.min.js
/*
 AngularJS v1.5.7
 (c) 2010-2016 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(n,c){'use strict';function l(b,a,g){var d=g.baseHref(),k=b[0];return function(b,e,f){var g,h;f=f||{};h=f.expires;g=c.isDefined(f.path)?f.path:d;c.isUndefined(e)&&(h="Thu, 01 Jan 1970 00:00:00 GMT",e="");c.isString(h)&&(h=new Date(h));e=encodeURIComponent(b)+"="+encodeURIComponent(e);e=e+(g?";path="+g:"")+(f.domain?";domain="+f.domain:"");e+=h?";expires="+h.toUTCString():"";e+=f.secure?";secure":"";f=e.length+1;4096<f&&a.warn("Cookie '"+b+"' possibly not set or overflowed because it was too large ("+
f+" > 4096 bytes)!");k.cookie=e}}c.module("ngCookies",["ng"]).provider("$cookies",[function(){var b=this.defaults={};this.$get=["$$cookieReader","$$cookieWriter",function(a,g){return{get:function(d){return a()[d]},getObject:function(d){return(d=this.get(d))?c.fromJson(d):d},getAll:function(){return a()},put:function(d,a,m){g(d,a,m?c.extend({},b,m):b)},putObject:function(d,b,a){this.put(d,c.toJson(b),a)},remove:function(a,k){g(a,void 0,k?c.extend({},b,k):b)}}}]}]);c.module("ngCookies").factory("$cookieStore",
["$cookies",function(b){return{get:function(a){return b.getObject(a)},put:function(a,c){b.putObject(a,c)},remove:function(a){b.remove(a)}}}]);l.$inject=["$document","$log","$browser"];c.module("ngCookies").provider("$$cookieWriter",function(){this.$get=l})})(window,window.angular);
//# sourceMappingURL=angular-cookies.min.js.map
;
define("angularCookies", ["angular"], function(){});

vendors/angular-cookie/angular-cookie.min.js
angular.module("ivpusic.cookie",["ipCookie"]),angular.module("ipCookie",["ng"]).factory("ipCookie",["$document",function(e){"use strict";function i(e){try{return decodeURIComponent(e)}catch(i){}}return function(){function t(t,n,r){var o,s,p,u,a,c,x,d,f;if(r=r||{},void 0!==n)return n="object"==typeof n?JSON.stringify(n):n+"","number"==typeof r.expires&&(f=r.expires,r.expires=new Date,-1===f?r.expires=new Date("Thu, 01 Jan 1970 00:00:00 GMT"):void 0!==r.expirationUnit?"hours"===r.expirationUnit?r.expires.setHours(r.expires.getHours()+f):"minutes"===r.expirationUnit?r.expires.setMinutes(r.expires.getMinutes()+f):"seconds"===r.expirationUnit?r.expires.setSeconds(r.expires.getSeconds()+f):r.expires.setDate(r.expires.getDate()+f):r.expires.setDate(r.expires.getDate()+f)),e[0].cookie=[encodeURIComponent(t),"=",encodeURIComponent(n),r.expires?"; expires="+r.expires.toUTCString():"",r.path?"; path="+r.path:"",r.domain?"; domain="+r.domain:"",r.secure?"; secure":""].join("");for(s=[],d=e[0].cookie,d&&(s=d.split("; ")),o={},x=!1,p=0;s.length>p;++p)if(s[p]){if(u=s[p],a=u.indexOf("="),c=u.substring(0,a),n=i(u.substring(a+1)),angular.isUndefined(n))continue;if(void 0===t||t===c){try{o[c]=JSON.parse(n)}catch(g){o[c]=n}if(t===c)return o[c];x=!0}}return x&&void 0===t?o:void 0}return t.remove=function(e,i){var n=void 0!==t(e);return n&&(i||(i={}),i.expires=-1,t(e,"",i)),n},t}()}]);
define("angularCookie", ["angular"], function(){});

vendors/angular-utf8-base64/angular-utf8-base64.min.js
"use strict";angular.module("ab-base64",[]).constant("base64",function(){var a={alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",lookup:null,ie:/MSIE /.test(navigator.userAgent),ieo:/MSIE [67]/.test(navigator.userAgent),encode:function(b){var c,d,e,f,g=a.toUtf8(b),h=-1,i=g.length,j=[,,,];if(a.ie){for(c=[];++h<i;)d=g[h],e=g[++h],j[0]=d>>2,j[1]=(3&d)<<4|e>>4,isNaN(e)?j[2]=j[3]=64:(f=g[++h],j[2]=(15&e)<<2|f>>6,j[3]=isNaN(f)?64:63&f),c.push(a.alphabet.charAt(j[0]),a.alphabet.charAt(j[1]),a.alphabet.charAt(j[2]),a.alphabet.charAt(j[3]));return c.join("")}for(c="";++h<i;)d=g[h],e=g[++h],j[0]=d>>2,j[1]=(3&d)<<4|e>>4,isNaN(e)?j[2]=j[3]=64:(f=g[++h],j[2]=(15&e)<<2|f>>6,j[3]=isNaN(f)?64:63&f),c+=a.alphabet[j[0]]+a.alphabet[j[1]]+a.alphabet[j[2]]+a.alphabet[j[3]];return c},decode:function(b){if(b=b.replace(/\s/g,""),b.length%4)throw new Error("InvalidLengthError: decode failed: The string to be decoded is not the correct length for a base64 encoded string.");if(/[^A-Za-z0-9+\/=\s]/g.test(b))throw new Error("InvalidCharacterError: decode failed: The string contains characters invalid in a base64 encoded string.");var c,d=a.fromUtf8(b),e=0,f=d.length;if(a.ieo){for(c=[];f>e;)c.push(d[e]<128?String.fromCharCode(d[e++]):d[e]>191&&d[e]<224?String.fromCharCode((31&d[e++])<<6|63&d[e++]):String.fromCharCode((15&d[e++])<<12|(63&d[e++])<<6|63&d[e++]));return c.join("")}for(c="";f>e;)c+=String.fromCharCode(d[e]<128?d[e++]:d[e]>191&&d[e]<224?(31&d[e++])<<6|63&d[e++]:(15&d[e++])<<12|(63&d[e++])<<6|63&d[e++]);return c},toUtf8:function(a){var b,c=-1,d=a.length,e=[];if(/^[\x00-\x7f]*$/.test(a))for(;++c<d;)e.push(a.charCodeAt(c));else for(;++c<d;)b=a.charCodeAt(c),128>b?e.push(b):2048>b?e.push(b>>6|192,63&b|128):e.push(b>>12|224,b>>6&63|128,63&b|128);return e},fromUtf8:function(b){var c,d=-1,e=[],f=[,,,];if(!a.lookup){for(c=a.alphabet.length,a.lookup={};++d<c;)a.lookup[a.alphabet.charAt(d)]=d;d=-1}for(c=b.length;++d<c&&(f[0]=a.lookup[b.charAt(d)],f[1]=a.lookup[b.charAt(++d)],e.push(f[0]<<2|f[1]>>4),f[2]=a.lookup[b.charAt(++d)],64!==f[2])&&(e.push((15&f[1])<<4|f[2]>>2),f[3]=a.lookup[b.charAt(++d)],64!==f[3]);)e.push((3&f[2])<<6|f[3]);return e}},b={decode:function(b){b=b.replace(/-/g,"+").replace(/_/g,"/");var c=b.length%4;if(c){if(1===c)throw new Error("InvalidLengthError: Input base64url string is the wrong length to determine padding");b+=new Array(5-c).join("=")}return a.decode(b)},encode:function(b){var c=a.encode(b);return c.replace(/\+/g,"-").replace(/\//g,"_").split("=",1)[0]}};return{decode:a.decode,encode:a.encode,urldecode:b.decode,urlencode:b.encode}}());
define("angularUTF8Base64", ["angular"], function(){});

../node_modules/lodash/lodash.js
/**
 * @license
 * Lodash <https://lodash.com/>
 * Copyright JS Foundation and other contributors <https://js.foundation/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */
;(function() {

  /** Used as a safe reference for `undefined` in pre-ES5 environments. */
  var undefined;

  /** Used as the semantic version number. */
  var VERSION = '4.17.4';

  /** Used as the size to enable large array optimizations. */
  var LARGE_ARRAY_SIZE = 200;

  /** Error message constants. */
  var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
      FUNC_ERROR_TEXT = 'Expected a function';

  /** Used to stand-in for `undefined` hash values. */
  var HASH_UNDEFINED = '__lodash_hash_undefined__';

  /** Used as the maximum memoize cache size. */
  var MAX_MEMOIZE_SIZE = 500;

  /** Used as the internal argument placeholder. */
  var PLACEHOLDER = '__lodash_placeholder__';

  /** Used to compose bitmasks for cloning. */
  var CLONE_DEEP_FLAG = 1,
      CLONE_FLAT_FLAG = 2,
      CLONE_SYMBOLS_FLAG = 4;

  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1,
      COMPARE_UNORDERED_FLAG = 2;

  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1,
      WRAP_BIND_KEY_FLAG = 2,
      WRAP_CURRY_BOUND_FLAG = 4,
      WRAP_CURRY_FLAG = 8,
      WRAP_CURRY_RIGHT_FLAG = 16,
      WRAP_PARTIAL_FLAG = 32,
      WRAP_PARTIAL_RIGHT_FLAG = 64,
      WRAP_ARY_FLAG = 128,
      WRAP_REARG_FLAG = 256,
      WRAP_FLIP_FLAG = 512;

  /** Used as default options for `_.truncate`. */
  var DEFAULT_TRUNC_LENGTH = 30,
      DEFAULT_TRUNC_OMISSION = '...';

  /** Used to detect hot functions by number of calls within a span of milliseconds. */
  var HOT_COUNT = 800,
      HOT_SPAN = 16;

  /** Used to indicate the type of lazy iteratees. */
  var LAZY_FILTER_FLAG = 1,
      LAZY_MAP_FLAG = 2,
      LAZY_WHILE_FLAG = 3;

  /** Used as references for various `Number` constants. */
  var INFINITY = 1 / 0,
      MAX_SAFE_INTEGER = 9007199254740991,
      MAX_INTEGER = 1.7976931348623157e+308,
      NAN = 0 / 0;

  /** Used as references for the maximum length and index of an array. */
  var MAX_ARRAY_LENGTH = 4294967295,
      MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
      HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;

  /** Used to associate wrap methods with their bit flags. */
  var wrapFlags = [
    ['ary', WRAP_ARY_FLAG],
    ['bind', WRAP_BIND_FLAG],
    ['bindKey', WRAP_BIND_KEY_FLAG],
    ['curry', WRAP_CURRY_FLAG],
    ['curryRight', WRAP_CURRY_RIGHT_FLAG],
    ['flip', WRAP_FLIP_FLAG],
    ['partial', WRAP_PARTIAL_FLAG],
    ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
    ['rearg', WRAP_REARG_FLAG]
  ];

  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      asyncTag = '[object AsyncFunction]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      domExcTag = '[object DOMException]',
      errorTag = '[object Error]',
      funcTag = '[object Function]',
      genTag = '[object GeneratorFunction]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      nullTag = '[object Null]',
      objectTag = '[object Object]',
      promiseTag = '[object Promise]',
      proxyTag = '[object Proxy]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      symbolTag = '[object Symbol]',
      undefinedTag = '[object Undefined]',
      weakMapTag = '[object WeakMap]',
      weakSetTag = '[object WeakSet]';

  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';

  /** Used to match empty string literals in compiled template source. */
  var reEmptyStringLeading = /\b__p \+= '';/g,
      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;

  /** Used to match HTML entities and HTML characters. */
  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
      reUnescapedHtml = /[&<>"']/g,
      reHasEscapedHtml = RegExp(reEscapedHtml.source),
      reHasUnescapedHtml = RegExp(reUnescapedHtml.source);

  /** Used to match template delimiters. */
  var reEscape = /<%-([\s\S]+?)%>/g,
      reEvaluate = /<%([\s\S]+?)%>/g,
      reInterpolate = /<%=([\s\S]+?)%>/g;

  /** Used to match property names within property paths. */
  var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
      reIsPlainProp = /^\w*$/,
      reLeadingDot = /^\./,
      rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

  /**
   * Used to match `RegExp`
   * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
   */
  var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
      reHasRegExpChar = RegExp(reRegExpChar.source);

  /** Used to match leading and trailing whitespace. */
  var reTrim = /^\s+|\s+$/g,
      reTrimStart = /^\s+/,
      reTrimEnd = /\s+$/;

  /** Used to match wrap detail comments. */
  var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
      reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
      reSplitDetails = /,? & /;

  /** Used to match words composed of alphanumeric characters. */
  var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;

  /** Used to match backslashes in property paths. */
  var reEscapeChar = /\\(\\)?/g;

  /**
   * Used to match
   * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
   */
  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;

  /** Used to match `RegExp` flags from their coerced string values. */
  var reFlags = /\w*$/;

  /** Used to detect bad signed hexadecimal string values. */
  var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

  /** Used to detect binary string values. */
  var reIsBinary = /^0b[01]+$/i;

  /** Used to detect host constructors (Safari). */
  var reIsHostCtor = /^\[object .+?Constructor\]$/;

  /** Used to detect octal string values. */
  var reIsOctal = /^0o[0-7]+$/i;

  /** Used to detect unsigned integer values. */
  var reIsUint = /^(?:0|[1-9]\d*)$/;

  /** Used to match Latin Unicode letters (excluding mathematical operators). */
  var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;

  /** Used to ensure capturing order of template delimiters. */
  var reNoMatch = /($^)/;

  /** Used to match unescaped characters in compiled string literals. */
  var reUnescapedString = /['\n\r\u2028\u2029\\]/g;

  /** Used to compose unicode character classes. */
  var rsAstralRange = '\\ud800-\\udfff',
      rsComboMarksRange = '\\u0300-\\u036f',
      reComboHalfMarksRange = '\\ufe20-\\ufe2f',
      rsComboSymbolsRange = '\\u20d0-\\u20ff',
      rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
      rsDingbatRange = '\\u2700-\\u27bf',
      rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
      rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
      rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
      rsPunctuationRange = '\\u2000-\\u206f',
      rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
      rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
      rsVarRange = '\\ufe0e\\ufe0f',
      rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;

  /** Used to compose unicode capture groups. */
  var rsApos = "['\u2019]",
      rsAstral = '[' + rsAstralRange + ']',
      rsBreak = '[' + rsBreakRange + ']',
      rsCombo = '[' + rsComboRange + ']',
      rsDigits = '\\d+',
      rsDingbat = '[' + rsDingbatRange + ']',
      rsLower = '[' + rsLowerRange + ']',
      rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
      rsFitz = '\\ud83c[\\udffb-\\udfff]',
      rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
      rsNonAstral = '[^' + rsAstralRange + ']',
      rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
      rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
      rsUpper = '[' + rsUpperRange + ']',
      rsZWJ = '\\u200d';

  /** Used to compose unicode regexes. */
  var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
      rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
      rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
      rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
      reOptMod = rsModifier + '?',
      rsOptVar = '[' + rsVarRange + ']?',
      rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
      rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)',
      rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)',
      rsSeq = rsOptVar + reOptMod + rsOptJoin,
      rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
      rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';

  /** Used to match apostrophes. */
  var reApos = RegExp(rsApos, 'g');

  /**
   * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
   * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
   */
  var reComboMark = RegExp(rsCombo, 'g');

  /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
  var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');

  /** Used to match complex or compound words. */
  var reUnicodeWord = RegExp([
    rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
    rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
    rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
    rsUpper + '+' + rsOptContrUpper,
    rsOrdUpper,
    rsOrdLower,
    rsDigits,
    rsEmoji
  ].join('|'), 'g');

  /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
  var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange  + rsComboRange + rsVarRange + ']');

  /** Used to detect strings that need a more robust regexp to match words. */
  var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;

  /** Used to assign default `context` object properties. */
  var contextProps = [
    'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
    'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
    'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
    'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
    '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
  ];

  /** Used to make template sourceURLs easier to identify. */
  var templateCounter = -1;

  /** Used to identify `toStringTag` values of typed arrays. */
  var typedArrayTags = {};
  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
  typedArrayTags[uint32Tag] = true;
  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
  typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
  typedArrayTags[errorTag] = typedArrayTags[funcTag] =
  typedArrayTags[mapTag] = typedArrayTags[numberTag] =
  typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
  typedArrayTags[setTag] = typedArrayTags[stringTag] =
  typedArrayTags[weakMapTag] = false;

  /** Used to identify `toStringTag` values supported by `_.clone`. */
  var cloneableTags = {};
  cloneableTags[argsTag] = cloneableTags[arrayTag] =
  cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
  cloneableTags[boolTag] = cloneableTags[dateTag] =
  cloneableTags[float32Tag] = cloneableTags[float64Tag] =
  cloneableTags[int8Tag] = cloneableTags[int16Tag] =
  cloneableTags[int32Tag] = cloneableTags[mapTag] =
  cloneableTags[numberTag] = cloneableTags[objectTag] =
  cloneableTags[regexpTag] = cloneableTags[setTag] =
  cloneableTags[stringTag] = cloneableTags[symbolTag] =
  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
  cloneableTags[errorTag] = cloneableTags[funcTag] =
  cloneableTags[weakMapTag] = false;

  /** Used to map Latin Unicode letters to basic Latin letters. */
  var deburredLetters = {
    // Latin-1 Supplement block.
    '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
    '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
    '\xc7': 'C',  '\xe7': 'c',
    '\xd0': 'D',  '\xf0': 'd',
    '\xc8': 'E',  '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
    '\xe8': 'e',  '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
    '\xcc': 'I',  '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
    '\xec': 'i',  '\xed': 'i', '\xee': 'i', '\xef': 'i',
    '\xd1': 'N',  '\xf1': 'n',
    '\xd2': 'O',  '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
    '\xf2': 'o',  '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
    '\xd9': 'U',  '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
    '\xf9': 'u',  '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
    '\xdd': 'Y',  '\xfd': 'y', '\xff': 'y',
    '\xc6': 'Ae', '\xe6': 'ae',
    '\xde': 'Th', '\xfe': 'th',
    '\xdf': 'ss',
    // Latin Extended-A block.
    '\u0100': 'A',  '\u0102': 'A', '\u0104': 'A',
    '\u0101': 'a',  '\u0103': 'a', '\u0105': 'a',
    '\u0106': 'C',  '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
    '\u0107': 'c',  '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
    '\u010e': 'D',  '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
    '\u0112': 'E',  '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
    '\u0113': 'e',  '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
    '\u011c': 'G',  '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
    '\u011d': 'g',  '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
    '\u0124': 'H',  '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
    '\u0128': 'I',  '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
    '\u0129': 'i',  '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
    '\u0134': 'J',  '\u0135': 'j',
    '\u0136': 'K',  '\u0137': 'k', '\u0138': 'k',
    '\u0139': 'L',  '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
    '\u013a': 'l',  '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
    '\u0143': 'N',  '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
    '\u0144': 'n',  '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
    '\u014c': 'O',  '\u014e': 'O', '\u0150': 'O',
    '\u014d': 'o',  '\u014f': 'o', '\u0151': 'o',
    '\u0154': 'R',  '\u0156': 'R', '\u0158': 'R',
    '\u0155': 'r',  '\u0157': 'r', '\u0159': 'r',
    '\u015a': 'S',  '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
    '\u015b': 's',  '\u015d': 's', '\u015f': 's', '\u0161': 's',
    '\u0162': 'T',  '\u0164': 'T', '\u0166': 'T',
    '\u0163': 't',  '\u0165': 't', '\u0167': 't',
    '\u0168': 'U',  '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
    '\u0169': 'u',  '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
    '\u0174': 'W',  '\u0175': 'w',
    '\u0176': 'Y',  '\u0177': 'y', '\u0178': 'Y',
    '\u0179': 'Z',  '\u017b': 'Z', '\u017d': 'Z',
    '\u017a': 'z',  '\u017c': 'z', '\u017e': 'z',
    '\u0132': 'IJ', '\u0133': 'ij',
    '\u0152': 'Oe', '\u0153': 'oe',
    '\u0149': "'n", '\u017f': 's'
  };

  /** Used to map characters to HTML entities. */
  var htmlEscapes = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;'
  };

  /** Used to map HTML entities to characters. */
  var htmlUnescapes = {
    '&amp;': '&',
    '&lt;': '<',
    '&gt;': '>',
    '&quot;': '"',
    '&#39;': "'"
  };

  /** Used to escape characters for inclusion in compiled string literals. */
  var stringEscapes = {
    '\\': '\\',
    "'": "'",
    '\n': 'n',
    '\r': 'r',
    '\u2028': 'u2028',
    '\u2029': 'u2029'
  };

  /** Built-in method references without a dependency on `root`. */
  var freeParseFloat = parseFloat,
      freeParseInt = parseInt;

  /** Detect free variable `global` from Node.js. */
  var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

  /** Detect free variable `self`. */
  var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

  /** Used as a reference to the global object. */
  var root = freeGlobal || freeSelf || Function('return this')();

  /** Detect free variable `exports`. */
  var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

  /** Detect free variable `module`. */
  var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

  /** Detect the popular CommonJS extension `module.exports`. */
  var moduleExports = freeModule && freeModule.exports === freeExports;

  /** Detect free variable `process` from Node.js. */
  var freeProcess = moduleExports && freeGlobal.process;

  /** Used to access faster Node.js helpers. */
  var nodeUtil = (function() {
    try {
      return freeProcess && freeProcess.binding && freeProcess.binding('util');
    } catch (e) {}
  }());

  /* Node.js helper references. */
  var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
      nodeIsDate = nodeUtil && nodeUtil.isDate,
      nodeIsMap = nodeUtil && nodeUtil.isMap,
      nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
      nodeIsSet = nodeUtil && nodeUtil.isSet,
      nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

  /*--------------------------------------------------------------------------*/

  /**
   * Adds the key-value `pair` to `map`.
   *
   * @private
   * @param {Object} map The map to modify.
   * @param {Array} pair The key-value pair to add.
   * @returns {Object} Returns `map`.
   */
  function addMapEntry(map, pair) {
    // Don't return `map.set` because it's not chainable in IE 11.
    map.set(pair[0], pair[1]);
    return map;
  }

  /**
   * Adds `value` to `set`.
   *
   * @private
   * @param {Object} set The set to modify.
   * @param {*} value The value to add.
   * @returns {Object} Returns `set`.
   */
  function addSetEntry(set, value) {
    // Don't return `set.add` because it's not chainable in IE 11.
    set.add(value);
    return set;
  }

  /**
   * A faster alternative to `Function#apply`, this function invokes `func`
   * with the `this` binding of `thisArg` and the arguments of `args`.
   *
   * @private
   * @param {Function} func The function to invoke.
   * @param {*} thisArg The `this` binding of `func`.
   * @param {Array} args The arguments to invoke `func` with.
   * @returns {*} Returns the result of `func`.
   */
  function apply(func, thisArg, args) {
    switch (args.length) {
      case 0: return func.call(thisArg);
      case 1: return func.call(thisArg, args[0]);
      case 2: return func.call(thisArg, args[0], args[1]);
      case 3: return func.call(thisArg, args[0], args[1], args[2]);
    }
    return func.apply(thisArg, args);
  }

  /**
   * A specialized version of `baseAggregator` for arrays.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} setter The function to set `accumulator` values.
   * @param {Function} iteratee The iteratee to transform keys.
   * @param {Object} accumulator The initial aggregated object.
   * @returns {Function} Returns `accumulator`.
   */
  function arrayAggregator(array, setter, iteratee, accumulator) {
    var index = -1,
        length = array == null ? 0 : array.length;

    while (++index < length) {
      var value = array[index];
      setter(accumulator, value, iteratee(value), array);
    }
    return accumulator;
  }

  /**
   * A specialized version of `_.forEach` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns `array`.
   */
  function arrayEach(array, iteratee) {
    var index = -1,
        length = array == null ? 0 : array.length;

    while (++index < length) {
      if (iteratee(array[index], index, array) === false) {
        break;
      }
    }
    return array;
  }

  /**
   * A specialized version of `_.forEachRight` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns `array`.
   */
  function arrayEachRight(array, iteratee) {
    var length = array == null ? 0 : array.length;

    while (length--) {
      if (iteratee(array[length], length, array) === false) {
        break;
      }
    }
    return array;
  }

  /**
   * A specialized version of `_.every` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {boolean} Returns `true` if all elements pass the predicate check,
   *  else `false`.
   */
  function arrayEvery(array, predicate) {
    var index = -1,
        length = array == null ? 0 : array.length;

    while (++index < length) {
      if (!predicate(array[index], index, array)) {
        return false;
      }
    }
    return true;
  }

  /**
   * A specialized version of `_.filter` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {Array} Returns the new filtered array.
   */
  function arrayFilter(array, predicate) {
    var index = -1,
        length = array == null ? 0 : array.length,
        resIndex = 0,
        result = [];

    while (++index < length) {
      var value = array[index];
      if (predicate(value, index, array)) {
        result[resIndex++] = value;
      }
    }
    return result;
  }

  /**
   * A specialized version of `_.includes` for arrays without support for
   * specifying an index to search from.
   *
   * @private
   * @param {Array} [array] The array to inspect.
   * @param {*} target The value to search for.
   * @returns {boolean} Returns `true` if `target` is found, else `false`.
   */
  function arrayIncludes(array, value) {
    var length = array == null ? 0 : array.length;
    return !!length && baseIndexOf(array, value, 0) > -1;
  }

  /**
   * This function is like `arrayIncludes` except that it accepts a comparator.
   *
   * @private
   * @param {Array} [array] The array to inspect.
   * @param {*} target The value to search for.
   * @param {Function} comparator The comparator invoked per element.
   * @returns {boolean} Returns `true` if `target` is found, else `false`.
   */
  function arrayIncludesWith(array, value, comparator) {
    var index = -1,
        length = array == null ? 0 : array.length;

    while (++index < length) {
      if (comparator(value, array[index])) {
        return true;
      }
    }
    return false;
  }

  /**
   * A specialized version of `_.map` for arrays without support for iteratee
   * shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns the new mapped array.
   */
  function arrayMap(array, iteratee) {
    var index = -1,
        length = array == null ? 0 : array.length,
        result = Array(length);

    while (++index < length) {
      result[index] = iteratee(array[index], index, array);
    }
    return result;
  }

  /**
   * Appends the elements of `values` to `array`.
   *
   * @private
   * @param {Array} array The array to modify.
   * @param {Array} values The values to append.
   * @returns {Array} Returns `array`.
   */
  function arrayPush(array, values) {
    var index = -1,
        length = values.length,
        offset = array.length;

    while (++index < length) {
      array[offset + index] = values[index];
    }
    return array;
  }

  /**
   * A specialized version of `_.reduce` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {*} [accumulator] The initial value.
   * @param {boolean} [initAccum] Specify using the first element of `array` as
   *  the initial value.
   * @returns {*} Returns the accumulated value.
   */
  function arrayReduce(array, iteratee, accumulator, initAccum) {
    var index = -1,
        length = array == null ? 0 : array.length;

    if (initAccum && length) {
      accumulator = array[++index];
    }
    while (++index < length) {
      accumulator = iteratee(accumulator, array[index], index, array);
    }
    return accumulator;
  }

  /**
   * A specialized version of `_.reduceRight` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {*} [accumulator] The initial value.
   * @param {boolean} [initAccum] Specify using the last element of `array` as
   *  the initial value.
   * @returns {*} Returns the accumulated value.
   */
  function arrayReduceRight(array, iteratee, accumulator, initAccum) {
    var length = array == null ? 0 : array.length;
    if (initAccum && length) {
      accumulator = array[--length];
    }
    while (length--) {
      accumulator = iteratee(accumulator, array[length], length, array);
    }
    return accumulator;
  }

  /**
   * A specialized version of `_.some` for arrays without support for iteratee
   * shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {boolean} Returns `true` if any element passes the predicate check,
   *  else `false`.
   */
  function arraySome(array, predicate) {
    var index = -1,
        length = array == null ? 0 : array.length;

    while (++index < length) {
      if (predicate(array[index], index, array)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Gets the size of an ASCII `string`.
   *
   * @private
   * @param {string} string The string inspect.
   * @returns {number} Returns the string size.
   */
  var asciiSize = baseProperty('length');

  /**
   * Converts an ASCII `string` to an array.
   *
   * @private
   * @param {string} string The string to convert.
   * @returns {Array} Returns the converted array.
   */
  function asciiToArray(string) {
    return string.split('');
  }

  /**
   * Splits an ASCII `string` into an array of its words.
   *
   * @private
   * @param {string} The string to inspect.
   * @returns {Array} Returns the words of `string`.
   */
  function asciiWords(string) {
    return string.match(reAsciiWord) || [];
  }

  /**
   * The base implementation of methods like `_.findKey` and `_.findLastKey`,
   * without support for iteratee shorthands, which iterates over `collection`
   * using `eachFunc`.
   *
   * @private
   * @param {Array|Object} collection The collection to inspect.
   * @param {Function} predicate The function invoked per iteration.
   * @param {Function} eachFunc The function to iterate over `collection`.
   * @returns {*} Returns the found element or its key, else `undefined`.
   */
  function baseFindKey(collection, predicate, eachFunc) {
    var result;
    eachFunc(collection, function(value, key, collection) {
      if (predicate(value, key, collection)) {
        result = key;
        return false;
      }
    });
    return result;
  }

  /**
   * The base implementation of `_.findIndex` and `_.findLastIndex` without
   * support for iteratee shorthands.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {Function} predicate The function invoked per iteration.
   * @param {number} fromIndex The index to search from.
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function baseFindIndex(array, predicate, fromIndex, fromRight) {
    var length = array.length,
        index = fromIndex + (fromRight ? 1 : -1);

    while ((fromRight ? index-- : ++index < length)) {
      if (predicate(array[index], index, array)) {
        return index;
      }
    }
    return -1;
  }

  /**
   * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} value The value to search for.
   * @param {number} fromIndex The index to search from.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function baseIndexOf(array, value, fromIndex) {
    return value === value
      ? strictIndexOf(array, value, fromIndex)
      : baseFindIndex(array, baseIsNaN, fromIndex);
  }

  /**
   * This function is like `baseIndexOf` except that it accepts a comparator.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} value The value to search for.
   * @param {number} fromIndex The index to search from.
   * @param {Function} comparator The comparator invoked per element.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function baseIndexOfWith(array, value, fromIndex, comparator) {
    var index = fromIndex - 1,
        length = array.length;

    while (++index < length) {
      if (comparator(array[index], value)) {
        return index;
      }
    }
    return -1;
  }

  /**
   * The base implementation of `_.isNaN` without support for number objects.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
   */
  function baseIsNaN(value) {
    return value !== value;
  }

  /**
   * The base implementation of `_.mean` and `_.meanBy` without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} array The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {number} Returns the mean.
   */
  function baseMean(array, iteratee) {
    var length = array == null ? 0 : array.length;
    return length ? (baseSum(array, iteratee) / length) : NAN;
  }

  /**
   * The base implementation of `_.property` without support for deep paths.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @returns {Function} Returns the new accessor function.
   */
  function baseProperty(key) {
    return function(object) {
      return object == null ? undefined : object[key];
    };
  }

  /**
   * The base implementation of `_.propertyOf` without support for deep paths.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Function} Returns the new accessor function.
   */
  function basePropertyOf(object) {
    return function(key) {
      return object == null ? undefined : object[key];
    };
  }

  /**
   * The base implementation of `_.reduce` and `_.reduceRight`, without support
   * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
   *
   * @private
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {*} accumulator The initial value.
   * @param {boolean} initAccum Specify using the first or last element of
   *  `collection` as the initial value.
   * @param {Function} eachFunc The function to iterate over `collection`.
   * @returns {*} Returns the accumulated value.
   */
  function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
    eachFunc(collection, function(value, index, collection) {
      accumulator = initAccum
        ? (initAccum = false, value)
        : iteratee(accumulator, value, index, collection);
    });
    return accumulator;
  }

  /**
   * The base implementation of `_.sortBy` which uses `comparer` to define the
   * sort order of `array` and replaces criteria objects with their corresponding
   * values.
   *
   * @private
   * @param {Array} array The array to sort.
   * @param {Function} comparer The function to define sort order.
   * @returns {Array} Returns `array`.
   */
  function baseSortBy(array, comparer) {
    var length = array.length;

    array.sort(comparer);
    while (length--) {
      array[length] = array[length].value;
    }
    return array;
  }

  /**
   * The base implementation of `_.sum` and `_.sumBy` without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} array The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {number} Returns the sum.
   */
  function baseSum(array, iteratee) {
    var result,
        index = -1,
        length = array.length;

    while (++index < length) {
      var current = iteratee(array[index]);
      if (current !== undefined) {
        result = result === undefined ? current : (result + current);
      }
    }
    return result;
  }

  /**
   * The base implementation of `_.times` without support for iteratee shorthands
   * or max array length checks.
   *
   * @private
   * @param {number} n The number of times to invoke `iteratee`.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns the array of results.
   */
  function baseTimes(n, iteratee) {
    var index = -1,
        result = Array(n);

    while (++index < n) {
      result[index] = iteratee(index);
    }
    return result;
  }

  /**
   * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
   * of key-value pairs for `object` corresponding to the property names of `props`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Array} props The property names to get values for.
   * @returns {Object} Returns the key-value pairs.
   */
  function baseToPairs(object, props) {
    return arrayMap(props, function(key) {
      return [key, object[key]];
    });
  }

  /**
   * The base implementation of `_.unary` without support for storing metadata.
   *
   * @private
   * @param {Function} func The function to cap arguments for.
   * @returns {Function} Returns the new capped function.
   */
  function baseUnary(func) {
    return function(value) {
      return func(value);
    };
  }

  /**
   * The base implementation of `_.values` and `_.valuesIn` which creates an
   * array of `object` property values corresponding to the property names
   * of `props`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Array} props The property names to get values for.
   * @returns {Object} Returns the array of property values.
   */
  function baseValues(object, props) {
    return arrayMap(props, function(key) {
      return object[key];
    });
  }

  /**
   * Checks if a `cache` value for `key` exists.
   *
   * @private
   * @param {Object} cache The cache to query.
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function cacheHas(cache, key) {
    return cache.has(key);
  }

  /**
   * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
   * that is not found in the character symbols.
   *
   * @private
   * @param {Array} strSymbols The string symbols to inspect.
   * @param {Array} chrSymbols The character symbols to find.
   * @returns {number} Returns the index of the first unmatched string symbol.
   */
  function charsStartIndex(strSymbols, chrSymbols) {
    var index = -1,
        length = strSymbols.length;

    while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
    return index;
  }

  /**
   * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
   * that is not found in the character symbols.
   *
   * @private
   * @param {Array} strSymbols The string symbols to inspect.
   * @param {Array} chrSymbols The character symbols to find.
   * @returns {number} Returns the index of the last unmatched string symbol.
   */
  function charsEndIndex(strSymbols, chrSymbols) {
    var index = strSymbols.length;

    while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
    return index;
  }

  /**
   * Gets the number of `placeholder` occurrences in `array`.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} placeholder The placeholder to search for.
   * @returns {number} Returns the placeholder count.
   */
  function countHolders(array, placeholder) {
    var length = array.length,
        result = 0;

    while (length--) {
      if (array[length] === placeholder) {
        ++result;
      }
    }
    return result;
  }

  /**
   * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
   * letters to basic Latin letters.
   *
   * @private
   * @param {string} letter The matched letter to deburr.
   * @returns {string} Returns the deburred letter.
   */
  var deburrLetter = basePropertyOf(deburredLetters);

  /**
   * Used by `_.escape` to convert characters to HTML entities.
   *
   * @private
   * @param {string} chr The matched character to escape.
   * @returns {string} Returns the escaped character.
   */
  var escapeHtmlChar = basePropertyOf(htmlEscapes);

  /**
   * Used by `_.template` to escape characters for inclusion in compiled string literals.
   *
   * @private
   * @param {string} chr The matched character to escape.
   * @returns {string} Returns the escaped character.
   */
  function escapeStringChar(chr) {
    return '\\' + stringEscapes[chr];
  }

  /**
   * Gets the value at `key` of `object`.
   *
   * @private
   * @param {Object} [object] The object to query.
   * @param {string} key The key of the property to get.
   * @returns {*} Returns the property value.
   */
  function getValue(object, key) {
    return object == null ? undefined : object[key];
  }

  /**
   * Checks if `string` contains Unicode symbols.
   *
   * @private
   * @param {string} string The string to inspect.
   * @returns {boolean} Returns `true` if a symbol is found, else `false`.
   */
  function hasUnicode(string) {
    return reHasUnicode.test(string);
  }

  /**
   * Checks if `string` contains a word composed of Unicode symbols.
   *
   * @private
   * @param {string} string The string to inspect.
   * @returns {boolean} Returns `true` if a word is found, else `false`.
   */
  function hasUnicodeWord(string) {
    return reHasUnicodeWord.test(string);
  }

  /**
   * Converts `iterator` to an array.
   *
   * @private
   * @param {Object} iterator The iterator to convert.
   * @returns {Array} Returns the converted array.
   */
  function iteratorToArray(iterator) {
    var data,
        result = [];

    while (!(data = iterator.next()).done) {
      result.push(data.value);
    }
    return result;
  }

  /**
   * Converts `map` to its key-value pairs.
   *
   * @private
   * @param {Object} map The map to convert.
   * @returns {Array} Returns the key-value pairs.
   */
  function mapToArray(map) {
    var index = -1,
        result = Array(map.size);

    map.forEach(function(value, key) {
      result[++index] = [key, value];
    });
    return result;
  }

  /**
   * Creates a unary function that invokes `func` with its argument transformed.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {Function} transform The argument transform.
   * @returns {Function} Returns the new function.
   */
  function overArg(func, transform) {
    return function(arg) {
      return func(transform(arg));
    };
  }

  /**
   * Replaces all `placeholder` elements in `array` with an internal placeholder
   * and returns an array of their indexes.
   *
   * @private
   * @param {Array} array The array to modify.
   * @param {*} placeholder The placeholder to replace.
   * @returns {Array} Returns the new array of placeholder indexes.
   */
  function replaceHolders(array, placeholder) {
    var index = -1,
        length = array.length,
        resIndex = 0,
        result = [];

    while (++index < length) {
      var value = array[index];
      if (value === placeholder || value === PLACEHOLDER) {
        array[index] = PLACEHOLDER;
        result[resIndex++] = index;
      }
    }
    return result;
  }

  /**
   * Converts `set` to an array of its values.
   *
   * @private
   * @param {Object} set The set to convert.
   * @returns {Array} Returns the values.
   */
  function setToArray(set) {
    var index = -1,
        result = Array(set.size);

    set.forEach(function(value) {
      result[++index] = value;
    });
    return result;
  }

  /**
   * Converts `set` to its value-value pairs.
   *
   * @private
   * @param {Object} set The set to convert.
   * @returns {Array} Returns the value-value pairs.
   */
  function setToPairs(set) {
    var index = -1,
        result = Array(set.size);

    set.forEach(function(value) {
      result[++index] = [value, value];
    });
    return result;
  }

  /**
   * A specialized version of `_.indexOf` which performs strict equality
   * comparisons of values, i.e. `===`.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} value The value to search for.
   * @param {number} fromIndex The index to search from.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function strictIndexOf(array, value, fromIndex) {
    var index = fromIndex - 1,
        length = array.length;

    while (++index < length) {
      if (array[index] === value) {
        return index;
      }
    }
    return -1;
  }

  /**
   * A specialized version of `_.lastIndexOf` which performs strict equality
   * comparisons of values, i.e. `===`.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} value The value to search for.
   * @param {number} fromIndex The index to search from.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function strictLastIndexOf(array, value, fromIndex) {
    var index = fromIndex + 1;
    while (index--) {
      if (array[index] === value) {
        return index;
      }
    }
    return index;
  }

  /**
   * Gets the number of symbols in `string`.
   *
   * @private
   * @param {string} string The string to inspect.
   * @returns {number} Returns the string size.
   */
  function stringSize(string) {
    return hasUnicode(string)
      ? unicodeSize(string)
      : asciiSize(string);
  }

  /**
   * Converts `string` to an array.
   *
   * @private
   * @param {string} string The string to convert.
   * @returns {Array} Returns the converted array.
   */
  function stringToArray(string) {
    return hasUnicode(string)
      ? unicodeToArray(string)
      : asciiToArray(string);
  }

  /**
   * Used by `_.unescape` to convert HTML entities to characters.
   *
   * @private
   * @param {string} chr The matched character to unescape.
   * @returns {string} Returns the unescaped character.
   */
  var unescapeHtmlChar = basePropertyOf(htmlUnescapes);

  /**
   * Gets the size of a Unicode `string`.
   *
   * @private
   * @param {string} string The string inspect.
   * @returns {number} Returns the string size.
   */
  function unicodeSize(string) {
    var result = reUnicode.lastIndex = 0;
    while (reUnicode.test(string)) {
      ++result;
    }
    return result;
  }

  /**
   * Converts a Unicode `string` to an array.
   *
   * @private
   * @param {string} string The string to convert.
   * @returns {Array} Returns the converted array.
   */
  function unicodeToArray(string) {
    return string.match(reUnicode) || [];
  }

  /**
   * Splits a Unicode `string` into an array of its words.
   *
   * @private
   * @param {string} The string to inspect.
   * @returns {Array} Returns the words of `string`.
   */
  function unicodeWords(string) {
    return string.match(reUnicodeWord) || [];
  }

  /*--------------------------------------------------------------------------*/

  /**
   * Create a new pristine `lodash` function using the `context` object.
   *
   * @static
   * @memberOf _
   * @since 1.1.0
   * @category Util
   * @param {Object} [context=root] The context object.
   * @returns {Function} Returns a new `lodash` function.
   * @example
   *
   * _.mixin({ 'foo': _.constant('foo') });
   *
   * var lodash = _.runInContext();
   * lodash.mixin({ 'bar': lodash.constant('bar') });
   *
   * _.isFunction(_.foo);
   * // => true
   * _.isFunction(_.bar);
   * // => false
   *
   * lodash.isFunction(lodash.foo);
   * // => false
   * lodash.isFunction(lodash.bar);
   * // => true
   *
   * // Create a suped-up `defer` in Node.js.
   * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
   */
  var runInContext = (function runInContext(context) {
    context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));

    /** Built-in constructor references. */
    var Array = context.Array,
        Date = context.Date,
        Error = context.Error,
        Function = context.Function,
        Math = context.Math,
        Object = context.Object,
        RegExp = context.RegExp,
        String = context.String,
        TypeError = context.TypeError;

    /** Used for built-in method references. */
    var arrayProto = Array.prototype,
        funcProto = Function.prototype,
        objectProto = Object.prototype;

    /** Used to detect overreaching core-js shims. */
    var coreJsData = context['__core-js_shared__'];

    /** Used to resolve the decompiled source of functions. */
    var funcToString = funcProto.toString;

    /** Used to check objects for own properties. */
    var hasOwnProperty = objectProto.hasOwnProperty;

    /** Used to generate unique IDs. */
    var idCounter = 0;

    /** Used to detect methods masquerading as native. */
    var maskSrcKey = (function() {
      var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
      return uid ? ('Symbol(src)_1.' + uid) : '';
    }());

    /**
     * Used to resolve the
     * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
     * of values.
     */
    var nativeObjectToString = objectProto.toString;

    /** Used to infer the `Object` constructor. */
    var objectCtorString = funcToString.call(Object);

    /** Used to restore the original `_` reference in `_.noConflict`. */
    var oldDash = root._;

    /** Used to detect if a method is native. */
    var reIsNative = RegExp('^' +
      funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
      .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
    );

    /** Built-in value references. */
    var Buffer = moduleExports ? context.Buffer : undefined,
        Symbol = context.Symbol,
        Uint8Array = context.Uint8Array,
        allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
        getPrototype = overArg(Object.getPrototypeOf, Object),
        objectCreate = Object.create,
        propertyIsEnumerable = objectProto.propertyIsEnumerable,
        splice = arrayProto.splice,
        spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
        symIterator = Symbol ? Symbol.iterator : undefined,
        symToStringTag = Symbol ? Symbol.toStringTag : undefined;

    var defineProperty = (function() {
      try {
        var func = getNative(Object, 'defineProperty');
        func({}, '', {});
        return func;
      } catch (e) {}
    }());

    /** Mocked built-ins. */
    var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
        ctxNow = Date && Date.now !== root.Date.now && Date.now,
        ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;

    /* Built-in method references for those with the same name as other `lodash` methods. */
    var nativeCeil = Math.ceil,
        nativeFloor = Math.floor,
        nativeGetSymbols = Object.getOwnPropertySymbols,
        nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
        nativeIsFinite = context.isFinite,
        nativeJoin = arrayProto.join,
        nativeKeys = overArg(Object.keys, Object),
        nativeMax = Math.max,
        nativeMin = Math.min,
        nativeNow = Date.now,
        nativeParseInt = context.parseInt,
        nativeRandom = Math.random,
        nativeReverse = arrayProto.reverse;

    /* Built-in method references that are verified to be native. */
    var DataView = getNative(context, 'DataView'),
        Map = getNative(context, 'Map'),
        Promise = getNative(context, 'Promise'),
        Set = getNative(context, 'Set'),
        WeakMap = getNative(context, 'WeakMap'),
        nativeCreate = getNative(Object, 'create');

    /** Used to store function metadata. */
    var metaMap = WeakMap && new WeakMap;

    /** Used to lookup unminified function names. */
    var realNames = {};

    /** Used to detect maps, sets, and weakmaps. */
    var dataViewCtorString = toSource(DataView),
        mapCtorString = toSource(Map),
        promiseCtorString = toSource(Promise),
        setCtorString = toSource(Set),
        weakMapCtorString = toSource(WeakMap);

    /** Used to convert symbols to primitives and strings. */
    var symbolProto = Symbol ? Symbol.prototype : undefined,
        symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
        symbolToString = symbolProto ? symbolProto.toString : undefined;

    /*------------------------------------------------------------------------*/

    /**
     * Creates a `lodash` object which wraps `value` to enable implicit method
     * chain sequences. Methods that operate on and return arrays, collections,
     * and functions can be chained together. Methods that retrieve a single value
     * or may return a primitive value will automatically end the chain sequence
     * and return the unwrapped value. Otherwise, the value must be unwrapped
     * with `_#value`.
     *
     * Explicit chain sequences, which must be unwrapped with `_#value`, may be
     * enabled using `_.chain`.
     *
     * The execution of chained methods is lazy, that is, it's deferred until
     * `_#value` is implicitly or explicitly called.
     *
     * Lazy evaluation allows several methods to support shortcut fusion.
     * Shortcut fusion is an optimization to merge iteratee calls; this avoids
     * the creation of intermediate arrays and can greatly reduce the number of
     * iteratee executions. Sections of a chain sequence qualify for shortcut
     * fusion if the section is applied to an array and iteratees accept only
     * one argument. The heuristic for whether a section qualifies for shortcut
     * fusion is subject to change.
     *
     * Chaining is supported in custom builds as long as the `_#value` method is
     * directly or indirectly included in the build.
     *
     * In addition to lodash methods, wrappers have `Array` and `String` methods.
     *
     * The wrapper `Array` methods are:
     * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
     *
     * The wrapper `String` methods are:
     * `replace` and `split`
     *
     * The wrapper methods that support shortcut fusion are:
     * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
     * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
     * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
     *
     * The chainable wrapper methods are:
     * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
     * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
     * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
     * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
     * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
     * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
     * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
     * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
     * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
     * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
     * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
     * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
     * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
     * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
     * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
     * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
     * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
     * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
     * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
     * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
     * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
     * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
     * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
     * `zipObject`, `zipObjectDeep`, and `zipWith`
     *
     * The wrapper methods that are **not** chainable by default are:
     * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
     * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
     * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
     * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
     * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
     * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
     * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
     * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
     * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
     * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
     * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
     * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
     * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
     * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
     * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
     * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
     * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
     * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
     * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
     * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
     * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
     * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
     * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
     * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
     * `upperFirst`, `value`, and `words`
     *
     * @name _
     * @constructor
     * @category Seq
     * @param {*} value The value to wrap in a `lodash` instance.
     * @returns {Object} Returns the new `lodash` wrapper instance.
     * @example
     *
     * function square(n) {
     *   return n * n;
     * }
     *
     * var wrapped = _([1, 2, 3]);
     *
     * // Returns an unwrapped value.
     * wrapped.reduce(_.add);
     * // => 6
     *
     * // Returns a wrapped value.
     * var squares = wrapped.map(square);
     *
     * _.isArray(squares);
     * // => false
     *
     * _.isArray(squares.value());
     * // => true
     */
    function lodash(value) {
      if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
        if (value instanceof LodashWrapper) {
          return value;
        }
        if (hasOwnProperty.call(value, '__wrapped__')) {
          return wrapperClone(value);
        }
      }
      return new LodashWrapper(value);
    }

    /**
     * The base implementation of `_.create` without support for assigning
     * properties to the created object.
     *
     * @private
     * @param {Object} proto The object to inherit from.
     * @returns {Object} Returns the new object.
     */
    var baseCreate = (function() {
      function object() {}
      return function(proto) {
        if (!isObject(proto)) {
          return {};
        }
        if (objectCreate) {
          return objectCreate(proto);
        }
        object.prototype = proto;
        var result = new object;
        object.prototype = undefined;
        return result;
      };
    }());

    /**
     * The function whose prototype chain sequence wrappers inherit from.
     *
     * @private
     */
    function baseLodash() {
      // No operation performed.
    }

    /**
     * The base constructor for creating `lodash` wrapper objects.
     *
     * @private
     * @param {*} value The value to wrap.
     * @param {boolean} [chainAll] Enable explicit method chain sequences.
     */
    function LodashWrapper(value, chainAll) {
      this.__wrapped__ = value;
      this.__actions__ = [];
      this.__chain__ = !!chainAll;
      this.__index__ = 0;
      this.__values__ = undefined;
    }

    /**
     * By default, the template delimiters used by lodash are like those in
     * embedded Ruby (ERB) as well as ES2015 template strings. Change the
     * following template settings to use alternative delimiters.
     *
     * @static
     * @memberOf _
     * @type {Object}
     */
    lodash.templateSettings = {

      /**
       * Used to detect `data` property values to be HTML-escaped.
       *
       * @memberOf _.templateSettings
       * @type {RegExp}
       */
      'escape': reEscape,

      /**
       * Used to detect code to be evaluated.
       *
       * @memberOf _.templateSettings
       * @type {RegExp}
       */
      'evaluate': reEvaluate,

      /**
       * Used to detect `data` property values to inject.
       *
       * @memberOf _.templateSettings
       * @type {RegExp}
       */
      'interpolate': reInterpolate,

      /**
       * Used to reference the data object in the template text.
       *
       * @memberOf _.templateSettings
       * @type {string}
       */
      'variable': '',

      /**
       * Used to import variables into the compiled template.
       *
       * @memberOf _.templateSettings
       * @type {Object}
       */
      'imports': {

        /**
         * A reference to the `lodash` function.
         *
         * @memberOf _.templateSettings.imports
         * @type {Function}
         */
        '_': lodash
      }
    };

    // Ensure wrappers are instances of `baseLodash`.
    lodash.prototype = baseLodash.prototype;
    lodash.prototype.constructor = lodash;

    LodashWrapper.prototype = baseCreate(baseLodash.prototype);
    LodashWrapper.prototype.constructor = LodashWrapper;

    /*------------------------------------------------------------------------*/

    /**
     * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
     *
     * @private
     * @constructor
     * @param {*} value The value to wrap.
     */
    function LazyWrapper(value) {
      this.__wrapped__ = value;
      this.__actions__ = [];
      this.__dir__ = 1;
      this.__filtered__ = false;
      this.__iteratees__ = [];
      this.__takeCount__ = MAX_ARRAY_LENGTH;
      this.__views__ = [];
    }

    /**
     * Creates a clone of the lazy wrapper object.
     *
     * @private
     * @name clone
     * @memberOf LazyWrapper
     * @returns {Object} Returns the cloned `LazyWrapper` object.
     */
    function lazyClone() {
      var result = new LazyWrapper(this.__wrapped__);
      result.__actions__ = copyArray(this.__actions__);
      result.__dir__ = this.__dir__;
      result.__filtered__ = this.__filtered__;
      result.__iteratees__ = copyArray(this.__iteratees__);
      result.__takeCount__ = this.__takeCount__;
      result.__views__ = copyArray(this.__views__);
      return result;
    }

    /**
     * Reverses the direction of lazy iteration.
     *
     * @private
     * @name reverse
     * @memberOf LazyWrapper
     * @returns {Object} Returns the new reversed `LazyWrapper` object.
     */
    function lazyReverse() {
      if (this.__filtered__) {
        var result = new LazyWrapper(this);
        result.__dir__ = -1;
        result.__filtered__ = true;
      } else {
        result = this.clone();
        result.__dir__ *= -1;
      }
      return result;
    }

    /**
     * Extracts the unwrapped value from its lazy wrapper.
     *
     * @private
     * @name value
     * @memberOf LazyWrapper
     * @returns {*} Returns the unwrapped value.
     */
    function lazyValue() {
      var array = this.__wrapped__.value(),
          dir = this.__dir__,
          isArr = isArray(array),
          isRight = dir < 0,
          arrLength = isArr ? array.length : 0,
          view = getView(0, arrLength, this.__views__),
          start = view.start,
          end = view.end,
          length = end - start,
          index = isRight ? end : (start - 1),
          iteratees = this.__iteratees__,
          iterLength = iteratees.length,
          resIndex = 0,
          takeCount = nativeMin(length, this.__takeCount__);

      if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
        return baseWrapperValue(array, this.__actions__);
      }
      var result = [];

      outer:
      while (length-- && resIndex < takeCount) {
        index += dir;

        var iterIndex = -1,
            value = array[index];

        while (++iterIndex < iterLength) {
          var data = iteratees[iterIndex],
              iteratee = data.iteratee,
              type = data.type,
              computed = iteratee(value);

          if (type == LAZY_MAP_FLAG) {
            value = computed;
          } else if (!computed) {
            if (type == LAZY_FILTER_FLAG) {
              continue outer;
            } else {
              break outer;
            }
          }
        }
        result[resIndex++] = value;
      }
      return result;
    }

    // Ensure `LazyWrapper` is an instance of `baseLodash`.
    LazyWrapper.prototype = baseCreate(baseLodash.prototype);
    LazyWrapper.prototype.constructor = LazyWrapper;

    /*------------------------------------------------------------------------*/

    /**
     * Creates a hash object.
     *
     * @private
     * @constructor
     * @param {Array} [entries] The key-value pairs to cache.
     */
    function Hash(entries) {
      var index = -1,
          length = entries == null ? 0 : entries.length;

      this.clear();
      while (++index < length) {
        var entry = entries[index];
        this.set(entry[0], entry[1]);
      }
    }

    /**
     * Removes all key-value entries from the hash.
     *
     * @private
     * @name clear
     * @memberOf Hash
     */
    function hashClear() {
      this.__data__ = nativeCreate ? nativeCreate(null) : {};
      this.size = 0;
    }

    /**
     * Removes `key` and its value from the hash.
     *
     * @private
     * @name delete
     * @memberOf Hash
     * @param {Object} hash The hash to modify.
     * @param {string} key The key of the value to remove.
     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
     */
    function hashDelete(key) {
      var result = this.has(key) && delete this.__data__[key];
      this.size -= result ? 1 : 0;
      return result;
    }

    /**
     * Gets the hash value for `key`.
     *
     * @private
     * @name get
     * @memberOf Hash
     * @param {string} key The key of the value to get.
     * @returns {*} Returns the entry value.
     */
    function hashGet(key) {
      var data = this.__data__;
      if (nativeCreate) {
        var result = data[key];
        return result === HASH_UNDEFINED ? undefined : result;
      }
      return hasOwnProperty.call(data, key) ? data[key] : undefined;
    }

    /**
     * Checks if a hash value for `key` exists.
     *
     * @private
     * @name has
     * @memberOf Hash
     * @param {string} key The key of the entry to check.
     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
     */
    function hashHas(key) {
      var data = this.__data__;
      return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
    }

    /**
     * Sets the hash `key` to `value`.
     *
     * @private
     * @name set
     * @memberOf Hash
     * @param {string} key The key of the value to set.
     * @param {*} value The value to set.
     * @returns {Object} Returns the hash instance.
     */
    function hashSet(key, value) {
      var data = this.__data__;
      this.size += this.has(key) ? 0 : 1;
      data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
      return this;
    }

    // Add methods to `Hash`.
    Hash.prototype.clear = hashClear;
    Hash.prototype['delete'] = hashDelete;
    Hash.prototype.get = hashGet;
    Hash.prototype.has = hashHas;
    Hash.prototype.set = hashSet;

    /*------------------------------------------------------------------------*/

    /**
     * Creates an list cache object.
     *
     * @private
     * @constructor
     * @param {Array} [entries] The key-value pairs to cache.
     */
    function ListCache(entries) {
      var index = -1,
          length = entries == null ? 0 : entries.length;

      this.clear();
      while (++index < length) {
        var entry = entries[index];
        this.set(entry[0], entry[1]);
      }
    }

    /**
     * Removes all key-value entries from the list cache.
     *
     * @private
     * @name clear
     * @memberOf ListCache
     */
    function listCacheClear() {
      this.__data__ = [];
      this.size = 0;
    }

    /**
     * Removes `key` and its value from the list cache.
     *
     * @private
     * @name delete
     * @memberOf ListCache
     * @param {string} key The key of the value to remove.
     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
     */
    function listCacheDelete(key) {
      var data = this.__data__,
          index = assocIndexOf(data, key);

      if (index < 0) {
        return false;
      }
      var lastIndex = data.length - 1;
      if (index == lastIndex) {
        data.pop();
      } else {
        splice.call(data, index, 1);
      }
      --this.size;
      return true;
    }

    /**
     * Gets the list cache value for `key`.
     *
     * @private
     * @name get
     * @memberOf ListCache
     * @param {string} key The key of the value to get.
     * @returns {*} Returns the entry value.
     */
    function listCacheGet(key) {
      var data = this.__data__,
          index = assocIndexOf(data, key);

      return index < 0 ? undefined : data[index][1];
    }

    /**
     * Checks if a list cache value for `key` exists.
     *
     * @private
     * @name has
     * @memberOf ListCache
     * @param {string} key The key of the entry to check.
     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
     */
    function listCacheHas(key) {
      return assocIndexOf(this.__data__, key) > -1;
    }

    /**
     * Sets the list cache `key` to `value`.
     *
     * @private
     * @name set
     * @memberOf ListCache
     * @param {string} key The key of the value to set.
     * @param {*} value The value to set.
     * @returns {Object} Returns the list cache instance.
     */
    function listCacheSet(key, value) {
      var data = this.__data__,
          index = assocIndexOf(data, key);

      if (index < 0) {
        ++this.size;
        data.push([key, value]);
      } else {
        data[index][1] = value;
      }
      return this;
    }

    // Add methods to `ListCache`.
    ListCache.prototype.clear = listCacheClear;
    ListCache.prototype['delete'] = listCacheDelete;
    ListCache.prototype.get = listCacheGet;
    ListCache.prototype.has = listCacheHas;
    ListCache.prototype.set = listCacheSet;

    /*------------------------------------------------------------------------*/

    /**
     * Creates a map cache object to store key-value pairs.
     *
     * @private
     * @constructor
     * @param {Array} [entries] The key-value pairs to cache.
     */
    function MapCache(entries) {
      var index = -1,
          length = entries == null ? 0 : entries.length;

      this.clear();
      while (++index < length) {
        var entry = entries[index];
        this.set(entry[0], entry[1]);
      }
    }

    /**
     * Removes all key-value entries from the map.
     *
     * @private
     * @name clear
     * @memberOf MapCache
     */
    function mapCacheClear() {
      this.size = 0;
      this.__data__ = {
        'hash': new Hash,
        'map': new (Map || ListCache),
        'string': new Hash
      };
    }

    /**
     * Removes `key` and its value from the map.
     *
     * @private
     * @name delete
     * @memberOf MapCache
     * @param {string} key The key of the value to remove.
     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
     */
    function mapCacheDelete(key) {
      var result = getMapData(this, key)['delete'](key);
      this.size -= result ? 1 : 0;
      return result;
    }

    /**
     * Gets the map value for `key`.
     *
     * @private
     * @name get
     * @memberOf MapCache
     * @param {string} key The key of the value to get.
     * @returns {*} Returns the entry value.
     */
    function mapCacheGet(key) {
      return getMapData(this, key).get(key);
    }

    /**
     * Checks if a map value for `key` exists.
     *
     * @private
     * @name has
     * @memberOf MapCache
     * @param {string} key The key of the entry to check.
     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
     */
    function mapCacheHas(key) {
      return getMapData(this, key).has(key);
    }

    /**
     * Sets the map `key` to `value`.
     *
     * @private
     * @name set
     * @memberOf MapCache
     * @param {string} key The key of the value to set.
     * @param {*} value The value to set.
     * @returns {Object} Returns the map cache instance.
     */
    function mapCacheSet(key, value) {
      var data = getMapData(this, key),
          size = data.size;

      data.set(key, value);
      this.size += data.size == size ? 0 : 1;
      return this;
    }

    // Add methods to `MapCache`.
    MapCache.prototype.clear = mapCacheClear;
    MapCache.prototype['delete'] = mapCacheDelete;
    MapCache.prototype.get = mapCacheGet;
    MapCache.prototype.has = mapCacheHas;
    MapCache.prototype.set = mapCacheSet;

    /*------------------------------------------------------------------------*/

    /**
     *
     * Creates an array cache object to store unique values.
     *
     * @private
     * @constructor
     * @param {Array} [values] The values to cache.
     */
    function SetCache(values) {
      var index = -1,
          length = values == null ? 0 : values.length;

      this.__data__ = new MapCache;
      while (++index < length) {
        this.add(values[index]);
      }
    }

    /**
     * Adds `value` to the array cache.
     *
     * @private
     * @name add
     * @memberOf SetCache
     * @alias push
     * @param {*} value The value to cache.
     * @returns {Object} Returns the cache instance.
     */
    function setCacheAdd(value) {
      this.__data__.set(value, HASH_UNDEFINED);
      return this;
    }

    /**
     * Checks if `value` is in the array cache.
     *
     * @private
     * @name has
     * @memberOf SetCache
     * @param {*} value The value to search for.
     * @returns {number} Returns `true` if `value` is found, else `false`.
     */
    function setCacheHas(value) {
      return this.__data__.has(value);
    }

    // Add methods to `SetCache`.
    SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
    SetCache.prototype.has = setCacheHas;

    /*------------------------------------------------------------------------*/

    /**
     * Creates a stack cache object to store key-value pairs.
     *
     * @private
     * @constructor
     * @param {Array} [entries] The key-value pairs to cache.
     */
    function Stack(entries) {
      var data = this.__data__ = new ListCache(entries);
      this.size = data.size;
    }

    /**
     * Removes all key-value entries from the stack.
     *
     * @private
     * @name clear
     * @memberOf Stack
     */
    function stackClear() {
      this.__data__ = new ListCache;
      this.size = 0;
    }

    /**
     * Removes `key` and its value from the stack.
     *
     * @private
     * @name delete
     * @memberOf Stack
     * @param {string} key The key of the value to remove.
     * @returns {boolean} Returns `true` if the entry was removed, else `false`.
     */
    function stackDelete(key) {
      var data = this.__data__,
          result = data['delete'](key);

      this.size = data.size;
      return result;
    }

    /**
     * Gets the stack value for `key`.
     *
     * @private
     * @name get
     * @memberOf Stack
     * @param {string} key The key of the value to get.
     * @returns {*} Returns the entry value.
     */
    function stackGet(key) {
      return this.__data__.get(key);
    }

    /**
     * Checks if a stack value for `key` exists.
     *
     * @private
     * @name has
     * @memberOf Stack
     * @param {string} key The key of the entry to check.
     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
     */
    function stackHas(key) {
      return this.__data__.has(key);
    }

    /**
     * Sets the stack `key` to `value`.
     *
     * @private
     * @name set
     * @memberOf Stack
     * @param {string} key The key of the value to set.
     * @param {*} value The value to set.
     * @returns {Object} Returns the stack cache instance.
     */
    function stackSet(key, value) {
      var data = this.__data__;
      if (data instanceof ListCache) {
        var pairs = data.__data__;
        if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
          pairs.push([key, value]);
          this.size = ++data.size;
          return this;
        }
        data = this.__data__ = new MapCache(pairs);
      }
      data.set(key, value);
      this.size = data.size;
      return this;
    }

    // Add methods to `Stack`.
    Stack.prototype.clear = stackClear;
    Stack.prototype['delete'] = stackDelete;
    Stack.prototype.get = stackGet;
    Stack.prototype.has = stackHas;
    Stack.prototype.set = stackSet;

    /*------------------------------------------------------------------------*/

    /**
     * Creates an array of the enumerable property names of the array-like `value`.
     *
     * @private
     * @param {*} value The value to query.
     * @param {boolean} inherited Specify returning inherited property names.
     * @returns {Array} Returns the array of property names.
     */
    function arrayLikeKeys(value, inherited) {
      var isArr = isArray(value),
          isArg = !isArr && isArguments(value),
          isBuff = !isArr && !isArg && isBuffer(value),
          isType = !isArr && !isArg && !isBuff && isTypedArray(value),
          skipIndexes = isArr || isArg || isBuff || isType,
          result = skipIndexes ? baseTimes(value.length, String) : [],
          length = result.length;

      for (var key in value) {
        if ((inherited || hasOwnProperty.call(value, key)) &&
            !(skipIndexes && (
               // Safari 9 has enumerable `arguments.length` in strict mode.
               key == 'length' ||
               // Node.js 0.10 has enumerable non-index properties on buffers.
               (isBuff && (key == 'offset' || key == 'parent')) ||
               // PhantomJS 2 has enumerable non-index properties on typed arrays.
               (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
               // Skip index properties.
               isIndex(key, length)
            ))) {
          result.push(key);
        }
      }
      return result;
    }

    /**
     * A specialized version of `_.sample` for arrays.
     *
     * @private
     * @param {Array} array The array to sample.
     * @returns {*} Returns the random element.
     */
    function arraySample(array) {
      var length = array.length;
      return length ? array[baseRandom(0, length - 1)] : undefined;
    }

    /**
     * A specialized version of `_.sampleSize` for arrays.
     *
     * @private
     * @param {Array} array The array to sample.
     * @param {number} n The number of elements to sample.
     * @returns {Array} Returns the random elements.
     */
    function arraySampleSize(array, n) {
      return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
    }

    /**
     * A specialized version of `_.shuffle` for arrays.
     *
     * @private
     * @param {Array} array The array to shuffle.
     * @returns {Array} Returns the new shuffled array.
     */
    function arrayShuffle(array) {
      return shuffleSelf(copyArray(array));
    }

    /**
     * This function is like `assignValue` except that it doesn't assign
     * `undefined` values.
     *
     * @private
     * @param {Object} object The object to modify.
     * @param {string} key The key of the property to assign.
     * @param {*} value The value to assign.
     */
    function assignMergeValue(object, key, value) {
      if ((value !== undefined && !eq(object[key], value)) ||
          (value === undefined && !(key in object))) {
        baseAssignValue(object, key, value);
      }
    }

    /**
     * Assigns `value` to `key` of `object` if the existing value is not equivalent
     * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons.
     *
     * @private
     * @param {Object} object The object to modify.
     * @param {string} key The key of the property to assign.
     * @param {*} value The value to assign.
     */
    function assignValue(object, key, value) {
      var objValue = object[key];
      if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
          (value === undefined && !(key in object))) {
        baseAssignValue(object, key, value);
      }
    }

    /**
     * Gets the index at which the `key` is found in `array` of key-value pairs.
     *
     * @private
     * @param {Array} array The array to inspect.
     * @param {*} key The key to search for.
     * @returns {number} Returns the index of the matched value, else `-1`.
     */
    function assocIndexOf(array, key) {
      var length = array.length;
      while (length--) {
        if (eq(array[length][0], key)) {
          return length;
        }
      }
      return -1;
    }

    /**
     * Aggregates elements of `collection` on `accumulator` with keys transformed
     * by `iteratee` and values set by `setter`.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} setter The function to set `accumulator` values.
     * @param {Function} iteratee The iteratee to transform keys.
     * @param {Object} accumulator The initial aggregated object.
     * @returns {Function} Returns `accumulator`.
     */
    function baseAggregator(collection, setter, iteratee, accumulator) {
      baseEach(collection, function(value, key, collection) {
        setter(accumulator, value, iteratee(value), collection);
      });
      return accumulator;
    }

    /**
     * The base implementation of `_.assign` without support for multiple sources
     * or `customizer` functions.
     *
     * @private
     * @param {Object} object The destination object.
     * @param {Object} source The source object.
     * @returns {Object} Returns `object`.
     */
    function baseAssign(object, source) {
      return object && copyObject(source, keys(source), object);
    }

    /**
     * The base implementation of `_.assignIn` without support for multiple sources
     * or `customizer` functions.
     *
     * @private
     * @param {Object} object The destination object.
     * @param {Object} source The source object.
     * @returns {Object} Returns `object`.
     */
    function baseAssignIn(object, source) {
      return object && copyObject(source, keysIn(source), object);
    }

    /**
     * The base implementation of `assignValue` and `assignMergeValue` without
     * value checks.
     *
     * @private
     * @param {Object} object The object to modify.
     * @param {string} key The key of the property to assign.
     * @param {*} value The value to assign.
     */
    function baseAssignValue(object, key, value) {
      if (key == '__proto__' && defineProperty) {
        defineProperty(object, key, {
          'configurable': true,
          'enumerable': true,
          'value': value,
          'writable': true
        });
      } else {
        object[key] = value;
      }
    }

    /**
     * The base implementation of `_.at` without support for individual paths.
     *
     * @private
     * @param {Object} object The object to iterate over.
     * @param {string[]} paths The property paths to pick.
     * @returns {Array} Returns the picked elements.
     */
    function baseAt(object, paths) {
      var index = -1,
          length = paths.length,
          result = Array(length),
          skip = object == null;

      while (++index < length) {
        result[index] = skip ? undefined : get(object, paths[index]);
      }
      return result;
    }

    /**
     * The base implementation of `_.clamp` which doesn't coerce arguments.
     *
     * @private
     * @param {number} number The number to clamp.
     * @param {number} [lower] The lower bound.
     * @param {number} upper The upper bound.
     * @returns {number} Returns the clamped number.
     */
    function baseClamp(number, lower, upper) {
      if (number === number) {
        if (upper !== undefined) {
          number = number <= upper ? number : upper;
        }
        if (lower !== undefined) {
          number = number >= lower ? number : lower;
        }
      }
      return number;
    }

    /**
     * The base implementation of `_.clone` and `_.cloneDeep` which tracks
     * traversed objects.
     *
     * @private
     * @param {*} value The value to clone.
     * @param {boolean} bitmask The bitmask flags.
     *  1 - Deep clone
     *  2 - Flatten inherited properties
     *  4 - Clone symbols
     * @param {Function} [customizer] The function to customize cloning.
     * @param {string} [key] The key of `value`.
     * @param {Object} [object] The parent object of `value`.
     * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
     * @returns {*} Returns the cloned value.
     */
    function baseClone(value, bitmask, customizer, key, object, stack) {
      var result,
          isDeep = bitmask & CLONE_DEEP_FLAG,
          isFlat = bitmask & CLONE_FLAT_FLAG,
          isFull = bitmask & CLONE_SYMBOLS_FLAG;

      if (customizer) {
        result = object ? customizer(value, key, object, stack) : customizer(value);
      }
      if (result !== undefined) {
        return result;
      }
      if (!isObject(value)) {
        return value;
      }
      var isArr = isArray(value);
      if (isArr) {
        result = initCloneArray(value);
        if (!isDeep) {
          return copyArray(value, result);
        }
      } else {
        var tag = getTag(value),
            isFunc = tag == funcTag || tag == genTag;

        if (isBuffer(value)) {
          return cloneBuffer(value, isDeep);
        }
        if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
          result = (isFlat || isFunc) ? {} : initCloneObject(value);
          if (!isDeep) {
            return isFlat
              ? copySymbolsIn(value, baseAssignIn(result, value))
              : copySymbols(value, baseAssign(result, value));
          }
        } else {
          if (!cloneableTags[tag]) {
            return object ? value : {};
          }
          result = initCloneByTag(value, tag, baseClone, isDeep);
        }
      }
      // Check for circular references and return its corresponding clone.
      stack || (stack = new Stack);
      var stacked = stack.get(value);
      if (stacked) {
        return stacked;
      }
      stack.set(value, result);

      var keysFunc = isFull
        ? (isFlat ? getAllKeysIn : getAllKeys)
        : (isFlat ? keysIn : keys);

      var props = isArr ? undefined : keysFunc(value);
      arrayEach(props || value, function(subValue, key) {
        if (props) {
          key = subValue;
          subValue = value[key];
        }
        // Recursively populate clone (susceptible to call stack limits).
        assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
      });
      return result;
    }

    /**
     * The base implementation of `_.conforms` which doesn't clone `source`.
     *
     * @private
     * @param {Object} source The object of property predicates to conform to.
     * @returns {Function} Returns the new spec function.
     */
    function baseConforms(source) {
      var props = keys(source);
      return function(object) {
        return baseConformsTo(object, source, props);
      };
    }

    /**
     * The base implementation of `_.conformsTo` which accepts `props` to check.
     *
     * @private
     * @param {Object} object The object to inspect.
     * @param {Object} source The object of property predicates to conform to.
     * @returns {boolean} Returns `true` if `object` conforms, else `false`.
     */
    function baseConformsTo(object, source, props) {
      var length = props.length;
      if (object == null) {
        return !length;
      }
      object = Object(object);
      while (length--) {
        var key = props[length],
            predicate = source[key],
            value = object[key];

        if ((value === undefined && !(key in object)) || !predicate(value)) {
          return false;
        }
      }
      return true;
    }

    /**
     * The base implementation of `_.delay` and `_.defer` which accepts `args`
     * to provide to `func`.
     *
     * @private
     * @param {Function} func The function to delay.
     * @param {number} wait The number of milliseconds to delay invocation.
     * @param {Array} args The arguments to provide to `func`.
     * @returns {number|Object} Returns the timer id or timeout object.
     */
    function baseDelay(func, wait, args) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      return setTimeout(function() { func.apply(undefined, args); }, wait);
    }

    /**
     * The base implementation of methods like `_.difference` without support
     * for excluding multiple arrays or iteratee shorthands.
     *
     * @private
     * @param {Array} array The array to inspect.
     * @param {Array} values The values to exclude.
     * @param {Function} [iteratee] The iteratee invoked per element.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new array of filtered values.
     */
    function baseDifference(array, values, iteratee, comparator) {
      var index = -1,
          includes = arrayIncludes,
          isCommon = true,
          length = array.length,
          result = [],
          valuesLength = values.length;

      if (!length) {
        return result;
      }
      if (iteratee) {
        values = arrayMap(values, baseUnary(iteratee));
      }
      if (comparator) {
        includes = arrayIncludesWith;
        isCommon = false;
      }
      else if (values.length >= LARGE_ARRAY_SIZE) {
        includes = cacheHas;
        isCommon = false;
        values = new SetCache(values);
      }
      outer:
      while (++index < length) {
        var value = array[index],
            computed = iteratee == null ? value : iteratee(value);

        value = (comparator || value !== 0) ? value : 0;
        if (isCommon && computed === computed) {
          var valuesIndex = valuesLength;
          while (valuesIndex--) {
            if (values[valuesIndex] === computed) {
              continue outer;
            }
          }
          result.push(value);
        }
        else if (!includes(values, computed, comparator)) {
          result.push(value);
        }
      }
      return result;
    }

    /**
     * The base implementation of `_.forEach` without support for iteratee shorthands.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} iteratee The function invoked per iteration.
     * @returns {Array|Object} Returns `collection`.
     */
    var baseEach = createBaseEach(baseForOwn);

    /**
     * The base implementation of `_.forEachRight` without support for iteratee shorthands.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} iteratee The function invoked per iteration.
     * @returns {Array|Object} Returns `collection`.
     */
    var baseEachRight = createBaseEach(baseForOwnRight, true);

    /**
     * The base implementation of `_.every` without support for iteratee shorthands.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} predicate The function invoked per iteration.
     * @returns {boolean} Returns `true` if all elements pass the predicate check,
     *  else `false`
     */
    function baseEvery(collection, predicate) {
      var result = true;
      baseEach(collection, function(value, index, collection) {
        result = !!predicate(value, index, collection);
        return result;
      });
      return result;
    }

    /**
     * The base implementation of methods like `_.max` and `_.min` which accepts a
     * `comparator` to determine the extremum value.
     *
     * @private
     * @param {Array} array The array to iterate over.
     * @param {Function} iteratee The iteratee invoked per iteration.
     * @param {Function} comparator The comparator used to compare values.
     * @returns {*} Returns the extremum value.
     */
    function baseExtremum(array, iteratee, comparator) {
      var index = -1,
          length = array.length;

      while (++index < length) {
        var value = array[index],
            current = iteratee(value);

        if (current != null && (computed === undefined
              ? (current === current && !isSymbol(current))
              : comparator(current, computed)
            )) {
          var computed = current,
              result = value;
        }
      }
      return result;
    }

    /**
     * The base implementation of `_.fill` without an iteratee call guard.
     *
     * @private
     * @param {Array} array The array to fill.
     * @param {*} value The value to fill `array` with.
     * @param {number} [start=0] The start position.
     * @param {number} [end=array.length] The end position.
     * @returns {Array} Returns `array`.
     */
    function baseFill(array, value, start, end) {
      var length = array.length;

      start = toInteger(start);
      if (start < 0) {
        start = -start > length ? 0 : (length + start);
      }
      end = (end === undefined || end > length) ? length : toInteger(end);
      if (end < 0) {
        end += length;
      }
      end = start > end ? 0 : toLength(end);
      while (start < end) {
        array[start++] = value;
      }
      return array;
    }

    /**
     * The base implementation of `_.filter` without support for iteratee shorthands.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} predicate The function invoked per iteration.
     * @returns {Array} Returns the new filtered array.
     */
    function baseFilter(collection, predicate) {
      var result = [];
      baseEach(collection, function(value, index, collection) {
        if (predicate(value, index, collection)) {
          result.push(value);
        }
      });
      return result;
    }

    /**
     * The base implementation of `_.flatten` with support for restricting flattening.
     *
     * @private
     * @param {Array} array The array to flatten.
     * @param {number} depth The maximum recursion depth.
     * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
     * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
     * @param {Array} [result=[]] The initial result value.
     * @returns {Array} Returns the new flattened array.
     */
    function baseFlatten(array, depth, predicate, isStrict, result) {
      var index = -1,
          length = array.length;

      predicate || (predicate = isFlattenable);
      result || (result = []);

      while (++index < length) {
        var value = array[index];
        if (depth > 0 && predicate(value)) {
          if (depth > 1) {
            // Recursively flatten arrays (susceptible to call stack limits).
            baseFlatten(value, depth - 1, predicate, isStrict, result);
          } else {
            arrayPush(result, value);
          }
        } else if (!isStrict) {
          result[result.length] = value;
        }
      }
      return result;
    }

    /**
     * The base implementation of `baseForOwn` which iterates over `object`
     * properties returned by `keysFunc` and invokes `iteratee` for each property.
     * Iteratee functions may exit iteration early by explicitly returning `false`.
     *
     * @private
     * @param {Object} object The object to iterate over.
     * @param {Function} iteratee The function invoked per iteration.
     * @param {Function} keysFunc The function to get the keys of `object`.
     * @returns {Object} Returns `object`.
     */
    var baseFor = createBaseFor();

    /**
     * This function is like `baseFor` except that it iterates over properties
     * in the opposite order.
     *
     * @private
     * @param {Object} object The object to iterate over.
     * @param {Function} iteratee The function invoked per iteration.
     * @param {Function} keysFunc The function to get the keys of `object`.
     * @returns {Object} Returns `object`.
     */
    var baseForRight = createBaseFor(true);

    /**
     * The base implementation of `_.forOwn` without support for iteratee shorthands.
     *
     * @private
     * @param {Object} object The object to iterate over.
     * @param {Function} iteratee The function invoked per iteration.
     * @returns {Object} Returns `object`.
     */
    function baseForOwn(object, iteratee) {
      return object && baseFor(object, iteratee, keys);
    }

    /**
     * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
     *
     * @private
     * @param {Object} object The object to iterate over.
     * @param {Function} iteratee The function invoked per iteration.
     * @returns {Object} Returns `object`.
     */
    function baseForOwnRight(object, iteratee) {
      return object && baseForRight(object, iteratee, keys);
    }

    /**
     * The base implementation of `_.functions` which creates an array of
     * `object` function property names filtered from `props`.
     *
     * @private
     * @param {Object} object The object to inspect.
     * @param {Array} props The property names to filter.
     * @returns {Array} Returns the function names.
     */
    function baseFunctions(object, props) {
      return arrayFilter(props, function(key) {
        return isFunction(object[key]);
      });
    }

    /**
     * The base implementation of `_.get` without support for default values.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {Array|string} path The path of the property to get.
     * @returns {*} Returns the resolved value.
     */
    function baseGet(object, path) {
      path = castPath(path, object);

      var index = 0,
          length = path.length;

      while (object != null && index < length) {
        object = object[toKey(path[index++])];
      }
      return (index && index == length) ? object : undefined;
    }

    /**
     * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
     * `keysFunc` and `symbolsFunc` to get the enumerable property names and
     * symbols of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {Function} keysFunc The function to get the keys of `object`.
     * @param {Function} symbolsFunc The function to get the symbols of `object`.
     * @returns {Array} Returns the array of property names and symbols.
     */
    function baseGetAllKeys(object, keysFunc, symbolsFunc) {
      var result = keysFunc(object);
      return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
    }

    /**
     * The base implementation of `getTag` without fallbacks for buggy environments.
     *
     * @private
     * @param {*} value The value to query.
     * @returns {string} Returns the `toStringTag`.
     */
    function baseGetTag(value) {
      if (value == null) {
        return value === undefined ? undefinedTag : nullTag;
      }
      return (symToStringTag && symToStringTag in Object(value))
        ? getRawTag(value)
        : objectToString(value);
    }

    /**
     * The base implementation of `_.gt` which doesn't coerce arguments.
     *
     * @private
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if `value` is greater than `other`,
     *  else `false`.
     */
    function baseGt(value, other) {
      return value > other;
    }

    /**
     * The base implementation of `_.has` without support for deep paths.
     *
     * @private
     * @param {Object} [object] The object to query.
     * @param {Array|string} key The key to check.
     * @returns {boolean} Returns `true` if `key` exists, else `false`.
     */
    function baseHas(object, key) {
      return object != null && hasOwnProperty.call(object, key);
    }

    /**
     * The base implementation of `_.hasIn` without support for deep paths.
     *
     * @private
     * @param {Object} [object] The object to query.
     * @param {Array|string} key The key to check.
     * @returns {boolean} Returns `true` if `key` exists, else `false`.
     */
    function baseHasIn(object, key) {
      return object != null && key in Object(object);
    }

    /**
     * The base implementation of `_.inRange` which doesn't coerce arguments.
     *
     * @private
     * @param {number} number The number to check.
     * @param {number} start The start of the range.
     * @param {number} end The end of the range.
     * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
     */
    function baseInRange(number, start, end) {
      return number >= nativeMin(start, end) && number < nativeMax(start, end);
    }

    /**
     * The base implementation of methods like `_.intersection`, without support
     * for iteratee shorthands, that accepts an array of arrays to inspect.
     *
     * @private
     * @param {Array} arrays The arrays to inspect.
     * @param {Function} [iteratee] The iteratee invoked per element.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new array of shared values.
     */
    function baseIntersection(arrays, iteratee, comparator) {
      var includes = comparator ? arrayIncludesWith : arrayIncludes,
          length = arrays[0].length,
          othLength = arrays.length,
          othIndex = othLength,
          caches = Array(othLength),
          maxLength = Infinity,
          result = [];

      while (othIndex--) {
        var array = arrays[othIndex];
        if (othIndex && iteratee) {
          array = arrayMap(array, baseUnary(iteratee));
        }
        maxLength = nativeMin(array.length, maxLength);
        caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
          ? new SetCache(othIndex && array)
          : undefined;
      }
      array = arrays[0];

      var index = -1,
          seen = caches[0];

      outer:
      while (++index < length && result.length < maxLength) {
        var value = array[index],
            computed = iteratee ? iteratee(value) : value;

        value = (comparator || value !== 0) ? value : 0;
        if (!(seen
              ? cacheHas(seen, computed)
              : includes(result, computed, comparator)
            )) {
          othIndex = othLength;
          while (--othIndex) {
            var cache = caches[othIndex];
            if (!(cache
                  ? cacheHas(cache, computed)
                  : includes(arrays[othIndex], computed, comparator))
                ) {
              continue outer;
            }
          }
          if (seen) {
            seen.push(computed);
          }
          result.push(value);
        }
      }
      return result;
    }

    /**
     * The base implementation of `_.invert` and `_.invertBy` which inverts
     * `object` with values transformed by `iteratee` and set by `setter`.
     *
     * @private
     * @param {Object} object The object to iterate over.
     * @param {Function} setter The function to set `accumulator` values.
     * @param {Function} iteratee The iteratee to transform values.
     * @param {Object} accumulator The initial inverted object.
     * @returns {Function} Returns `accumulator`.
     */
    function baseInverter(object, setter, iteratee, accumulator) {
      baseForOwn(object, function(value, key, object) {
        setter(accumulator, iteratee(value), key, object);
      });
      return accumulator;
    }

    /**
     * The base implementation of `_.invoke` without support for individual
     * method arguments.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {Array|string} path The path of the method to invoke.
     * @param {Array} args The arguments to invoke the method with.
     * @returns {*} Returns the result of the invoked method.
     */
    function baseInvoke(object, path, args) {
      path = castPath(path, object);
      object = parent(object, path);
      var func = object == null ? object : object[toKey(last(path))];
      return func == null ? undefined : apply(func, object, args);
    }

    /**
     * The base implementation of `_.isArguments`.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an `arguments` object,
     */
    function baseIsArguments(value) {
      return isObjectLike(value) && baseGetTag(value) == argsTag;
    }

    /**
     * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
     */
    function baseIsArrayBuffer(value) {
      return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
    }

    /**
     * The base implementation of `_.isDate` without Node.js optimizations.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
     */
    function baseIsDate(value) {
      return isObjectLike(value) && baseGetTag(value) == dateTag;
    }

    /**
     * The base implementation of `_.isEqual` which supports partial comparisons
     * and tracks traversed objects.
     *
     * @private
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @param {boolean} bitmask The bitmask flags.
     *  1 - Unordered comparison
     *  2 - Partial comparison
     * @param {Function} [customizer] The function to customize comparisons.
     * @param {Object} [stack] Tracks traversed `value` and `other` objects.
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
     */
    function baseIsEqual(value, other, bitmask, customizer, stack) {
      if (value === other) {
        return true;
      }
      if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
        return value !== value && other !== other;
      }
      return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
    }

    /**
     * A specialized version of `baseIsEqual` for arrays and objects which performs
     * deep comparisons and tracks traversed objects enabling objects with circular
     * references to be compared.
     *
     * @private
     * @param {Object} object The object to compare.
     * @param {Object} other The other object to compare.
     * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
     * @param {Function} customizer The function to customize comparisons.
     * @param {Function} equalFunc The function to determine equivalents of values.
     * @param {Object} [stack] Tracks traversed `object` and `other` objects.
     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
     */
    function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
      var objIsArr = isArray(object),
          othIsArr = isArray(other),
          objTag = objIsArr ? arrayTag : getTag(object),
          othTag = othIsArr ? arrayTag : getTag(other);

      objTag = objTag == argsTag ? objectTag : objTag;
      othTag = othTag == argsTag ? objectTag : othTag;

      var objIsObj = objTag == objectTag,
          othIsObj = othTag == objectTag,
          isSameTag = objTag == othTag;

      if (isSameTag && isBuffer(object)) {
        if (!isBuffer(other)) {
          return false;
        }
        objIsArr = true;
        objIsObj = false;
      }
      if (isSameTag && !objIsObj) {
        stack || (stack = new Stack);
        return (objIsArr || isTypedArray(object))
          ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
          : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
      }
      if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
        var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
            othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

        if (objIsWrapped || othIsWrapped) {
          var objUnwrapped = objIsWrapped ? object.value() : object,
              othUnwrapped = othIsWrapped ? other.value() : other;

          stack || (stack = new Stack);
          return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
        }
      }
      if (!isSameTag) {
        return false;
      }
      stack || (stack = new Stack);
      return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
    }

    /**
     * The base implementation of `_.isMap` without Node.js optimizations.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a map, else `false`.
     */
    function baseIsMap(value) {
      return isObjectLike(value) && getTag(value) == mapTag;
    }

    /**
     * The base implementation of `_.isMatch` without support for iteratee shorthands.
     *
     * @private
     * @param {Object} object The object to inspect.
     * @param {Object} source The object of property values to match.
     * @param {Array} matchData The property names, values, and compare flags to match.
     * @param {Function} [customizer] The function to customize comparisons.
     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
     */
    function baseIsMatch(object, source, matchData, customizer) {
      var index = matchData.length,
          length = index,
          noCustomizer = !customizer;

      if (object == null) {
        return !length;
      }
      object = Object(object);
      while (index--) {
        var data = matchData[index];
        if ((noCustomizer && data[2])
              ? data[1] !== object[data[0]]
              : !(data[0] in object)
            ) {
          return false;
        }
      }
      while (++index < length) {
        data = matchData[index];
        var key = data[0],
            objValue = object[key],
            srcValue = data[1];

        if (noCustomizer && data[2]) {
          if (objValue === undefined && !(key in object)) {
            return false;
          }
        } else {
          var stack = new Stack;
          if (customizer) {
            var result = customizer(objValue, srcValue, key, object, source, stack);
          }
          if (!(result === undefined
                ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
                : result
              )) {
            return false;
          }
        }
      }
      return true;
    }

    /**
     * The base implementation of `_.isNative` without bad shim checks.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a native function,
     *  else `false`.
     */
    function baseIsNative(value) {
      if (!isObject(value) || isMasked(value)) {
        return false;
      }
      var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
      return pattern.test(toSource(value));
    }

    /**
     * The base implementation of `_.isRegExp` without Node.js optimizations.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
     */
    function baseIsRegExp(value) {
      return isObjectLike(value) && baseGetTag(value) == regexpTag;
    }

    /**
     * The base implementation of `_.isSet` without Node.js optimizations.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a set, else `false`.
     */
    function baseIsSet(value) {
      return isObjectLike(value) && getTag(value) == setTag;
    }

    /**
     * The base implementation of `_.isTypedArray` without Node.js optimizations.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
     */
    function baseIsTypedArray(value) {
      return isObjectLike(value) &&
        isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
    }

    /**
     * The base implementation of `_.iteratee`.
     *
     * @private
     * @param {*} [value=_.identity] The value to convert to an iteratee.
     * @returns {Function} Returns the iteratee.
     */
    function baseIteratee(value) {
      // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
      // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
      if (typeof value == 'function') {
        return value;
      }
      if (value == null) {
        return identity;
      }
      if (typeof value == 'object') {
        return isArray(value)
          ? baseMatchesProperty(value[0], value[1])
          : baseMatches(value);
      }
      return property(value);
    }

    /**
     * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     */
    function baseKeys(object) {
      if (!isPrototype(object)) {
        return nativeKeys(object);
      }
      var result = [];
      for (var key in Object(object)) {
        if (hasOwnProperty.call(object, key) && key != 'constructor') {
          result.push(key);
        }
      }
      return result;
    }

    /**
     * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     */
    function baseKeysIn(object) {
      if (!isObject(object)) {
        return nativeKeysIn(object);
      }
      var isProto = isPrototype(object),
          result = [];

      for (var key in object) {
        if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
          result.push(key);
        }
      }
      return result;
    }

    /**
     * The base implementation of `_.lt` which doesn't coerce arguments.
     *
     * @private
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if `value` is less than `other`,
     *  else `false`.
     */
    function baseLt(value, other) {
      return value < other;
    }

    /**
     * The base implementation of `_.map` without support for iteratee shorthands.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} iteratee The function invoked per iteration.
     * @returns {Array} Returns the new mapped array.
     */
    function baseMap(collection, iteratee) {
      var index = -1,
          result = isArrayLike(collection) ? Array(collection.length) : [];

      baseEach(collection, function(value, key, collection) {
        result[++index] = iteratee(value, key, collection);
      });
      return result;
    }

    /**
     * The base implementation of `_.matches` which doesn't clone `source`.
     *
     * @private
     * @param {Object} source The object of property values to match.
     * @returns {Function} Returns the new spec function.
     */
    function baseMatches(source) {
      var matchData = getMatchData(source);
      if (matchData.length == 1 && matchData[0][2]) {
        return matchesStrictComparable(matchData[0][0], matchData[0][1]);
      }
      return function(object) {
        return object === source || baseIsMatch(object, source, matchData);
      };
    }

    /**
     * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
     *
     * @private
     * @param {string} path The path of the property to get.
     * @param {*} srcValue The value to match.
     * @returns {Function} Returns the new spec function.
     */
    function baseMatchesProperty(path, srcValue) {
      if (isKey(path) && isStrictComparable(srcValue)) {
        return matchesStrictComparable(toKey(path), srcValue);
      }
      return function(object) {
        var objValue = get(object, path);
        return (objValue === undefined && objValue === srcValue)
          ? hasIn(object, path)
          : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
      };
    }

    /**
     * The base implementation of `_.merge` without support for multiple sources.
     *
     * @private
     * @param {Object} object The destination object.
     * @param {Object} source The source object.
     * @param {number} srcIndex The index of `source`.
     * @param {Function} [customizer] The function to customize merged values.
     * @param {Object} [stack] Tracks traversed source values and their merged
     *  counterparts.
     */
    function baseMerge(object, source, srcIndex, customizer, stack) {
      if (object === source) {
        return;
      }
      baseFor(source, function(srcValue, key) {
        if (isObject(srcValue)) {
          stack || (stack = new Stack);
          baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
        }
        else {
          var newValue = customizer
            ? customizer(object[key], srcValue, (key + ''), object, source, stack)
            : undefined;

          if (newValue === undefined) {
            newValue = srcValue;
          }
          assignMergeValue(object, key, newValue);
        }
      }, keysIn);
    }

    /**
     * A specialized version of `baseMerge` for arrays and objects which performs
     * deep merges and tracks traversed objects enabling objects with circular
     * references to be merged.
     *
     * @private
     * @param {Object} object The destination object.
     * @param {Object} source The source object.
     * @param {string} key The key of the value to merge.
     * @param {number} srcIndex The index of `source`.
     * @param {Function} mergeFunc The function to merge values.
     * @param {Function} [customizer] The function to customize assigned values.
     * @param {Object} [stack] Tracks traversed source values and their merged
     *  counterparts.
     */
    function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
      var objValue = object[key],
          srcValue = source[key],
          stacked = stack.get(srcValue);

      if (stacked) {
        assignMergeValue(object, key, stacked);
        return;
      }
      var newValue = customizer
        ? customizer(objValue, srcValue, (key + ''), object, source, stack)
        : undefined;

      var isCommon = newValue === undefined;

      if (isCommon) {
        var isArr = isArray(srcValue),
            isBuff = !isArr && isBuffer(srcValue),
            isTyped = !isArr && !isBuff && isTypedArray(srcValue);

        newValue = srcValue;
        if (isArr || isBuff || isTyped) {
          if (isArray(objValue)) {
            newValue = objValue;
          }
          else if (isArrayLikeObject(objValue)) {
            newValue = copyArray(objValue);
          }
          else if (isBuff) {
            isCommon = false;
            newValue = cloneBuffer(srcValue, true);
          }
          else if (isTyped) {
            isCommon = false;
            newValue = cloneTypedArray(srcValue, true);
          }
          else {
            newValue = [];
          }
        }
        else if (isPlainObject(srcValue) || isArguments(srcValue)) {
          newValue = objValue;
          if (isArguments(objValue)) {
            newValue = toPlainObject(objValue);
          }
          else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
            newValue = initCloneObject(srcValue);
          }
        }
        else {
          isCommon = false;
        }
      }
      if (isCommon) {
        // Recursively merge objects and arrays (susceptible to call stack limits).
        stack.set(srcValue, newValue);
        mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
        stack['delete'](srcValue);
      }
      assignMergeValue(object, key, newValue);
    }

    /**
     * The base implementation of `_.nth` which doesn't coerce arguments.
     *
     * @private
     * @param {Array} array The array to query.
     * @param {number} n The index of the element to return.
     * @returns {*} Returns the nth element of `array`.
     */
    function baseNth(array, n) {
      var length = array.length;
      if (!length) {
        return;
      }
      n += n < 0 ? length : 0;
      return isIndex(n, length) ? array[n] : undefined;
    }

    /**
     * The base implementation of `_.orderBy` without param guards.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
     * @param {string[]} orders The sort orders of `iteratees`.
     * @returns {Array} Returns the new sorted array.
     */
    function baseOrderBy(collection, iteratees, orders) {
      var index = -1;
      iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));

      var result = baseMap(collection, function(value, key, collection) {
        var criteria = arrayMap(iteratees, function(iteratee) {
          return iteratee(value);
        });
        return { 'criteria': criteria, 'index': ++index, 'value': value };
      });

      return baseSortBy(result, function(object, other) {
        return compareMultiple(object, other, orders);
      });
    }

    /**
     * The base implementation of `_.pick` without support for individual
     * property identifiers.
     *
     * @private
     * @param {Object} object The source object.
     * @param {string[]} paths The property paths to pick.
     * @returns {Object} Returns the new object.
     */
    function basePick(object, paths) {
      return basePickBy(object, paths, function(value, path) {
        return hasIn(object, path);
      });
    }

    /**
     * The base implementation of  `_.pickBy` without support for iteratee shorthands.
     *
     * @private
     * @param {Object} object The source object.
     * @param {string[]} paths The property paths to pick.
     * @param {Function} predicate The function invoked per property.
     * @returns {Object} Returns the new object.
     */
    function basePickBy(object, paths, predicate) {
      var index = -1,
          length = paths.length,
          result = {};

      while (++index < length) {
        var path = paths[index],
            value = baseGet(object, path);

        if (predicate(value, path)) {
          baseSet(result, castPath(path, object), value);
        }
      }
      return result;
    }

    /**
     * A specialized version of `baseProperty` which supports deep paths.
     *
     * @private
     * @param {Array|string} path The path of the property to get.
     * @returns {Function} Returns the new accessor function.
     */
    function basePropertyDeep(path) {
      return function(object) {
        return baseGet(object, path);
      };
    }

    /**
     * The base implementation of `_.pullAllBy` without support for iteratee
     * shorthands.
     *
     * @private
     * @param {Array} array The array to modify.
     * @param {Array} values The values to remove.
     * @param {Function} [iteratee] The iteratee invoked per element.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns `array`.
     */
    function basePullAll(array, values, iteratee, comparator) {
      var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
          index = -1,
          length = values.length,
          seen = array;

      if (array === values) {
        values = copyArray(values);
      }
      if (iteratee) {
        seen = arrayMap(array, baseUnary(iteratee));
      }
      while (++index < length) {
        var fromIndex = 0,
            value = values[index],
            computed = iteratee ? iteratee(value) : value;

        while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
          if (seen !== array) {
            splice.call(seen, fromIndex, 1);
          }
          splice.call(array, fromIndex, 1);
        }
      }
      return array;
    }

    /**
     * The base implementation of `_.pullAt` without support for individual
     * indexes or capturing the removed elements.
     *
     * @private
     * @param {Array} array The array to modify.
     * @param {number[]} indexes The indexes of elements to remove.
     * @returns {Array} Returns `array`.
     */
    function basePullAt(array, indexes) {
      var length = array ? indexes.length : 0,
          lastIndex = length - 1;

      while (length--) {
        var index = indexes[length];
        if (length == lastIndex || index !== previous) {
          var previous = index;
          if (isIndex(index)) {
            splice.call(array, index, 1);
          } else {
            baseUnset(array, index);
          }
        }
      }
      return array;
    }

    /**
     * The base implementation of `_.random` without support for returning
     * floating-point numbers.
     *
     * @private
     * @param {number} lower The lower bound.
     * @param {number} upper The upper bound.
     * @returns {number} Returns the random number.
     */
    function baseRandom(lower, upper) {
      return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
    }

    /**
     * The base implementation of `_.range` and `_.rangeRight` which doesn't
     * coerce arguments.
     *
     * @private
     * @param {number} start The start of the range.
     * @param {number} end The end of the range.
     * @param {number} step The value to increment or decrement by.
     * @param {boolean} [fromRight] Specify iterating from right to left.
     * @returns {Array} Returns the range of numbers.
     */
    function baseRange(start, end, step, fromRight) {
      var index = -1,
          length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
          result = Array(length);

      while (length--) {
        result[fromRight ? length : ++index] = start;
        start += step;
      }
      return result;
    }

    /**
     * The base implementation of `_.repeat` which doesn't coerce arguments.
     *
     * @private
     * @param {string} string The string to repeat.
     * @param {number} n The number of times to repeat the string.
     * @returns {string} Returns the repeated string.
     */
    function baseRepeat(string, n) {
      var result = '';
      if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
        return result;
      }
      // Leverage the exponentiation by squaring algorithm for a faster repeat.
      // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
      do {
        if (n % 2) {
          result += string;
        }
        n = nativeFloor(n / 2);
        if (n) {
          string += string;
        }
      } while (n);

      return result;
    }

    /**
     * The base implementation of `_.rest` which doesn't validate or coerce arguments.
     *
     * @private
     * @param {Function} func The function to apply a rest parameter to.
     * @param {number} [start=func.length-1] The start position of the rest parameter.
     * @returns {Function} Returns the new function.
     */
    function baseRest(func, start) {
      return setToString(overRest(func, start, identity), func + '');
    }

    /**
     * The base implementation of `_.sample`.
     *
     * @private
     * @param {Array|Object} collection The collection to sample.
     * @returns {*} Returns the random element.
     */
    function baseSample(collection) {
      return arraySample(values(collection));
    }

    /**
     * The base implementation of `_.sampleSize` without param guards.
     *
     * @private
     * @param {Array|Object} collection The collection to sample.
     * @param {number} n The number of elements to sample.
     * @returns {Array} Returns the random elements.
     */
    function baseSampleSize(collection, n) {
      var array = values(collection);
      return shuffleSelf(array, baseClamp(n, 0, array.length));
    }

    /**
     * The base implementation of `_.set`.
     *
     * @private
     * @param {Object} object The object to modify.
     * @param {Array|string} path The path of the property to set.
     * @param {*} value The value to set.
     * @param {Function} [customizer] The function to customize path creation.
     * @returns {Object} Returns `object`.
     */
    function baseSet(object, path, value, customizer) {
      if (!isObject(object)) {
        return object;
      }
      path = castPath(path, object);

      var index = -1,
          length = path.length,
          lastIndex = length - 1,
          nested = object;

      while (nested != null && ++index < length) {
        var key = toKey(path[index]),
            newValue = value;

        if (index != lastIndex) {
          var objValue = nested[key];
          newValue = customizer ? customizer(objValue, key, nested) : undefined;
          if (newValue === undefined) {
            newValue = isObject(objValue)
              ? objValue
              : (isIndex(path[index + 1]) ? [] : {});
          }
        }
        assignValue(nested, key, newValue);
        nested = nested[key];
      }
      return object;
    }

    /**
     * The base implementation of `setData` without support for hot loop shorting.
     *
     * @private
     * @param {Function} func The function to associate metadata with.
     * @param {*} data The metadata.
     * @returns {Function} Returns `func`.
     */
    var baseSetData = !metaMap ? identity : function(func, data) {
      metaMap.set(func, data);
      return func;
    };

    /**
     * The base implementation of `setToString` without support for hot loop shorting.
     *
     * @private
     * @param {Function} func The function to modify.
     * @param {Function} string The `toString` result.
     * @returns {Function} Returns `func`.
     */
    var baseSetToString = !defineProperty ? identity : function(func, string) {
      return defineProperty(func, 'toString', {
        'configurable': true,
        'enumerable': false,
        'value': constant(string),
        'writable': true
      });
    };

    /**
     * The base implementation of `_.shuffle`.
     *
     * @private
     * @param {Array|Object} collection The collection to shuffle.
     * @returns {Array} Returns the new shuffled array.
     */
    function baseShuffle(collection) {
      return shuffleSelf(values(collection));
    }

    /**
     * The base implementation of `_.slice` without an iteratee call guard.
     *
     * @private
     * @param {Array} array The array to slice.
     * @param {number} [start=0] The start position.
     * @param {number} [end=array.length] The end position.
     * @returns {Array} Returns the slice of `array`.
     */
    function baseSlice(array, start, end) {
      var index = -1,
          length = array.length;

      if (start < 0) {
        start = -start > length ? 0 : (length + start);
      }
      end = end > length ? length : end;
      if (end < 0) {
        end += length;
      }
      length = start > end ? 0 : ((end - start) >>> 0);
      start >>>= 0;

      var result = Array(length);
      while (++index < length) {
        result[index] = array[index + start];
      }
      return result;
    }

    /**
     * The base implementation of `_.some` without support for iteratee shorthands.
     *
     * @private
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} predicate The function invoked per iteration.
     * @returns {boolean} Returns `true` if any element passes the predicate check,
     *  else `false`.
     */
    function baseSome(collection, predicate) {
      var result;

      baseEach(collection, function(value, index, collection) {
        result = predicate(value, index, collection);
        return !result;
      });
      return !!result;
    }

    /**
     * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
     * performs a binary search of `array` to determine the index at which `value`
     * should be inserted into `array` in order to maintain its sort order.
     *
     * @private
     * @param {Array} array The sorted array to inspect.
     * @param {*} value The value to evaluate.
     * @param {boolean} [retHighest] Specify returning the highest qualified index.
     * @returns {number} Returns the index at which `value` should be inserted
     *  into `array`.
     */
    function baseSortedIndex(array, value, retHighest) {
      var low = 0,
          high = array == null ? low : array.length;

      if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
        while (low < high) {
          var mid = (low + high) >>> 1,
              computed = array[mid];

          if (computed !== null && !isSymbol(computed) &&
              (retHighest ? (computed <= value) : (computed < value))) {
            low = mid + 1;
          } else {
            high = mid;
          }
        }
        return high;
      }
      return baseSortedIndexBy(array, value, identity, retHighest);
    }

    /**
     * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
     * which invokes `iteratee` for `value` and each element of `array` to compute
     * their sort ranking. The iteratee is invoked with one argument; (value).
     *
     * @private
     * @param {Array} array The sorted array to inspect.
     * @param {*} value The value to evaluate.
     * @param {Function} iteratee The iteratee invoked per element.
     * @param {boolean} [retHighest] Specify returning the highest qualified index.
     * @returns {number} Returns the index at which `value` should be inserted
     *  into `array`.
     */
    function baseSortedIndexBy(array, value, iteratee, retHighest) {
      value = iteratee(value);

      var low = 0,
          high = array == null ? 0 : array.length,
          valIsNaN = value !== value,
          valIsNull = value === null,
          valIsSymbol = isSymbol(value),
          valIsUndefined = value === undefined;

      while (low < high) {
        var mid = nativeFloor((low + high) / 2),
            computed = iteratee(array[mid]),
            othIsDefined = computed !== undefined,
            othIsNull = computed === null,
            othIsReflexive = computed === computed,
            othIsSymbol = isSymbol(computed);

        if (valIsNaN) {
          var setLow = retHighest || othIsReflexive;
        } else if (valIsUndefined) {
          setLow = othIsReflexive && (retHighest || othIsDefined);
        } else if (valIsNull) {
          setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
        } else if (valIsSymbol) {
          setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
        } else if (othIsNull || othIsSymbol) {
          setLow = false;
        } else {
          setLow = retHighest ? (computed <= value) : (computed < value);
        }
        if (setLow) {
          low = mid + 1;
        } else {
          high = mid;
        }
      }
      return nativeMin(high, MAX_ARRAY_INDEX);
    }

    /**
     * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
     * support for iteratee shorthands.
     *
     * @private
     * @param {Array} array The array to inspect.
     * @param {Function} [iteratee] The iteratee invoked per element.
     * @returns {Array} Returns the new duplicate free array.
     */
    function baseSortedUniq(array, iteratee) {
      var index = -1,
          length = array.length,
          resIndex = 0,
          result = [];

      while (++index < length) {
        var value = array[index],
            computed = iteratee ? iteratee(value) : value;

        if (!index || !eq(computed, seen)) {
          var seen = computed;
          result[resIndex++] = value === 0 ? 0 : value;
        }
      }
      return result;
    }

    /**
     * The base implementation of `_.toNumber` which doesn't ensure correct
     * conversions of binary, hexadecimal, or octal string values.
     *
     * @private
     * @param {*} value The value to process.
     * @returns {number} Returns the number.
     */
    function baseToNumber(value) {
      if (typeof value == 'number') {
        return value;
      }
      if (isSymbol(value)) {
        return NAN;
      }
      return +value;
    }

    /**
     * The base implementation of `_.toString` which doesn't convert nullish
     * values to empty strings.
     *
     * @private
     * @param {*} value The value to process.
     * @returns {string} Returns the string.
     */
    function baseToString(value) {
      // Exit early for strings to avoid a performance hit in some environments.
      if (typeof value == 'string') {
        return value;
      }
      if (isArray(value)) {
        // Recursively convert values (susceptible to call stack limits).
        return arrayMap(value, baseToString) + '';
      }
      if (isSymbol(value)) {
        return symbolToString ? symbolToString.call(value) : '';
      }
      var result = (value + '');
      return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
    }

    /**
     * The base implementation of `_.uniqBy` without support for iteratee shorthands.
     *
     * @private
     * @param {Array} array The array to inspect.
     * @param {Function} [iteratee] The iteratee invoked per element.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new duplicate free array.
     */
    function baseUniq(array, iteratee, comparator) {
      var index = -1,
          includes = arrayIncludes,
          length = array.length,
          isCommon = true,
          result = [],
          seen = result;

      if (comparator) {
        isCommon = false;
        includes = arrayIncludesWith;
      }
      else if (length >= LARGE_ARRAY_SIZE) {
        var set = iteratee ? null : createSet(array);
        if (set) {
          return setToArray(set);
        }
        isCommon = false;
        includes = cacheHas;
        seen = new SetCache;
      }
      else {
        seen = iteratee ? [] : result;
      }
      outer:
      while (++index < length) {
        var value = array[index],
            computed = iteratee ? iteratee(value) : value;

        value = (comparator || value !== 0) ? value : 0;
        if (isCommon && computed === computed) {
          var seenIndex = seen.length;
          while (seenIndex--) {
            if (seen[seenIndex] === computed) {
              continue outer;
            }
          }
          if (iteratee) {
            seen.push(computed);
          }
          result.push(value);
        }
        else if (!includes(seen, computed, comparator)) {
          if (seen !== result) {
            seen.push(computed);
          }
          result.push(value);
        }
      }
      return result;
    }

    /**
     * The base implementation of `_.unset`.
     *
     * @private
     * @param {Object} object The object to modify.
     * @param {Array|string} path The property path to unset.
     * @returns {boolean} Returns `true` if the property is deleted, else `false`.
     */
    function baseUnset(object, path) {
      path = castPath(path, object);
      object = parent(object, path);
      return object == null || delete object[toKey(last(path))];
    }

    /**
     * The base implementation of `_.update`.
     *
     * @private
     * @param {Object} object The object to modify.
     * @param {Array|string} path The path of the property to update.
     * @param {Function} updater The function to produce the updated value.
     * @param {Function} [customizer] The function to customize path creation.
     * @returns {Object} Returns `object`.
     */
    function baseUpdate(object, path, updater, customizer) {
      return baseSet(object, path, updater(baseGet(object, path)), customizer);
    }

    /**
     * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
     * without support for iteratee shorthands.
     *
     * @private
     * @param {Array} array The array to query.
     * @param {Function} predicate The function invoked per iteration.
     * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
     * @param {boolean} [fromRight] Specify iterating from right to left.
     * @returns {Array} Returns the slice of `array`.
     */
    function baseWhile(array, predicate, isDrop, fromRight) {
      var length = array.length,
          index = fromRight ? length : -1;

      while ((fromRight ? index-- : ++index < length) &&
        predicate(array[index], index, array)) {}

      return isDrop
        ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
        : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
    }

    /**
     * The base implementation of `wrapperValue` which returns the result of
     * performing a sequence of actions on the unwrapped `value`, where each
     * successive action is supplied the return value of the previous.
     *
     * @private
     * @param {*} value The unwrapped value.
     * @param {Array} actions Actions to perform to resolve the unwrapped value.
     * @returns {*} Returns the resolved value.
     */
    function baseWrapperValue(value, actions) {
      var result = value;
      if (result instanceof LazyWrapper) {
        result = result.value();
      }
      return arrayReduce(actions, function(result, action) {
        return action.func.apply(action.thisArg, arrayPush([result], action.args));
      }, result);
    }

    /**
     * The base implementation of methods like `_.xor`, without support for
     * iteratee shorthands, that accepts an array of arrays to inspect.
     *
     * @private
     * @param {Array} arrays The arrays to inspect.
     * @param {Function} [iteratee] The iteratee invoked per element.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new array of values.
     */
    function baseXor(arrays, iteratee, comparator) {
      var length = arrays.length;
      if (length < 2) {
        return length ? baseUniq(arrays[0]) : [];
      }
      var index = -1,
          result = Array(length);

      while (++index < length) {
        var array = arrays[index],
            othIndex = -1;

        while (++othIndex < length) {
          if (othIndex != index) {
            result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
          }
        }
      }
      return baseUniq(baseFlatten(result, 1), iteratee, comparator);
    }

    /**
     * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
     *
     * @private
     * @param {Array} props The property identifiers.
     * @param {Array} values The property values.
     * @param {Function} assignFunc The function to assign values.
     * @returns {Object} Returns the new object.
     */
    function baseZipObject(props, values, assignFunc) {
      var index = -1,
          length = props.length,
          valsLength = values.length,
          result = {};

      while (++index < length) {
        var value = index < valsLength ? values[index] : undefined;
        assignFunc(result, props[index], value);
      }
      return result;
    }

    /**
     * Casts `value` to an empty array if it's not an array like object.
     *
     * @private
     * @param {*} value The value to inspect.
     * @returns {Array|Object} Returns the cast array-like object.
     */
    function castArrayLikeObject(value) {
      return isArrayLikeObject(value) ? value : [];
    }

    /**
     * Casts `value` to `identity` if it's not a function.
     *
     * @private
     * @param {*} value The value to inspect.
     * @returns {Function} Returns cast function.
     */
    function castFunction(value) {
      return typeof value == 'function' ? value : identity;
    }

    /**
     * Casts `value` to a path array if it's not one.
     *
     * @private
     * @param {*} value The value to inspect.
     * @param {Object} [object] The object to query keys on.
     * @returns {Array} Returns the cast property path array.
     */
    function castPath(value, object) {
      if (isArray(value)) {
        return value;
      }
      return isKey(value, object) ? [value] : stringToPath(toString(value));
    }

    /**
     * A `baseRest` alias which can be replaced with `identity` by module
     * replacement plugins.
     *
     * @private
     * @type {Function}
     * @param {Function} func The function to apply a rest parameter to.
     * @returns {Function} Returns the new function.
     */
    var castRest = baseRest;

    /**
     * Casts `array` to a slice if it's needed.
     *
     * @private
     * @param {Array} array The array to inspect.
     * @param {number} start The start position.
     * @param {number} [end=array.length] The end position.
     * @returns {Array} Returns the cast slice.
     */
    function castSlice(array, start, end) {
      var length = array.length;
      end = end === undefined ? length : end;
      return (!start && end >= length) ? array : baseSlice(array, start, end);
    }

    /**
     * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
     *
     * @private
     * @param {number|Object} id The timer id or timeout object of the timer to clear.
     */
    var clearTimeout = ctxClearTimeout || function(id) {
      return root.clearTimeout(id);
    };

    /**
     * Creates a clone of  `buffer`.
     *
     * @private
     * @param {Buffer} buffer The buffer to clone.
     * @param {boolean} [isDeep] Specify a deep clone.
     * @returns {Buffer} Returns the cloned buffer.
     */
    function cloneBuffer(buffer, isDeep) {
      if (isDeep) {
        return buffer.slice();
      }
      var length = buffer.length,
          result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);

      buffer.copy(result);
      return result;
    }

    /**
     * Creates a clone of `arrayBuffer`.
     *
     * @private
     * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
     * @returns {ArrayBuffer} Returns the cloned array buffer.
     */
    function cloneArrayBuffer(arrayBuffer) {
      var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
      new Uint8Array(result).set(new Uint8Array(arrayBuffer));
      return result;
    }

    /**
     * Creates a clone of `dataView`.
     *
     * @private
     * @param {Object} dataView The data view to clone.
     * @param {boolean} [isDeep] Specify a deep clone.
     * @returns {Object} Returns the cloned data view.
     */
    function cloneDataView(dataView, isDeep) {
      var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
      return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
    }

    /**
     * Creates a clone of `map`.
     *
     * @private
     * @param {Object} map The map to clone.
     * @param {Function} cloneFunc The function to clone values.
     * @param {boolean} [isDeep] Specify a deep clone.
     * @returns {Object} Returns the cloned map.
     */
    function cloneMap(map, isDeep, cloneFunc) {
      var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
      return arrayReduce(array, addMapEntry, new map.constructor);
    }

    /**
     * Creates a clone of `regexp`.
     *
     * @private
     * @param {Object} regexp The regexp to clone.
     * @returns {Object} Returns the cloned regexp.
     */
    function cloneRegExp(regexp) {
      var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
      result.lastIndex = regexp.lastIndex;
      return result;
    }

    /**
     * Creates a clone of `set`.
     *
     * @private
     * @param {Object} set The set to clone.
     * @param {Function} cloneFunc The function to clone values.
     * @param {boolean} [isDeep] Specify a deep clone.
     * @returns {Object} Returns the cloned set.
     */
    function cloneSet(set, isDeep, cloneFunc) {
      var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
      return arrayReduce(array, addSetEntry, new set.constructor);
    }

    /**
     * Creates a clone of the `symbol` object.
     *
     * @private
     * @param {Object} symbol The symbol object to clone.
     * @returns {Object} Returns the cloned symbol object.
     */
    function cloneSymbol(symbol) {
      return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
    }

    /**
     * Creates a clone of `typedArray`.
     *
     * @private
     * @param {Object} typedArray The typed array to clone.
     * @param {boolean} [isDeep] Specify a deep clone.
     * @returns {Object} Returns the cloned typed array.
     */
    function cloneTypedArray(typedArray, isDeep) {
      var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
      return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
    }

    /**
     * Compares values to sort them in ascending order.
     *
     * @private
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {number} Returns the sort order indicator for `value`.
     */
    function compareAscending(value, other) {
      if (value !== other) {
        var valIsDefined = value !== undefined,
            valIsNull = value === null,
            valIsReflexive = value === value,
            valIsSymbol = isSymbol(value);

        var othIsDefined = other !== undefined,
            othIsNull = other === null,
            othIsReflexive = other === other,
            othIsSymbol = isSymbol(other);

        if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
            (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
            (valIsNull && othIsDefined && othIsReflexive) ||
            (!valIsDefined && othIsReflexive) ||
            !valIsReflexive) {
          return 1;
        }
        if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
            (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
            (othIsNull && valIsDefined && valIsReflexive) ||
            (!othIsDefined && valIsReflexive) ||
            !othIsReflexive) {
          return -1;
        }
      }
      return 0;
    }

    /**
     * Used by `_.orderBy` to compare multiple properties of a value to another
     * and stable sort them.
     *
     * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
     * specify an order of "desc" for descending or "asc" for ascending sort order
     * of corresponding values.
     *
     * @private
     * @param {Object} object The object to compare.
     * @param {Object} other The other object to compare.
     * @param {boolean[]|string[]} orders The order to sort by for each property.
     * @returns {number} Returns the sort order indicator for `object`.
     */
    function compareMultiple(object, other, orders) {
      var index = -1,
          objCriteria = object.criteria,
          othCriteria = other.criteria,
          length = objCriteria.length,
          ordersLength = orders.length;

      while (++index < length) {
        var result = compareAscending(objCriteria[index], othCriteria[index]);
        if (result) {
          if (index >= ordersLength) {
            return result;
          }
          var order = orders[index];
          return result * (order == 'desc' ? -1 : 1);
        }
      }
      // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
      // that causes it, under certain circumstances, to provide the same value for
      // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
      // for more details.
      //
      // This also ensures a stable sort in V8 and other engines.
      // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
      return object.index - other.index;
    }

    /**
     * Creates an array that is the composition of partially applied arguments,
     * placeholders, and provided arguments into a single array of arguments.
     *
     * @private
     * @param {Array} args The provided arguments.
     * @param {Array} partials The arguments to prepend to those provided.
     * @param {Array} holders The `partials` placeholder indexes.
     * @params {boolean} [isCurried] Specify composing for a curried function.
     * @returns {Array} Returns the new array of composed arguments.
     */
    function composeArgs(args, partials, holders, isCurried) {
      var argsIndex = -1,
          argsLength = args.length,
          holdersLength = holders.length,
          leftIndex = -1,
          leftLength = partials.length,
          rangeLength = nativeMax(argsLength - holdersLength, 0),
          result = Array(leftLength + rangeLength),
          isUncurried = !isCurried;

      while (++leftIndex < leftLength) {
        result[leftIndex] = partials[leftIndex];
      }
      while (++argsIndex < holdersLength) {
        if (isUncurried || argsIndex < argsLength) {
          result[holders[argsIndex]] = args[argsIndex];
        }
      }
      while (rangeLength--) {
        result[leftIndex++] = args[argsIndex++];
      }
      return result;
    }

    /**
     * This function is like `composeArgs` except that the arguments composition
     * is tailored for `_.partialRight`.
     *
     * @private
     * @param {Array} args The provided arguments.
     * @param {Array} partials The arguments to append to those provided.
     * @param {Array} holders The `partials` placeholder indexes.
     * @params {boolean} [isCurried] Specify composing for a curried function.
     * @returns {Array} Returns the new array of composed arguments.
     */
    function composeArgsRight(args, partials, holders, isCurried) {
      var argsIndex = -1,
          argsLength = args.length,
          holdersIndex = -1,
          holdersLength = holders.length,
          rightIndex = -1,
          rightLength = partials.length,
          rangeLength = nativeMax(argsLength - holdersLength, 0),
          result = Array(rangeLength + rightLength),
          isUncurried = !isCurried;

      while (++argsIndex < rangeLength) {
        result[argsIndex] = args[argsIndex];
      }
      var offset = argsIndex;
      while (++rightIndex < rightLength) {
        result[offset + rightIndex] = partials[rightIndex];
      }
      while (++holdersIndex < holdersLength) {
        if (isUncurried || argsIndex < argsLength) {
          result[offset + holders[holdersIndex]] = args[argsIndex++];
        }
      }
      return result;
    }

    /**
     * Copies the values of `source` to `array`.
     *
     * @private
     * @param {Array} source The array to copy values from.
     * @param {Array} [array=[]] The array to copy values to.
     * @returns {Array} Returns `array`.
     */
    function copyArray(source, array) {
      var index = -1,
          length = source.length;

      array || (array = Array(length));
      while (++index < length) {
        array[index] = source[index];
      }
      return array;
    }

    /**
     * Copies properties of `source` to `object`.
     *
     * @private
     * @param {Object} source The object to copy properties from.
     * @param {Array} props The property identifiers to copy.
     * @param {Object} [object={}] The object to copy properties to.
     * @param {Function} [customizer] The function to customize copied values.
     * @returns {Object} Returns `object`.
     */
    function copyObject(source, props, object, customizer) {
      var isNew = !object;
      object || (object = {});

      var index = -1,
          length = props.length;

      while (++index < length) {
        var key = props[index];

        var newValue = customizer
          ? customizer(object[key], source[key], key, object, source)
          : undefined;

        if (newValue === undefined) {
          newValue = source[key];
        }
        if (isNew) {
          baseAssignValue(object, key, newValue);
        } else {
          assignValue(object, key, newValue);
        }
      }
      return object;
    }

    /**
     * Copies own symbols of `source` to `object`.
     *
     * @private
     * @param {Object} source The object to copy symbols from.
     * @param {Object} [object={}] The object to copy symbols to.
     * @returns {Object} Returns `object`.
     */
    function copySymbols(source, object) {
      return copyObject(source, getSymbols(source), object);
    }

    /**
     * Copies own and inherited symbols of `source` to `object`.
     *
     * @private
     * @param {Object} source The object to copy symbols from.
     * @param {Object} [object={}] The object to copy symbols to.
     * @returns {Object} Returns `object`.
     */
    function copySymbolsIn(source, object) {
      return copyObject(source, getSymbolsIn(source), object);
    }

    /**
     * Creates a function like `_.groupBy`.
     *
     * @private
     * @param {Function} setter The function to set accumulator values.
     * @param {Function} [initializer] The accumulator object initializer.
     * @returns {Function} Returns the new aggregator function.
     */
    function createAggregator(setter, initializer) {
      return function(collection, iteratee) {
        var func = isArray(collection) ? arrayAggregator : baseAggregator,
            accumulator = initializer ? initializer() : {};

        return func(collection, setter, getIteratee(iteratee, 2), accumulator);
      };
    }

    /**
     * Creates a function like `_.assign`.
     *
     * @private
     * @param {Function} assigner The function to assign values.
     * @returns {Function} Returns the new assigner function.
     */
    function createAssigner(assigner) {
      return baseRest(function(object, sources) {
        var index = -1,
            length = sources.length,
            customizer = length > 1 ? sources[length - 1] : undefined,
            guard = length > 2 ? sources[2] : undefined;

        customizer = (assigner.length > 3 && typeof customizer == 'function')
          ? (length--, customizer)
          : undefined;

        if (guard && isIterateeCall(sources[0], sources[1], guard)) {
          customizer = length < 3 ? undefined : customizer;
          length = 1;
        }
        object = Object(object);
        while (++index < length) {
          var source = sources[index];
          if (source) {
            assigner(object, source, index, customizer);
          }
        }
        return object;
      });
    }

    /**
     * Creates a `baseEach` or `baseEachRight` function.
     *
     * @private
     * @param {Function} eachFunc The function to iterate over a collection.
     * @param {boolean} [fromRight] Specify iterating from right to left.
     * @returns {Function} Returns the new base function.
     */
    function createBaseEach(eachFunc, fromRight) {
      return function(collection, iteratee) {
        if (collection == null) {
          return collection;
        }
        if (!isArrayLike(collection)) {
          return eachFunc(collection, iteratee);
        }
        var length = collection.length,
            index = fromRight ? length : -1,
            iterable = Object(collection);

        while ((fromRight ? index-- : ++index < length)) {
          if (iteratee(iterable[index], index, iterable) === false) {
            break;
          }
        }
        return collection;
      };
    }

    /**
     * Creates a base function for methods like `_.forIn` and `_.forOwn`.
     *
     * @private
     * @param {boolean} [fromRight] Specify iterating from right to left.
     * @returns {Function} Returns the new base function.
     */
    function createBaseFor(fromRight) {
      return function(object, iteratee, keysFunc) {
        var index = -1,
            iterable = Object(object),
            props = keysFunc(object),
            length = props.length;

        while (length--) {
          var key = props[fromRight ? length : ++index];
          if (iteratee(iterable[key], key, iterable) === false) {
            break;
          }
        }
        return object;
      };
    }

    /**
     * Creates a function that wraps `func` to invoke it with the optional `this`
     * binding of `thisArg`.
     *
     * @private
     * @param {Function} func The function to wrap.
     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
     * @param {*} [thisArg] The `this` binding of `func`.
     * @returns {Function} Returns the new wrapped function.
     */
    function createBind(func, bitmask, thisArg) {
      var isBind = bitmask & WRAP_BIND_FLAG,
          Ctor = createCtor(func);

      function wrapper() {
        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
        return fn.apply(isBind ? thisArg : this, arguments);
      }
      return wrapper;
    }

    /**
     * Creates a function like `_.lowerFirst`.
     *
     * @private
     * @param {string} methodName The name of the `String` case method to use.
     * @returns {Function} Returns the new case function.
     */
    function createCaseFirst(methodName) {
      return function(string) {
        string = toString(string);

        var strSymbols = hasUnicode(string)
          ? stringToArray(string)
          : undefined;

        var chr = strSymbols
          ? strSymbols[0]
          : string.charAt(0);

        var trailing = strSymbols
          ? castSlice(strSymbols, 1).join('')
          : string.slice(1);

        return chr[methodName]() + trailing;
      };
    }

    /**
     * Creates a function like `_.camelCase`.
     *
     * @private
     * @param {Function} callback The function to combine each word.
     * @returns {Function} Returns the new compounder function.
     */
    function createCompounder(callback) {
      return function(string) {
        return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
      };
    }

    /**
     * Creates a function that produces an instance of `Ctor` regardless of
     * whether it was invoked as part of a `new` expression or by `call` or `apply`.
     *
     * @private
     * @param {Function} Ctor The constructor to wrap.
     * @returns {Function} Returns the new wrapped function.
     */
    function createCtor(Ctor) {
      return function() {
        // Use a `switch` statement to work with class constructors. See
        // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
        // for more details.
        var args = arguments;
        switch (args.length) {
          case 0: return new Ctor;
          case 1: return new Ctor(args[0]);
          case 2: return new Ctor(args[0], args[1]);
          case 3: return new Ctor(args[0], args[1], args[2]);
          case 4: return new Ctor(args[0], args[1], args[2], args[3]);
          case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
          case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
          case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
        }
        var thisBinding = baseCreate(Ctor.prototype),
            result = Ctor.apply(thisBinding, args);

        // Mimic the constructor's `return` behavior.
        // See https://es5.github.io/#x13.2.2 for more details.
        return isObject(result) ? result : thisBinding;
      };
    }

    /**
     * Creates a function that wraps `func` to enable currying.
     *
     * @private
     * @param {Function} func The function to wrap.
     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
     * @param {number} arity The arity of `func`.
     * @returns {Function} Returns the new wrapped function.
     */
    function createCurry(func, bitmask, arity) {
      var Ctor = createCtor(func);

      function wrapper() {
        var length = arguments.length,
            args = Array(length),
            index = length,
            placeholder = getHolder(wrapper);

        while (index--) {
          args[index] = arguments[index];
        }
        var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
          ? []
          : replaceHolders(args, placeholder);

        length -= holders.length;
        if (length < arity) {
          return createRecurry(
            func, bitmask, createHybrid, wrapper.placeholder, undefined,
            args, holders, undefined, undefined, arity - length);
        }
        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
        return apply(fn, this, args);
      }
      return wrapper;
    }

    /**
     * Creates a `_.find` or `_.findLast` function.
     *
     * @private
     * @param {Function} findIndexFunc The function to find the collection index.
     * @returns {Function} Returns the new find function.
     */
    function createFind(findIndexFunc) {
      return function(collection, predicate, fromIndex) {
        var iterable = Object(collection);
        if (!isArrayLike(collection)) {
          var iteratee = getIteratee(predicate, 3);
          collection = keys(collection);
          predicate = function(key) { return iteratee(iterable[key], key, iterable); };
        }
        var index = findIndexFunc(collection, predicate, fromIndex);
        return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
      };
    }

    /**
     * Creates a `_.flow` or `_.flowRight` function.
     *
     * @private
     * @param {boolean} [fromRight] Specify iterating from right to left.
     * @returns {Function} Returns the new flow function.
     */
    function createFlow(fromRight) {
      return flatRest(function(funcs) {
        var length = funcs.length,
            index = length,
            prereq = LodashWrapper.prototype.thru;

        if (fromRight) {
          funcs.reverse();
        }
        while (index--) {
          var func = funcs[index];
          if (typeof func != 'function') {
            throw new TypeError(FUNC_ERROR_TEXT);
          }
          if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
            var wrapper = new LodashWrapper([], true);
          }
        }
        index = wrapper ? index : length;
        while (++index < length) {
          func = funcs[index];

          var funcName = getFuncName(func),
              data = funcName == 'wrapper' ? getData(func) : undefined;

          if (data && isLaziable(data[0]) &&
                data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
                !data[4].length && data[9] == 1
              ) {
            wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
          } else {
            wrapper = (func.length == 1 && isLaziable(func))
              ? wrapper[funcName]()
              : wrapper.thru(func);
          }
        }
        return function() {
          var args = arguments,
              value = args[0];

          if (wrapper && args.length == 1 && isArray(value)) {
            return wrapper.plant(value).value();
          }
          var index = 0,
              result = length ? funcs[index].apply(this, args) : value;

          while (++index < length) {
            result = funcs[index].call(this, result);
          }
          return result;
        };
      });
    }

    /**
     * Creates a function that wraps `func` to invoke it with optional `this`
     * binding of `thisArg`, partial application, and currying.
     *
     * @private
     * @param {Function|string} func The function or method name to wrap.
     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
     * @param {*} [thisArg] The `this` binding of `func`.
     * @param {Array} [partials] The arguments to prepend to those provided to
     *  the new function.
     * @param {Array} [holders] The `partials` placeholder indexes.
     * @param {Array} [partialsRight] The arguments to append to those provided
     *  to the new function.
     * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
     * @param {Array} [argPos] The argument positions of the new function.
     * @param {number} [ary] The arity cap of `func`.
     * @param {number} [arity] The arity of `func`.
     * @returns {Function} Returns the new wrapped function.
     */
    function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
      var isAry = bitmask & WRAP_ARY_FLAG,
          isBind = bitmask & WRAP_BIND_FLAG,
          isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
          isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
          isFlip = bitmask & WRAP_FLIP_FLAG,
          Ctor = isBindKey ? undefined : createCtor(func);

      function wrapper() {
        var length = arguments.length,
            args = Array(length),
            index = length;

        while (index--) {
          args[index] = arguments[index];
        }
        if (isCurried) {
          var placeholder = getHolder(wrapper),
              holdersCount = countHolders(args, placeholder);
        }
        if (partials) {
          args = composeArgs(args, partials, holders, isCurried);
        }
        if (partialsRight) {
          args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
        }
        length -= holdersCount;
        if (isCurried && length < arity) {
          var newHolders = replaceHolders(args, placeholder);
          return createRecurry(
            func, bitmask, createHybrid, wrapper.placeholder, thisArg,
            args, newHolders, argPos, ary, arity - length
          );
        }
        var thisBinding = isBind ? thisArg : this,
            fn = isBindKey ? thisBinding[func] : func;

        length = args.length;
        if (argPos) {
          args = reorder(args, argPos);
        } else if (isFlip && length > 1) {
          args.reverse();
        }
        if (isAry && ary < length) {
          args.length = ary;
        }
        if (this && this !== root && this instanceof wrapper) {
          fn = Ctor || createCtor(fn);
        }
        return fn.apply(thisBinding, args);
      }
      return wrapper;
    }

    /**
     * Creates a function like `_.invertBy`.
     *
     * @private
     * @param {Function} setter The function to set accumulator values.
     * @param {Function} toIteratee The function to resolve iteratees.
     * @returns {Function} Returns the new inverter function.
     */
    function createInverter(setter, toIteratee) {
      return function(object, iteratee) {
        return baseInverter(object, setter, toIteratee(iteratee), {});
      };
    }

    /**
     * Creates a function that performs a mathematical operation on two values.
     *
     * @private
     * @param {Function} operator The function to perform the operation.
     * @param {number} [defaultValue] The value used for `undefined` arguments.
     * @returns {Function} Returns the new mathematical operation function.
     */
    function createMathOperation(operator, defaultValue) {
      return function(value, other) {
        var result;
        if (value === undefined && other === undefined) {
          return defaultValue;
        }
        if (value !== undefined) {
          result = value;
        }
        if (other !== undefined) {
          if (result === undefined) {
            return other;
          }
          if (typeof value == 'string' || typeof other == 'string') {
            value = baseToString(value);
            other = baseToString(other);
          } else {
            value = baseToNumber(value);
            other = baseToNumber(other);
          }
          result = operator(value, other);
        }
        return result;
      };
    }

    /**
     * Creates a function like `_.over`.
     *
     * @private
     * @param {Function} arrayFunc The function to iterate over iteratees.
     * @returns {Function} Returns the new over function.
     */
    function createOver(arrayFunc) {
      return flatRest(function(iteratees) {
        iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
        return baseRest(function(args) {
          var thisArg = this;
          return arrayFunc(iteratees, function(iteratee) {
            return apply(iteratee, thisArg, args);
          });
        });
      });
    }

    /**
     * Creates the padding for `string` based on `length`. The `chars` string
     * is truncated if the number of characters exceeds `length`.
     *
     * @private
     * @param {number} length The padding length.
     * @param {string} [chars=' '] The string used as padding.
     * @returns {string} Returns the padding for `string`.
     */
    function createPadding(length, chars) {
      chars = chars === undefined ? ' ' : baseToString(chars);

      var charsLength = chars.length;
      if (charsLength < 2) {
        return charsLength ? baseRepeat(chars, length) : chars;
      }
      var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
      return hasUnicode(chars)
        ? castSlice(stringToArray(result), 0, length).join('')
        : result.slice(0, length);
    }

    /**
     * Creates a function that wraps `func` to invoke it with the `this` binding
     * of `thisArg` and `partials` prepended to the arguments it receives.
     *
     * @private
     * @param {Function} func The function to wrap.
     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
     * @param {*} thisArg The `this` binding of `func`.
     * @param {Array} partials The arguments to prepend to those provided to
     *  the new function.
     * @returns {Function} Returns the new wrapped function.
     */
    function createPartial(func, bitmask, thisArg, partials) {
      var isBind = bitmask & WRAP_BIND_FLAG,
          Ctor = createCtor(func);

      function wrapper() {
        var argsIndex = -1,
            argsLength = arguments.length,
            leftIndex = -1,
            leftLength = partials.length,
            args = Array(leftLength + argsLength),
            fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;

        while (++leftIndex < leftLength) {
          args[leftIndex] = partials[leftIndex];
        }
        while (argsLength--) {
          args[leftIndex++] = arguments[++argsIndex];
        }
        return apply(fn, isBind ? thisArg : this, args);
      }
      return wrapper;
    }

    /**
     * Creates a `_.range` or `_.rangeRight` function.
     *
     * @private
     * @param {boolean} [fromRight] Specify iterating from right to left.
     * @returns {Function} Returns the new range function.
     */
    function createRange(fromRight) {
      return function(start, end, step) {
        if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
          end = step = undefined;
        }
        // Ensure the sign of `-0` is preserved.
        start = toFinite(start);
        if (end === undefined) {
          end = start;
          start = 0;
        } else {
          end = toFinite(end);
        }
        step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
        return baseRange(start, end, step, fromRight);
      };
    }

    /**
     * Creates a function that performs a relational operation on two values.
     *
     * @private
     * @param {Function} operator The function to perform the operation.
     * @returns {Function} Returns the new relational operation function.
     */
    function createRelationalOperation(operator) {
      return function(value, other) {
        if (!(typeof value == 'string' && typeof other == 'string')) {
          value = toNumber(value);
          other = toNumber(other);
        }
        return operator(value, other);
      };
    }

    /**
     * Creates a function that wraps `func` to continue currying.
     *
     * @private
     * @param {Function} func The function to wrap.
     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
     * @param {Function} wrapFunc The function to create the `func` wrapper.
     * @param {*} placeholder The placeholder value.
     * @param {*} [thisArg] The `this` binding of `func`.
     * @param {Array} [partials] The arguments to prepend to those provided to
     *  the new function.
     * @param {Array} [holders] The `partials` placeholder indexes.
     * @param {Array} [argPos] The argument positions of the new function.
     * @param {number} [ary] The arity cap of `func`.
     * @param {number} [arity] The arity of `func`.
     * @returns {Function} Returns the new wrapped function.
     */
    function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
      var isCurry = bitmask & WRAP_CURRY_FLAG,
          newHolders = isCurry ? holders : undefined,
          newHoldersRight = isCurry ? undefined : holders,
          newPartials = isCurry ? partials : undefined,
          newPartialsRight = isCurry ? undefined : partials;

      bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
      bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);

      if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
        bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
      }
      var newData = [
        func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
        newHoldersRight, argPos, ary, arity
      ];

      var result = wrapFunc.apply(undefined, newData);
      if (isLaziable(func)) {
        setData(result, newData);
      }
      result.placeholder = placeholder;
      return setWrapToString(result, func, bitmask);
    }

    /**
     * Creates a function like `_.round`.
     *
     * @private
     * @param {string} methodName The name of the `Math` method to use when rounding.
     * @returns {Function} Returns the new round function.
     */
    function createRound(methodName) {
      var func = Math[methodName];
      return function(number, precision) {
        number = toNumber(number);
        precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
        if (precision) {
          // Shift with exponential notation to avoid floating-point issues.
          // See [MDN](https://mdn.io/round#Examples) for more details.
          var pair = (toString(number) + 'e').split('e'),
              value = func(pair[0] + 'e' + (+pair[1] + precision));

          pair = (toString(value) + 'e').split('e');
          return +(pair[0] + 'e' + (+pair[1] - precision));
        }
        return func(number);
      };
    }

    /**
     * Creates a set object of `values`.
     *
     * @private
     * @param {Array} values The values to add to the set.
     * @returns {Object} Returns the new set.
     */
    var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
      return new Set(values);
    };

    /**
     * Creates a `_.toPairs` or `_.toPairsIn` function.
     *
     * @private
     * @param {Function} keysFunc The function to get the keys of a given object.
     * @returns {Function} Returns the new pairs function.
     */
    function createToPairs(keysFunc) {
      return function(object) {
        var tag = getTag(object);
        if (tag == mapTag) {
          return mapToArray(object);
        }
        if (tag == setTag) {
          return setToPairs(object);
        }
        return baseToPairs(object, keysFunc(object));
      };
    }

    /**
     * Creates a function that either curries or invokes `func` with optional
     * `this` binding and partially applied arguments.
     *
     * @private
     * @param {Function|string} func The function or method name to wrap.
     * @param {number} bitmask The bitmask flags.
     *    1 - `_.bind`
     *    2 - `_.bindKey`
     *    4 - `_.curry` or `_.curryRight` of a bound function
     *    8 - `_.curry`
     *   16 - `_.curryRight`
     *   32 - `_.partial`
     *   64 - `_.partialRight`
     *  128 - `_.rearg`
     *  256 - `_.ary`
     *  512 - `_.flip`
     * @param {*} [thisArg] The `this` binding of `func`.
     * @param {Array} [partials] The arguments to be partially applied.
     * @param {Array} [holders] The `partials` placeholder indexes.
     * @param {Array} [argPos] The argument positions of the new function.
     * @param {number} [ary] The arity cap of `func`.
     * @param {number} [arity] The arity of `func`.
     * @returns {Function} Returns the new wrapped function.
     */
    function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
      var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
      if (!isBindKey && typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      var length = partials ? partials.length : 0;
      if (!length) {
        bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
        partials = holders = undefined;
      }
      ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
      arity = arity === undefined ? arity : toInteger(arity);
      length -= holders ? holders.length : 0;

      if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
        var partialsRight = partials,
            holdersRight = holders;

        partials = holders = undefined;
      }
      var data = isBindKey ? undefined : getData(func);

      var newData = [
        func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
        argPos, ary, arity
      ];

      if (data) {
        mergeData(newData, data);
      }
      func = newData[0];
      bitmask = newData[1];
      thisArg = newData[2];
      partials = newData[3];
      holders = newData[4];
      arity = newData[9] = newData[9] === undefined
        ? (isBindKey ? 0 : func.length)
        : nativeMax(newData[9] - length, 0);

      if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
        bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
      }
      if (!bitmask || bitmask == WRAP_BIND_FLAG) {
        var result = createBind(func, bitmask, thisArg);
      } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
        result = createCurry(func, bitmask, arity);
      } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
        result = createPartial(func, bitmask, thisArg, partials);
      } else {
        result = createHybrid.apply(undefined, newData);
      }
      var setter = data ? baseSetData : setData;
      return setWrapToString(setter(result, newData), func, bitmask);
    }

    /**
     * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
     * of source objects to the destination object for all destination properties
     * that resolve to `undefined`.
     *
     * @private
     * @param {*} objValue The destination value.
     * @param {*} srcValue The source value.
     * @param {string} key The key of the property to assign.
     * @param {Object} object The parent object of `objValue`.
     * @returns {*} Returns the value to assign.
     */
    function customDefaultsAssignIn(objValue, srcValue, key, object) {
      if (objValue === undefined ||
          (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
        return srcValue;
      }
      return objValue;
    }

    /**
     * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
     * objects into destination objects that are passed thru.
     *
     * @private
     * @param {*} objValue The destination value.
     * @param {*} srcValue The source value.
     * @param {string} key The key of the property to merge.
     * @param {Object} object The parent object of `objValue`.
     * @param {Object} source The parent object of `srcValue`.
     * @param {Object} [stack] Tracks traversed source values and their merged
     *  counterparts.
     * @returns {*} Returns the value to assign.
     */
    function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
      if (isObject(objValue) && isObject(srcValue)) {
        // Recursively merge objects and arrays (susceptible to call stack limits).
        stack.set(srcValue, objValue);
        baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
        stack['delete'](srcValue);
      }
      return objValue;
    }

    /**
     * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
     * objects.
     *
     * @private
     * @param {*} value The value to inspect.
     * @param {string} key The key of the property to inspect.
     * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
     */
    function customOmitClone(value) {
      return isPlainObject(value) ? undefined : value;
    }

    /**
     * A specialized version of `baseIsEqualDeep` for arrays with support for
     * partial deep comparisons.
     *
     * @private
     * @param {Array} array The array to compare.
     * @param {Array} other The other array to compare.
     * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
     * @param {Function} customizer The function to customize comparisons.
     * @param {Function} equalFunc The function to determine equivalents of values.
     * @param {Object} stack Tracks traversed `array` and `other` objects.
     * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
     */
    function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
      var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
          arrLength = array.length,
          othLength = other.length;

      if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(array);
      if (stacked && stack.get(other)) {
        return stacked == other;
      }
      var index = -1,
          result = true,
          seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;

      stack.set(array, other);
      stack.set(other, array);

      // Ignore non-index properties.
      while (++index < arrLength) {
        var arrValue = array[index],
            othValue = other[index];

        if (customizer) {
          var compared = isPartial
            ? customizer(othValue, arrValue, index, other, array, stack)
            : customizer(arrValue, othValue, index, array, other, stack);
        }
        if (compared !== undefined) {
          if (compared) {
            continue;
          }
          result = false;
          break;
        }
        // Recursively compare arrays (susceptible to call stack limits).
        if (seen) {
          if (!arraySome(other, function(othValue, othIndex) {
                if (!cacheHas(seen, othIndex) &&
                    (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
                  return seen.push(othIndex);
                }
              })) {
            result = false;
            break;
          }
        } else if (!(
              arrValue === othValue ||
                equalFunc(arrValue, othValue, bitmask, customizer, stack)
            )) {
          result = false;
          break;
        }
      }
      stack['delete'](array);
      stack['delete'](other);
      return result;
    }

    /**
     * A specialized version of `baseIsEqualDeep` for comparing objects of
     * the same `toStringTag`.
     *
     * **Note:** This function only supports comparing values with tags of
     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
     *
     * @private
     * @param {Object} object The object to compare.
     * @param {Object} other The other object to compare.
     * @param {string} tag The `toStringTag` of the objects to compare.
     * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
     * @param {Function} customizer The function to customize comparisons.
     * @param {Function} equalFunc The function to determine equivalents of values.
     * @param {Object} stack Tracks traversed `object` and `other` objects.
     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
     */
    function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
      switch (tag) {
        case dataViewTag:
          if ((object.byteLength != other.byteLength) ||
              (object.byteOffset != other.byteOffset)) {
            return false;
          }
          object = object.buffer;
          other = other.buffer;

        case arrayBufferTag:
          if ((object.byteLength != other.byteLength) ||
              !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
            return false;
          }
          return true;

        case boolTag:
        case dateTag:
        case numberTag:
          // Coerce booleans to `1` or `0` and dates to milliseconds.
          // Invalid dates are coerced to `NaN`.
          return eq(+object, +other);

        case errorTag:
          return object.name == other.name && object.message == other.message;

        case regexpTag:
        case stringTag:
          // Coerce regexes to strings and treat strings, primitives and objects,
          // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
          // for more details.
          return object == (other + '');

        case mapTag:
          var convert = mapToArray;

        case setTag:
          var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
          convert || (convert = setToArray);

          if (object.size != other.size && !isPartial) {
            return false;
          }
          // Assume cyclic values are equal.
          var stacked = stack.get(object);
          if (stacked) {
            return stacked == other;
          }
          bitmask |= COMPARE_UNORDERED_FLAG;

          // Recursively compare objects (susceptible to call stack limits).
          stack.set(object, other);
          var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
          stack['delete'](object);
          return result;

        case symbolTag:
          if (symbolValueOf) {
            return symbolValueOf.call(object) == symbolValueOf.call(other);
          }
      }
      return false;
    }

    /**
     * A specialized version of `baseIsEqualDeep` for objects with support for
     * partial deep comparisons.
     *
     * @private
     * @param {Object} object The object to compare.
     * @param {Object} other The other object to compare.
     * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
     * @param {Function} customizer The function to customize comparisons.
     * @param {Function} equalFunc The function to determine equivalents of values.
     * @param {Object} stack Tracks traversed `object` and `other` objects.
     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
     */
    function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
      var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
          objProps = getAllKeys(object),
          objLength = objProps.length,
          othProps = getAllKeys(other),
          othLength = othProps.length;

      if (objLength != othLength && !isPartial) {
        return false;
      }
      var index = objLength;
      while (index--) {
        var key = objProps[index];
        if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
          return false;
        }
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked && stack.get(other)) {
        return stacked == other;
      }
      var result = true;
      stack.set(object, other);
      stack.set(other, object);

      var skipCtor = isPartial;
      while (++index < objLength) {
        key = objProps[index];
        var objValue = object[key],
            othValue = other[key];

        if (customizer) {
          var compared = isPartial
            ? customizer(othValue, objValue, key, other, object, stack)
            : customizer(objValue, othValue, key, object, other, stack);
        }
        // Recursively compare objects (susceptible to call stack limits).
        if (!(compared === undefined
              ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
              : compared
            )) {
          result = false;
          break;
        }
        skipCtor || (skipCtor = key == 'constructor');
      }
      if (result && !skipCtor) {
        var objCtor = object.constructor,
            othCtor = other.constructor;

        // Non `Object` object instances with different constructors are not equal.
        if (objCtor != othCtor &&
            ('constructor' in object && 'constructor' in other) &&
            !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
              typeof othCtor == 'function' && othCtor instanceof othCtor)) {
          result = false;
        }
      }
      stack['delete'](object);
      stack['delete'](other);
      return result;
    }

    /**
     * A specialized version of `baseRest` which flattens the rest array.
     *
     * @private
     * @param {Function} func The function to apply a rest parameter to.
     * @returns {Function} Returns the new function.
     */
    function flatRest(func) {
      return setToString(overRest(func, undefined, flatten), func + '');
    }

    /**
     * Creates an array of own enumerable property names and symbols of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names and symbols.
     */
    function getAllKeys(object) {
      return baseGetAllKeys(object, keys, getSymbols);
    }

    /**
     * Creates an array of own and inherited enumerable property names and
     * symbols of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names and symbols.
     */
    function getAllKeysIn(object) {
      return baseGetAllKeys(object, keysIn, getSymbolsIn);
    }

    /**
     * Gets metadata for `func`.
     *
     * @private
     * @param {Function} func The function to query.
     * @returns {*} Returns the metadata for `func`.
     */
    var getData = !metaMap ? noop : function(func) {
      return metaMap.get(func);
    };

    /**
     * Gets the name of `func`.
     *
     * @private
     * @param {Function} func The function to query.
     * @returns {string} Returns the function name.
     */
    function getFuncName(func) {
      var result = (func.name + ''),
          array = realNames[result],
          length = hasOwnProperty.call(realNames, result) ? array.length : 0;

      while (length--) {
        var data = array[length],
            otherFunc = data.func;
        if (otherFunc == null || otherFunc == func) {
          return data.name;
        }
      }
      return result;
    }

    /**
     * Gets the argument placeholder value for `func`.
     *
     * @private
     * @param {Function} func The function to inspect.
     * @returns {*} Returns the placeholder value.
     */
    function getHolder(func) {
      var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
      return object.placeholder;
    }

    /**
     * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
     * this function returns the custom method, otherwise it returns `baseIteratee`.
     * If arguments are provided, the chosen function is invoked with them and
     * its result is returned.
     *
     * @private
     * @param {*} [value] The value to convert to an iteratee.
     * @param {number} [arity] The arity of the created iteratee.
     * @returns {Function} Returns the chosen function or its result.
     */
    function getIteratee() {
      var result = lodash.iteratee || iteratee;
      result = result === iteratee ? baseIteratee : result;
      return arguments.length ? result(arguments[0], arguments[1]) : result;
    }

    /**
     * Gets the data for `map`.
     *
     * @private
     * @param {Object} map The map to query.
     * @param {string} key The reference key.
     * @returns {*} Returns the map data.
     */
    function getMapData(map, key) {
      var data = map.__data__;
      return isKeyable(key)
        ? data[typeof key == 'string' ? 'string' : 'hash']
        : data.map;
    }

    /**
     * Gets the property names, values, and compare flags of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the match data of `object`.
     */
    function getMatchData(object) {
      var result = keys(object),
          length = result.length;

      while (length--) {
        var key = result[length],
            value = object[key];

        result[length] = [key, value, isStrictComparable(value)];
      }
      return result;
    }

    /**
     * Gets the native function at `key` of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {string} key The key of the method to get.
     * @returns {*} Returns the function if it's native, else `undefined`.
     */
    function getNative(object, key) {
      var value = getValue(object, key);
      return baseIsNative(value) ? value : undefined;
    }

    /**
     * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
     *
     * @private
     * @param {*} value The value to query.
     * @returns {string} Returns the raw `toStringTag`.
     */
    function getRawTag(value) {
      var isOwn = hasOwnProperty.call(value, symToStringTag),
          tag = value[symToStringTag];

      try {
        value[symToStringTag] = undefined;
        var unmasked = true;
      } catch (e) {}

      var result = nativeObjectToString.call(value);
      if (unmasked) {
        if (isOwn) {
          value[symToStringTag] = tag;
        } else {
          delete value[symToStringTag];
        }
      }
      return result;
    }

    /**
     * Creates an array of the own enumerable symbols of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of symbols.
     */
    var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
      if (object == null) {
        return [];
      }
      object = Object(object);
      return arrayFilter(nativeGetSymbols(object), function(symbol) {
        return propertyIsEnumerable.call(object, symbol);
      });
    };

    /**
     * Creates an array of the own and inherited enumerable symbols of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of symbols.
     */
    var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
      var result = [];
      while (object) {
        arrayPush(result, getSymbols(object));
        object = getPrototype(object);
      }
      return result;
    };

    /**
     * Gets the `toStringTag` of `value`.
     *
     * @private
     * @param {*} value The value to query.
     * @returns {string} Returns the `toStringTag`.
     */
    var getTag = baseGetTag;

    // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
    if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
        (Map && getTag(new Map) != mapTag) ||
        (Promise && getTag(Promise.resolve()) != promiseTag) ||
        (Set && getTag(new Set) != setTag) ||
        (WeakMap && getTag(new WeakMap) != weakMapTag)) {
      getTag = function(value) {
        var result = baseGetTag(value),
            Ctor = result == objectTag ? value.constructor : undefined,
            ctorString = Ctor ? toSource(Ctor) : '';

        if (ctorString) {
          switch (ctorString) {
            case dataViewCtorString: return dataViewTag;
            case mapCtorString: return mapTag;
            case promiseCtorString: return promiseTag;
            case setCtorString: return setTag;
            case weakMapCtorString: return weakMapTag;
          }
        }
        return result;
      };
    }

    /**
     * Gets the view, applying any `transforms` to the `start` and `end` positions.
     *
     * @private
     * @param {number} start The start of the view.
     * @param {number} end The end of the view.
     * @param {Array} transforms The transformations to apply to the view.
     * @returns {Object} Returns an object containing the `start` and `end`
     *  positions of the view.
     */
    function getView(start, end, transforms) {
      var index = -1,
          length = transforms.length;

      while (++index < length) {
        var data = transforms[index],
            size = data.size;

        switch (data.type) {
          case 'drop':      start += size; break;
          case 'dropRight': end -= size; break;
          case 'take':      end = nativeMin(end, start + size); break;
          case 'takeRight': start = nativeMax(start, end - size); break;
        }
      }
      return { 'start': start, 'end': end };
    }

    /**
     * Extracts wrapper details from the `source` body comment.
     *
     * @private
     * @param {string} source The source to inspect.
     * @returns {Array} Returns the wrapper details.
     */
    function getWrapDetails(source) {
      var match = source.match(reWrapDetails);
      return match ? match[1].split(reSplitDetails) : [];
    }

    /**
     * Checks if `path` exists on `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {Array|string} path The path to check.
     * @param {Function} hasFunc The function to check properties.
     * @returns {boolean} Returns `true` if `path` exists, else `false`.
     */
    function hasPath(object, path, hasFunc) {
      path = castPath(path, object);

      var index = -1,
          length = path.length,
          result = false;

      while (++index < length) {
        var key = toKey(path[index]);
        if (!(result = object != null && hasFunc(object, key))) {
          break;
        }
        object = object[key];
      }
      if (result || ++index != length) {
        return result;
      }
      length = object == null ? 0 : object.length;
      return !!length && isLength(length) && isIndex(key, length) &&
        (isArray(object) || isArguments(object));
    }

    /**
     * Initializes an array clone.
     *
     * @private
     * @param {Array} array The array to clone.
     * @returns {Array} Returns the initialized clone.
     */
    function initCloneArray(array) {
      var length = array.length,
          result = array.constructor(length);

      // Add properties assigned by `RegExp#exec`.
      if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
        result.index = array.index;
        result.input = array.input;
      }
      return result;
    }

    /**
     * Initializes an object clone.
     *
     * @private
     * @param {Object} object The object to clone.
     * @returns {Object} Returns the initialized clone.
     */
    function initCloneObject(object) {
      return (typeof object.constructor == 'function' && !isPrototype(object))
        ? baseCreate(getPrototype(object))
        : {};
    }

    /**
     * Initializes an object clone based on its `toStringTag`.
     *
     * **Note:** This function only supports cloning values with tags of
     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
     *
     * @private
     * @param {Object} object The object to clone.
     * @param {string} tag The `toStringTag` of the object to clone.
     * @param {Function} cloneFunc The function to clone values.
     * @param {boolean} [isDeep] Specify a deep clone.
     * @returns {Object} Returns the initialized clone.
     */
    function initCloneByTag(object, tag, cloneFunc, isDeep) {
      var Ctor = object.constructor;
      switch (tag) {
        case arrayBufferTag:
          return cloneArrayBuffer(object);

        case boolTag:
        case dateTag:
          return new Ctor(+object);

        case dataViewTag:
          return cloneDataView(object, isDeep);

        case float32Tag: case float64Tag:
        case int8Tag: case int16Tag: case int32Tag:
        case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
          return cloneTypedArray(object, isDeep);

        case mapTag:
          return cloneMap(object, isDeep, cloneFunc);

        case numberTag:
        case stringTag:
          return new Ctor(object);

        case regexpTag:
          return cloneRegExp(object);

        case setTag:
          return cloneSet(object, isDeep, cloneFunc);

        case symbolTag:
          return cloneSymbol(object);
      }
    }

    /**
     * Inserts wrapper `details` in a comment at the top of the `source` body.
     *
     * @private
     * @param {string} source The source to modify.
     * @returns {Array} details The details to insert.
     * @returns {string} Returns the modified source.
     */
    function insertWrapDetails(source, details) {
      var length = details.length;
      if (!length) {
        return source;
      }
      var lastIndex = length - 1;
      details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
      details = details.join(length > 2 ? ', ' : ' ');
      return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
    }

    /**
     * Checks if `value` is a flattenable `arguments` object or array.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
     */
    function isFlattenable(value) {
      return isArray(value) || isArguments(value) ||
        !!(spreadableSymbol && value && value[spreadableSymbol]);
    }

    /**
     * Checks if `value` is a valid array-like index.
     *
     * @private
     * @param {*} value The value to check.
     * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
     * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
     */
    function isIndex(value, length) {
      length = length == null ? MAX_SAFE_INTEGER : length;
      return !!length &&
        (typeof value == 'number' || reIsUint.test(value)) &&
        (value > -1 && value % 1 == 0 && value < length);
    }

    /**
     * Checks if the given arguments are from an iteratee call.
     *
     * @private
     * @param {*} value The potential iteratee value argument.
     * @param {*} index The potential iteratee index or key argument.
     * @param {*} object The potential iteratee object argument.
     * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
     *  else `false`.
     */
    function isIterateeCall(value, index, object) {
      if (!isObject(object)) {
        return false;
      }
      var type = typeof index;
      if (type == 'number'
            ? (isArrayLike(object) && isIndex(index, object.length))
            : (type == 'string' && index in object)
          ) {
        return eq(object[index], value);
      }
      return false;
    }

    /**
     * Checks if `value` is a property name and not a property path.
     *
     * @private
     * @param {*} value The value to check.
     * @param {Object} [object] The object to query keys on.
     * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
     */
    function isKey(value, object) {
      if (isArray(value)) {
        return false;
      }
      var type = typeof value;
      if (type == 'number' || type == 'symbol' || type == 'boolean' ||
          value == null || isSymbol(value)) {
        return true;
      }
      return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
        (object != null && value in Object(object));
    }

    /**
     * Checks if `value` is suitable for use as unique object key.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
     */
    function isKeyable(value) {
      var type = typeof value;
      return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
        ? (value !== '__proto__')
        : (value === null);
    }

    /**
     * Checks if `func` has a lazy counterpart.
     *
     * @private
     * @param {Function} func The function to check.
     * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
     *  else `false`.
     */
    function isLaziable(func) {
      var funcName = getFuncName(func),
          other = lodash[funcName];

      if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
        return false;
      }
      if (func === other) {
        return true;
      }
      var data = getData(other);
      return !!data && func === data[0];
    }

    /**
     * Checks if `func` has its source masked.
     *
     * @private
     * @param {Function} func The function to check.
     * @returns {boolean} Returns `true` if `func` is masked, else `false`.
     */
    function isMasked(func) {
      return !!maskSrcKey && (maskSrcKey in func);
    }

    /**
     * Checks if `func` is capable of being masked.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
     */
    var isMaskable = coreJsData ? isFunction : stubFalse;

    /**
     * Checks if `value` is likely a prototype object.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
     */
    function isPrototype(value) {
      var Ctor = value && value.constructor,
          proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

      return value === proto;
    }

    /**
     * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
     *
     * @private
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` if suitable for strict
     *  equality comparisons, else `false`.
     */
    function isStrictComparable(value) {
      return value === value && !isObject(value);
    }

    /**
     * A specialized version of `matchesProperty` for source values suitable
     * for strict equality comparisons, i.e. `===`.
     *
     * @private
     * @param {string} key The key of the property to get.
     * @param {*} srcValue The value to match.
     * @returns {Function} Returns the new spec function.
     */
    function matchesStrictComparable(key, srcValue) {
      return function(object) {
        if (object == null) {
          return false;
        }
        return object[key] === srcValue &&
          (srcValue !== undefined || (key in Object(object)));
      };
    }

    /**
     * A specialized version of `_.memoize` which clears the memoized function's
     * cache when it exceeds `MAX_MEMOIZE_SIZE`.
     *
     * @private
     * @param {Function} func The function to have its output memoized.
     * @returns {Function} Returns the new memoized function.
     */
    function memoizeCapped(func) {
      var result = memoize(func, function(key) {
        if (cache.size === MAX_MEMOIZE_SIZE) {
          cache.clear();
        }
        return key;
      });

      var cache = result.cache;
      return result;
    }

    /**
     * Merges the function metadata of `source` into `data`.
     *
     * Merging metadata reduces the number of wrappers used to invoke a function.
     * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
     * may be applied regardless of execution order. Methods like `_.ary` and
     * `_.rearg` modify function arguments, making the order in which they are
     * executed important, preventing the merging of metadata. However, we make
     * an exception for a safe combined case where curried functions have `_.ary`
     * and or `_.rearg` applied.
     *
     * @private
     * @param {Array} data The destination metadata.
     * @param {Array} source The source metadata.
     * @returns {Array} Returns `data`.
     */
    function mergeData(data, source) {
      var bitmask = data[1],
          srcBitmask = source[1],
          newBitmask = bitmask | srcBitmask,
          isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);

      var isCombo =
        ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
        ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
        ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));

      // Exit early if metadata can't be merged.
      if (!(isCommon || isCombo)) {
        return data;
      }
      // Use source `thisArg` if available.
      if (srcBitmask & WRAP_BIND_FLAG) {
        data[2] = source[2];
        // Set when currying a bound function.
        newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
      }
      // Compose partial arguments.
      var value = source[3];
      if (value) {
        var partials = data[3];
        data[3] = partials ? composeArgs(partials, value, source[4]) : value;
        data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
      }
      // Compose partial right arguments.
      value = source[5];
      if (value) {
        partials = data[5];
        data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
        data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
      }
      // Use source `argPos` if available.
      value = source[7];
      if (value) {
        data[7] = value;
      }
      // Use source `ary` if it's smaller.
      if (srcBitmask & WRAP_ARY_FLAG) {
        data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
      }
      // Use source `arity` if one is not provided.
      if (data[9] == null) {
        data[9] = source[9];
      }
      // Use source `func` and merge bitmasks.
      data[0] = source[0];
      data[1] = newBitmask;

      return data;
    }

    /**
     * This function is like
     * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
     * except that it includes inherited enumerable properties.
     *
     * @private
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     */
    function nativeKeysIn(object) {
      var result = [];
      if (object != null) {
        for (var key in Object(object)) {
          result.push(key);
        }
      }
      return result;
    }

    /**
     * Converts `value` to a string using `Object.prototype.toString`.
     *
     * @private
     * @param {*} value The value to convert.
     * @returns {string} Returns the converted string.
     */
    function objectToString(value) {
      return nativeObjectToString.call(value);
    }

    /**
     * A specialized version of `baseRest` which transforms the rest array.
     *
     * @private
     * @param {Function} func The function to apply a rest parameter to.
     * @param {number} [start=func.length-1] The start position of the rest parameter.
     * @param {Function} transform The rest array transform.
     * @returns {Function} Returns the new function.
     */
    function overRest(func, start, transform) {
      start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
      return function() {
        var args = arguments,
            index = -1,
            length = nativeMax(args.length - start, 0),
            array = Array(length);

        while (++index < length) {
          array[index] = args[start + index];
        }
        index = -1;
        var otherArgs = Array(start + 1);
        while (++index < start) {
          otherArgs[index] = args[index];
        }
        otherArgs[start] = transform(array);
        return apply(func, this, otherArgs);
      };
    }

    /**
     * Gets the parent value at `path` of `object`.
     *
     * @private
     * @param {Object} object The object to query.
     * @param {Array} path The path to get the parent value of.
     * @returns {*} Returns the parent value.
     */
    function parent(object, path) {
      return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
    }

    /**
     * Reorder `array` according to the specified indexes where the element at
     * the first index is assigned as the first element, the element at
     * the second index is assigned as the second element, and so on.
     *
     * @private
     * @param {Array} array The array to reorder.
     * @param {Array} indexes The arranged array indexes.
     * @returns {Array} Returns `array`.
     */
    function reorder(array, indexes) {
      var arrLength = array.length,
          length = nativeMin(indexes.length, arrLength),
          oldArray = copyArray(array);

      while (length--) {
        var index = indexes[length];
        array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
      }
      return array;
    }

    /**
     * Sets metadata for `func`.
     *
     * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
     * period of time, it will trip its breaker and transition to an identity
     * function to avoid garbage collection pauses in V8. See
     * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
     * for more details.
     *
     * @private
     * @param {Function} func The function to associate metadata with.
     * @param {*} data The metadata.
     * @returns {Function} Returns `func`.
     */
    var setData = shortOut(baseSetData);

    /**
     * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
     *
     * @private
     * @param {Function} func The function to delay.
     * @param {number} wait The number of milliseconds to delay invocation.
     * @returns {number|Object} Returns the timer id or timeout object.
     */
    var setTimeout = ctxSetTimeout || function(func, wait) {
      return root.setTimeout(func, wait);
    };

    /**
     * Sets the `toString` method of `func` to return `string`.
     *
     * @private
     * @param {Function} func The function to modify.
     * @param {Function} string The `toString` result.
     * @returns {Function} Returns `func`.
     */
    var setToString = shortOut(baseSetToString);

    /**
     * Sets the `toString` method of `wrapper` to mimic the source of `reference`
     * with wrapper details in a comment at the top of the source body.
     *
     * @private
     * @param {Function} wrapper The function to modify.
     * @param {Function} reference The reference function.
     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
     * @returns {Function} Returns `wrapper`.
     */
    function setWrapToString(wrapper, reference, bitmask) {
      var source = (reference + '');
      return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
    }

    /**
     * Creates a function that'll short out and invoke `identity` instead
     * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
     * milliseconds.
     *
     * @private
     * @param {Function} func The function to restrict.
     * @returns {Function} Returns the new shortable function.
     */
    function shortOut(func) {
      var count = 0,
          lastCalled = 0;

      return function() {
        var stamp = nativeNow(),
            remaining = HOT_SPAN - (stamp - lastCalled);

        lastCalled = stamp;
        if (remaining > 0) {
          if (++count >= HOT_COUNT) {
            return arguments[0];
          }
        } else {
          count = 0;
        }
        return func.apply(undefined, arguments);
      };
    }

    /**
     * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
     *
     * @private
     * @param {Array} array The array to shuffle.
     * @param {number} [size=array.length] The size of `array`.
     * @returns {Array} Returns `array`.
     */
    function shuffleSelf(array, size) {
      var index = -1,
          length = array.length,
          lastIndex = length - 1;

      size = size === undefined ? length : size;
      while (++index < size) {
        var rand = baseRandom(index, lastIndex),
            value = array[rand];

        array[rand] = array[index];
        array[index] = value;
      }
      array.length = size;
      return array;
    }

    /**
     * Converts `string` to a property path array.
     *
     * @private
     * @param {string} string The string to convert.
     * @returns {Array} Returns the property path array.
     */
    var stringToPath = memoizeCapped(function(string) {
      var result = [];
      if (reLeadingDot.test(string)) {
        result.push('');
      }
      string.replace(rePropName, function(match, number, quote, string) {
        result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
      });
      return result;
    });

    /**
     * Converts `value` to a string key if it's not a string or symbol.
     *
     * @private
     * @param {*} value The value to inspect.
     * @returns {string|symbol} Returns the key.
     */
    function toKey(value) {
      if (typeof value == 'string' || isSymbol(value)) {
        return value;
      }
      var result = (value + '');
      return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
    }

    /**
     * Converts `func` to its source code.
     *
     * @private
     * @param {Function} func The function to convert.
     * @returns {string} Returns the source code.
     */
    function toSource(func) {
      if (func != null) {
        try {
          return funcToString.call(func);
        } catch (e) {}
        try {
          return (func + '');
        } catch (e) {}
      }
      return '';
    }

    /**
     * Updates wrapper `details` based on `bitmask` flags.
     *
     * @private
     * @returns {Array} details The details to modify.
     * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
     * @returns {Array} Returns `details`.
     */
    function updateWrapDetails(details, bitmask) {
      arrayEach(wrapFlags, function(pair) {
        var value = '_.' + pair[0];
        if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
          details.push(value);
        }
      });
      return details.sort();
    }

    /**
     * Creates a clone of `wrapper`.
     *
     * @private
     * @param {Object} wrapper The wrapper to clone.
     * @returns {Object} Returns the cloned wrapper.
     */
    function wrapperClone(wrapper) {
      if (wrapper instanceof LazyWrapper) {
        return wrapper.clone();
      }
      var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
      result.__actions__ = copyArray(wrapper.__actions__);
      result.__index__  = wrapper.__index__;
      result.__values__ = wrapper.__values__;
      return result;
    }

    /*------------------------------------------------------------------------*/

    /**
     * Creates an array of elements split into groups the length of `size`.
     * If `array` can't be split evenly, the final chunk will be the remaining
     * elements.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to process.
     * @param {number} [size=1] The length of each chunk
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Array} Returns the new array of chunks.
     * @example
     *
     * _.chunk(['a', 'b', 'c', 'd'], 2);
     * // => [['a', 'b'], ['c', 'd']]
     *
     * _.chunk(['a', 'b', 'c', 'd'], 3);
     * // => [['a', 'b', 'c'], ['d']]
     */
    function chunk(array, size, guard) {
      if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
        size = 1;
      } else {
        size = nativeMax(toInteger(size), 0);
      }
      var length = array == null ? 0 : array.length;
      if (!length || size < 1) {
        return [];
      }
      var index = 0,
          resIndex = 0,
          result = Array(nativeCeil(length / size));

      while (index < length) {
        result[resIndex++] = baseSlice(array, index, (index += size));
      }
      return result;
    }

    /**
     * Creates an array with all falsey values removed. The values `false`, `null`,
     * `0`, `""`, `undefined`, and `NaN` are falsey.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to compact.
     * @returns {Array} Returns the new array of filtered values.
     * @example
     *
     * _.compact([0, 1, false, 2, '', 3]);
     * // => [1, 2, 3]
     */
    function compact(array) {
      var index = -1,
          length = array == null ? 0 : array.length,
          resIndex = 0,
          result = [];

      while (++index < length) {
        var value = array[index];
        if (value) {
          result[resIndex++] = value;
        }
      }
      return result;
    }

    /**
     * Creates a new array concatenating `array` with any additional arrays
     * and/or values.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to concatenate.
     * @param {...*} [values] The values to concatenate.
     * @returns {Array} Returns the new concatenated array.
     * @example
     *
     * var array = [1];
     * var other = _.concat(array, 2, [3], [[4]]);
     *
     * console.log(other);
     * // => [1, 2, 3, [4]]
     *
     * console.log(array);
     * // => [1]
     */
    function concat() {
      var length = arguments.length;
      if (!length) {
        return [];
      }
      var args = Array(length - 1),
          array = arguments[0],
          index = length;

      while (index--) {
        args[index - 1] = arguments[index];
      }
      return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
    }

    /**
     * Creates an array of `array` values not included in the other given arrays
     * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons. The order and references of result values are
     * determined by the first array.
     *
     * **Note:** Unlike `_.pullAll`, this method returns a new array.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {...Array} [values] The values to exclude.
     * @returns {Array} Returns the new array of filtered values.
     * @see _.without, _.xor
     * @example
     *
     * _.difference([2, 1], [2, 3]);
     * // => [1]
     */
    var difference = baseRest(function(array, values) {
      return isArrayLikeObject(array)
        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
        : [];
    });

    /**
     * This method is like `_.difference` except that it accepts `iteratee` which
     * is invoked for each element of `array` and `values` to generate the criterion
     * by which they're compared. The order and references of result values are
     * determined by the first array. The iteratee is invoked with one argument:
     * (value).
     *
     * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {...Array} [values] The values to exclude.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {Array} Returns the new array of filtered values.
     * @example
     *
     * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
     * // => [1.2]
     *
     * // The `_.property` iteratee shorthand.
     * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
     * // => [{ 'x': 2 }]
     */
    var differenceBy = baseRest(function(array, values) {
      var iteratee = last(values);
      if (isArrayLikeObject(iteratee)) {
        iteratee = undefined;
      }
      return isArrayLikeObject(array)
        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
        : [];
    });

    /**
     * This method is like `_.difference` except that it accepts `comparator`
     * which is invoked to compare elements of `array` to `values`. The order and
     * references of result values are determined by the first array. The comparator
     * is invoked with two arguments: (arrVal, othVal).
     *
     * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {...Array} [values] The values to exclude.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new array of filtered values.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
     *
     * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
     * // => [{ 'x': 2, 'y': 1 }]
     */
    var differenceWith = baseRest(function(array, values) {
      var comparator = last(values);
      if (isArrayLikeObject(comparator)) {
        comparator = undefined;
      }
      return isArrayLikeObject(array)
        ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
        : [];
    });

    /**
     * Creates a slice of `array` with `n` elements dropped from the beginning.
     *
     * @static
     * @memberOf _
     * @since 0.5.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {number} [n=1] The number of elements to drop.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * _.drop([1, 2, 3]);
     * // => [2, 3]
     *
     * _.drop([1, 2, 3], 2);
     * // => [3]
     *
     * _.drop([1, 2, 3], 5);
     * // => []
     *
     * _.drop([1, 2, 3], 0);
     * // => [1, 2, 3]
     */
    function drop(array, n, guard) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return [];
      }
      n = (guard || n === undefined) ? 1 : toInteger(n);
      return baseSlice(array, n < 0 ? 0 : n, length);
    }

    /**
     * Creates a slice of `array` with `n` elements dropped from the end.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {number} [n=1] The number of elements to drop.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * _.dropRight([1, 2, 3]);
     * // => [1, 2]
     *
     * _.dropRight([1, 2, 3], 2);
     * // => [1]
     *
     * _.dropRight([1, 2, 3], 5);
     * // => []
     *
     * _.dropRight([1, 2, 3], 0);
     * // => [1, 2, 3]
     */
    function dropRight(array, n, guard) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return [];
      }
      n = (guard || n === undefined) ? 1 : toInteger(n);
      n = length - n;
      return baseSlice(array, 0, n < 0 ? 0 : n);
    }

    /**
     * Creates a slice of `array` excluding elements dropped from the end.
     * Elements are dropped until `predicate` returns falsey. The predicate is
     * invoked with three arguments: (value, index, array).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': true },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': false }
     * ];
     *
     * _.dropRightWhile(users, function(o) { return !o.active; });
     * // => objects for ['barney']
     *
     * // The `_.matches` iteratee shorthand.
     * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
     * // => objects for ['barney', 'fred']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.dropRightWhile(users, ['active', false]);
     * // => objects for ['barney']
     *
     * // The `_.property` iteratee shorthand.
     * _.dropRightWhile(users, 'active');
     * // => objects for ['barney', 'fred', 'pebbles']
     */
    function dropRightWhile(array, predicate) {
      return (array && array.length)
        ? baseWhile(array, getIteratee(predicate, 3), true, true)
        : [];
    }

    /**
     * Creates a slice of `array` excluding elements dropped from the beginning.
     * Elements are dropped until `predicate` returns falsey. The predicate is
     * invoked with three arguments: (value, index, array).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': false },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': true }
     * ];
     *
     * _.dropWhile(users, function(o) { return !o.active; });
     * // => objects for ['pebbles']
     *
     * // The `_.matches` iteratee shorthand.
     * _.dropWhile(users, { 'user': 'barney', 'active': false });
     * // => objects for ['fred', 'pebbles']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.dropWhile(users, ['active', false]);
     * // => objects for ['pebbles']
     *
     * // The `_.property` iteratee shorthand.
     * _.dropWhile(users, 'active');
     * // => objects for ['barney', 'fred', 'pebbles']
     */
    function dropWhile(array, predicate) {
      return (array && array.length)
        ? baseWhile(array, getIteratee(predicate, 3), true)
        : [];
    }

    /**
     * Fills elements of `array` with `value` from `start` up to, but not
     * including, `end`.
     *
     * **Note:** This method mutates `array`.
     *
     * @static
     * @memberOf _
     * @since 3.2.0
     * @category Array
     * @param {Array} array The array to fill.
     * @param {*} value The value to fill `array` with.
     * @param {number} [start=0] The start position.
     * @param {number} [end=array.length] The end position.
     * @returns {Array} Returns `array`.
     * @example
     *
     * var array = [1, 2, 3];
     *
     * _.fill(array, 'a');
     * console.log(array);
     * // => ['a', 'a', 'a']
     *
     * _.fill(Array(3), 2);
     * // => [2, 2, 2]
     *
     * _.fill([4, 6, 8, 10], '*', 1, 3);
     * // => [4, '*', '*', 10]
     */
    function fill(array, value, start, end) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return [];
      }
      if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
        start = 0;
        end = length;
      }
      return baseFill(array, value, start, end);
    }

    /**
     * This method is like `_.find` except that it returns the index of the first
     * element `predicate` returns truthy for instead of the element itself.
     *
     * @static
     * @memberOf _
     * @since 1.1.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @param {number} [fromIndex=0] The index to search from.
     * @returns {number} Returns the index of the found element, else `-1`.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': false },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': true }
     * ];
     *
     * _.findIndex(users, function(o) { return o.user == 'barney'; });
     * // => 0
     *
     * // The `_.matches` iteratee shorthand.
     * _.findIndex(users, { 'user': 'fred', 'active': false });
     * // => 1
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.findIndex(users, ['active', false]);
     * // => 0
     *
     * // The `_.property` iteratee shorthand.
     * _.findIndex(users, 'active');
     * // => 2
     */
    function findIndex(array, predicate, fromIndex) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return -1;
      }
      var index = fromIndex == null ? 0 : toInteger(fromIndex);
      if (index < 0) {
        index = nativeMax(length + index, 0);
      }
      return baseFindIndex(array, getIteratee(predicate, 3), index);
    }

    /**
     * This method is like `_.findIndex` except that it iterates over elements
     * of `collection` from right to left.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @param {number} [fromIndex=array.length-1] The index to search from.
     * @returns {number} Returns the index of the found element, else `-1`.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': true },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': false }
     * ];
     *
     * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
     * // => 2
     *
     * // The `_.matches` iteratee shorthand.
     * _.findLastIndex(users, { 'user': 'barney', 'active': true });
     * // => 0
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.findLastIndex(users, ['active', false]);
     * // => 2
     *
     * // The `_.property` iteratee shorthand.
     * _.findLastIndex(users, 'active');
     * // => 0
     */
    function findLastIndex(array, predicate, fromIndex) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return -1;
      }
      var index = length - 1;
      if (fromIndex !== undefined) {
        index = toInteger(fromIndex);
        index = fromIndex < 0
          ? nativeMax(length + index, 0)
          : nativeMin(index, length - 1);
      }
      return baseFindIndex(array, getIteratee(predicate, 3), index, true);
    }

    /**
     * Flattens `array` a single level deep.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to flatten.
     * @returns {Array} Returns the new flattened array.
     * @example
     *
     * _.flatten([1, [2, [3, [4]], 5]]);
     * // => [1, 2, [3, [4]], 5]
     */
    function flatten(array) {
      var length = array == null ? 0 : array.length;
      return length ? baseFlatten(array, 1) : [];
    }

    /**
     * Recursively flattens `array`.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to flatten.
     * @returns {Array} Returns the new flattened array.
     * @example
     *
     * _.flattenDeep([1, [2, [3, [4]], 5]]);
     * // => [1, 2, 3, 4, 5]
     */
    function flattenDeep(array) {
      var length = array == null ? 0 : array.length;
      return length ? baseFlatten(array, INFINITY) : [];
    }

    /**
     * Recursively flatten `array` up to `depth` times.
     *
     * @static
     * @memberOf _
     * @since 4.4.0
     * @category Array
     * @param {Array} array The array to flatten.
     * @param {number} [depth=1] The maximum recursion depth.
     * @returns {Array} Returns the new flattened array.
     * @example
     *
     * var array = [1, [2, [3, [4]], 5]];
     *
     * _.flattenDepth(array, 1);
     * // => [1, 2, [3, [4]], 5]
     *
     * _.flattenDepth(array, 2);
     * // => [1, 2, 3, [4], 5]
     */
    function flattenDepth(array, depth) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return [];
      }
      depth = depth === undefined ? 1 : toInteger(depth);
      return baseFlatten(array, depth);
    }

    /**
     * The inverse of `_.toPairs`; this method returns an object composed
     * from key-value `pairs`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} pairs The key-value pairs.
     * @returns {Object} Returns the new object.
     * @example
     *
     * _.fromPairs([['a', 1], ['b', 2]]);
     * // => { 'a': 1, 'b': 2 }
     */
    function fromPairs(pairs) {
      var index = -1,
          length = pairs == null ? 0 : pairs.length,
          result = {};

      while (++index < length) {
        var pair = pairs[index];
        result[pair[0]] = pair[1];
      }
      return result;
    }

    /**
     * Gets the first element of `array`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @alias first
     * @category Array
     * @param {Array} array The array to query.
     * @returns {*} Returns the first element of `array`.
     * @example
     *
     * _.head([1, 2, 3]);
     * // => 1
     *
     * _.head([]);
     * // => undefined
     */
    function head(array) {
      return (array && array.length) ? array[0] : undefined;
    }

    /**
     * Gets the index at which the first occurrence of `value` is found in `array`
     * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons. If `fromIndex` is negative, it's used as the
     * offset from the end of `array`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {*} value The value to search for.
     * @param {number} [fromIndex=0] The index to search from.
     * @returns {number} Returns the index of the matched value, else `-1`.
     * @example
     *
     * _.indexOf([1, 2, 1, 2], 2);
     * // => 1
     *
     * // Search from the `fromIndex`.
     * _.indexOf([1, 2, 1, 2], 2, 2);
     * // => 3
     */
    function indexOf(array, value, fromIndex) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return -1;
      }
      var index = fromIndex == null ? 0 : toInteger(fromIndex);
      if (index < 0) {
        index = nativeMax(length + index, 0);
      }
      return baseIndexOf(array, value, index);
    }

    /**
     * Gets all but the last element of `array`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to query.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * _.initial([1, 2, 3]);
     * // => [1, 2]
     */
    function initial(array) {
      var length = array == null ? 0 : array.length;
      return length ? baseSlice(array, 0, -1) : [];
    }

    /**
     * Creates an array of unique values that are included in all given arrays
     * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons. The order and references of result values are
     * determined by the first array.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @returns {Array} Returns the new array of intersecting values.
     * @example
     *
     * _.intersection([2, 1], [2, 3]);
     * // => [2]
     */
    var intersection = baseRest(function(arrays) {
      var mapped = arrayMap(arrays, castArrayLikeObject);
      return (mapped.length && mapped[0] === arrays[0])
        ? baseIntersection(mapped)
        : [];
    });

    /**
     * This method is like `_.intersection` except that it accepts `iteratee`
     * which is invoked for each element of each `arrays` to generate the criterion
     * by which they're compared. The order and references of result values are
     * determined by the first array. The iteratee is invoked with one argument:
     * (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {Array} Returns the new array of intersecting values.
     * @example
     *
     * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
     * // => [2.1]
     *
     * // The `_.property` iteratee shorthand.
     * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
     * // => [{ 'x': 1 }]
     */
    var intersectionBy = baseRest(function(arrays) {
      var iteratee = last(arrays),
          mapped = arrayMap(arrays, castArrayLikeObject);

      if (iteratee === last(mapped)) {
        iteratee = undefined;
      } else {
        mapped.pop();
      }
      return (mapped.length && mapped[0] === arrays[0])
        ? baseIntersection(mapped, getIteratee(iteratee, 2))
        : [];
    });

    /**
     * This method is like `_.intersection` except that it accepts `comparator`
     * which is invoked to compare elements of `arrays`. The order and references
     * of result values are determined by the first array. The comparator is
     * invoked with two arguments: (arrVal, othVal).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new array of intersecting values.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
     *
     * _.intersectionWith(objects, others, _.isEqual);
     * // => [{ 'x': 1, 'y': 2 }]
     */
    var intersectionWith = baseRest(function(arrays) {
      var comparator = last(arrays),
          mapped = arrayMap(arrays, castArrayLikeObject);

      comparator = typeof comparator == 'function' ? comparator : undefined;
      if (comparator) {
        mapped.pop();
      }
      return (mapped.length && mapped[0] === arrays[0])
        ? baseIntersection(mapped, undefined, comparator)
        : [];
    });

    /**
     * Converts all elements in `array` into a string separated by `separator`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to convert.
     * @param {string} [separator=','] The element separator.
     * @returns {string} Returns the joined string.
     * @example
     *
     * _.join(['a', 'b', 'c'], '~');
     * // => 'a~b~c'
     */
    function join(array, separator) {
      return array == null ? '' : nativeJoin.call(array, separator);
    }

    /**
     * Gets the last element of `array`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to query.
     * @returns {*} Returns the last element of `array`.
     * @example
     *
     * _.last([1, 2, 3]);
     * // => 3
     */
    function last(array) {
      var length = array == null ? 0 : array.length;
      return length ? array[length - 1] : undefined;
    }

    /**
     * This method is like `_.indexOf` except that it iterates over elements of
     * `array` from right to left.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {*} value The value to search for.
     * @param {number} [fromIndex=array.length-1] The index to search from.
     * @returns {number} Returns the index of the matched value, else `-1`.
     * @example
     *
     * _.lastIndexOf([1, 2, 1, 2], 2);
     * // => 3
     *
     * // Search from the `fromIndex`.
     * _.lastIndexOf([1, 2, 1, 2], 2, 2);
     * // => 1
     */
    function lastIndexOf(array, value, fromIndex) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return -1;
      }
      var index = length;
      if (fromIndex !== undefined) {
        index = toInteger(fromIndex);
        index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
      }
      return value === value
        ? strictLastIndexOf(array, value, index)
        : baseFindIndex(array, baseIsNaN, index, true);
    }

    /**
     * Gets the element at index `n` of `array`. If `n` is negative, the nth
     * element from the end is returned.
     *
     * @static
     * @memberOf _
     * @since 4.11.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {number} [n=0] The index of the element to return.
     * @returns {*} Returns the nth element of `array`.
     * @example
     *
     * var array = ['a', 'b', 'c', 'd'];
     *
     * _.nth(array, 1);
     * // => 'b'
     *
     * _.nth(array, -2);
     * // => 'c';
     */
    function nth(array, n) {
      return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
    }

    /**
     * Removes all given values from `array` using
     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons.
     *
     * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
     * to remove elements from an array by predicate.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Array
     * @param {Array} array The array to modify.
     * @param {...*} [values] The values to remove.
     * @returns {Array} Returns `array`.
     * @example
     *
     * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
     *
     * _.pull(array, 'a', 'c');
     * console.log(array);
     * // => ['b', 'b']
     */
    var pull = baseRest(pullAll);

    /**
     * This method is like `_.pull` except that it accepts an array of values to remove.
     *
     * **Note:** Unlike `_.difference`, this method mutates `array`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to modify.
     * @param {Array} values The values to remove.
     * @returns {Array} Returns `array`.
     * @example
     *
     * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
     *
     * _.pullAll(array, ['a', 'c']);
     * console.log(array);
     * // => ['b', 'b']
     */
    function pullAll(array, values) {
      return (array && array.length && values && values.length)
        ? basePullAll(array, values)
        : array;
    }

    /**
     * This method is like `_.pullAll` except that it accepts `iteratee` which is
     * invoked for each element of `array` and `values` to generate the criterion
     * by which they're compared. The iteratee is invoked with one argument: (value).
     *
     * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to modify.
     * @param {Array} values The values to remove.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {Array} Returns `array`.
     * @example
     *
     * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
     *
     * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
     * console.log(array);
     * // => [{ 'x': 2 }]
     */
    function pullAllBy(array, values, iteratee) {
      return (array && array.length && values && values.length)
        ? basePullAll(array, values, getIteratee(iteratee, 2))
        : array;
    }

    /**
     * This method is like `_.pullAll` except that it accepts `comparator` which
     * is invoked to compare elements of `array` to `values`. The comparator is
     * invoked with two arguments: (arrVal, othVal).
     *
     * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
     *
     * @static
     * @memberOf _
     * @since 4.6.0
     * @category Array
     * @param {Array} array The array to modify.
     * @param {Array} values The values to remove.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns `array`.
     * @example
     *
     * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
     *
     * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
     * console.log(array);
     * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
     */
    function pullAllWith(array, values, comparator) {
      return (array && array.length && values && values.length)
        ? basePullAll(array, values, undefined, comparator)
        : array;
    }

    /**
     * Removes elements from `array` corresponding to `indexes` and returns an
     * array of removed elements.
     *
     * **Note:** Unlike `_.at`, this method mutates `array`.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to modify.
     * @param {...(number|number[])} [indexes] The indexes of elements to remove.
     * @returns {Array} Returns the new array of removed elements.
     * @example
     *
     * var array = ['a', 'b', 'c', 'd'];
     * var pulled = _.pullAt(array, [1, 3]);
     *
     * console.log(array);
     * // => ['a', 'c']
     *
     * console.log(pulled);
     * // => ['b', 'd']
     */
    var pullAt = flatRest(function(array, indexes) {
      var length = array == null ? 0 : array.length,
          result = baseAt(array, indexes);

      basePullAt(array, arrayMap(indexes, function(index) {
        return isIndex(index, length) ? +index : index;
      }).sort(compareAscending));

      return result;
    });

    /**
     * Removes all elements from `array` that `predicate` returns truthy for
     * and returns an array of the removed elements. The predicate is invoked
     * with three arguments: (value, index, array).
     *
     * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
     * to pull elements from an array by value.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Array
     * @param {Array} array The array to modify.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the new array of removed elements.
     * @example
     *
     * var array = [1, 2, 3, 4];
     * var evens = _.remove(array, function(n) {
     *   return n % 2 == 0;
     * });
     *
     * console.log(array);
     * // => [1, 3]
     *
     * console.log(evens);
     * // => [2, 4]
     */
    function remove(array, predicate) {
      var result = [];
      if (!(array && array.length)) {
        return result;
      }
      var index = -1,
          indexes = [],
          length = array.length;

      predicate = getIteratee(predicate, 3);
      while (++index < length) {
        var value = array[index];
        if (predicate(value, index, array)) {
          result.push(value);
          indexes.push(index);
        }
      }
      basePullAt(array, indexes);
      return result;
    }

    /**
     * Reverses `array` so that the first element becomes the last, the second
     * element becomes the second to last, and so on.
     *
     * **Note:** This method mutates `array` and is based on
     * [`Array#reverse`](https://mdn.io/Array/reverse).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to modify.
     * @returns {Array} Returns `array`.
     * @example
     *
     * var array = [1, 2, 3];
     *
     * _.reverse(array);
     * // => [3, 2, 1]
     *
     * console.log(array);
     * // => [3, 2, 1]
     */
    function reverse(array) {
      return array == null ? array : nativeReverse.call(array);
    }

    /**
     * Creates a slice of `array` from `start` up to, but not including, `end`.
     *
     * **Note:** This method is used instead of
     * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
     * returned.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to slice.
     * @param {number} [start=0] The start position.
     * @param {number} [end=array.length] The end position.
     * @returns {Array} Returns the slice of `array`.
     */
    function slice(array, start, end) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return [];
      }
      if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
        start = 0;
        end = length;
      }
      else {
        start = start == null ? 0 : toInteger(start);
        end = end === undefined ? length : toInteger(end);
      }
      return baseSlice(array, start, end);
    }

    /**
     * Uses a binary search to determine the lowest index at which `value`
     * should be inserted into `array` in order to maintain its sort order.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The sorted array to inspect.
     * @param {*} value The value to evaluate.
     * @returns {number} Returns the index at which `value` should be inserted
     *  into `array`.
     * @example
     *
     * _.sortedIndex([30, 50], 40);
     * // => 1
     */
    function sortedIndex(array, value) {
      return baseSortedIndex(array, value);
    }

    /**
     * This method is like `_.sortedIndex` except that it accepts `iteratee`
     * which is invoked for `value` and each element of `array` to compute their
     * sort ranking. The iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The sorted array to inspect.
     * @param {*} value The value to evaluate.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {number} Returns the index at which `value` should be inserted
     *  into `array`.
     * @example
     *
     * var objects = [{ 'x': 4 }, { 'x': 5 }];
     *
     * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
     * // => 0
     *
     * // The `_.property` iteratee shorthand.
     * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
     * // => 0
     */
    function sortedIndexBy(array, value, iteratee) {
      return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
    }

    /**
     * This method is like `_.indexOf` except that it performs a binary
     * search on a sorted `array`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {*} value The value to search for.
     * @returns {number} Returns the index of the matched value, else `-1`.
     * @example
     *
     * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
     * // => 1
     */
    function sortedIndexOf(array, value) {
      var length = array == null ? 0 : array.length;
      if (length) {
        var index = baseSortedIndex(array, value);
        if (index < length && eq(array[index], value)) {
          return index;
        }
      }
      return -1;
    }

    /**
     * This method is like `_.sortedIndex` except that it returns the highest
     * index at which `value` should be inserted into `array` in order to
     * maintain its sort order.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The sorted array to inspect.
     * @param {*} value The value to evaluate.
     * @returns {number} Returns the index at which `value` should be inserted
     *  into `array`.
     * @example
     *
     * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
     * // => 4
     */
    function sortedLastIndex(array, value) {
      return baseSortedIndex(array, value, true);
    }

    /**
     * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
     * which is invoked for `value` and each element of `array` to compute their
     * sort ranking. The iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The sorted array to inspect.
     * @param {*} value The value to evaluate.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {number} Returns the index at which `value` should be inserted
     *  into `array`.
     * @example
     *
     * var objects = [{ 'x': 4 }, { 'x': 5 }];
     *
     * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
     * // => 1
     *
     * // The `_.property` iteratee shorthand.
     * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
     * // => 1
     */
    function sortedLastIndexBy(array, value, iteratee) {
      return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
    }

    /**
     * This method is like `_.lastIndexOf` except that it performs a binary
     * search on a sorted `array`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {*} value The value to search for.
     * @returns {number} Returns the index of the matched value, else `-1`.
     * @example
     *
     * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
     * // => 3
     */
    function sortedLastIndexOf(array, value) {
      var length = array == null ? 0 : array.length;
      if (length) {
        var index = baseSortedIndex(array, value, true) - 1;
        if (eq(array[index], value)) {
          return index;
        }
      }
      return -1;
    }

    /**
     * This method is like `_.uniq` except that it's designed and optimized
     * for sorted arrays.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @returns {Array} Returns the new duplicate free array.
     * @example
     *
     * _.sortedUniq([1, 1, 2]);
     * // => [1, 2]
     */
    function sortedUniq(array) {
      return (array && array.length)
        ? baseSortedUniq(array)
        : [];
    }

    /**
     * This method is like `_.uniqBy` except that it's designed and optimized
     * for sorted arrays.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {Function} [iteratee] The iteratee invoked per element.
     * @returns {Array} Returns the new duplicate free array.
     * @example
     *
     * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
     * // => [1.1, 2.3]
     */
    function sortedUniqBy(array, iteratee) {
      return (array && array.length)
        ? baseSortedUniq(array, getIteratee(iteratee, 2))
        : [];
    }

    /**
     * Gets all but the first element of `array`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to query.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * _.tail([1, 2, 3]);
     * // => [2, 3]
     */
    function tail(array) {
      var length = array == null ? 0 : array.length;
      return length ? baseSlice(array, 1, length) : [];
    }

    /**
     * Creates a slice of `array` with `n` elements taken from the beginning.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {number} [n=1] The number of elements to take.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * _.take([1, 2, 3]);
     * // => [1]
     *
     * _.take([1, 2, 3], 2);
     * // => [1, 2]
     *
     * _.take([1, 2, 3], 5);
     * // => [1, 2, 3]
     *
     * _.take([1, 2, 3], 0);
     * // => []
     */
    function take(array, n, guard) {
      if (!(array && array.length)) {
        return [];
      }
      n = (guard || n === undefined) ? 1 : toInteger(n);
      return baseSlice(array, 0, n < 0 ? 0 : n);
    }

    /**
     * Creates a slice of `array` with `n` elements taken from the end.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {number} [n=1] The number of elements to take.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * _.takeRight([1, 2, 3]);
     * // => [3]
     *
     * _.takeRight([1, 2, 3], 2);
     * // => [2, 3]
     *
     * _.takeRight([1, 2, 3], 5);
     * // => [1, 2, 3]
     *
     * _.takeRight([1, 2, 3], 0);
     * // => []
     */
    function takeRight(array, n, guard) {
      var length = array == null ? 0 : array.length;
      if (!length) {
        return [];
      }
      n = (guard || n === undefined) ? 1 : toInteger(n);
      n = length - n;
      return baseSlice(array, n < 0 ? 0 : n, length);
    }

    /**
     * Creates a slice of `array` with elements taken from the end. Elements are
     * taken until `predicate` returns falsey. The predicate is invoked with
     * three arguments: (value, index, array).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': true },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': false }
     * ];
     *
     * _.takeRightWhile(users, function(o) { return !o.active; });
     * // => objects for ['fred', 'pebbles']
     *
     * // The `_.matches` iteratee shorthand.
     * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
     * // => objects for ['pebbles']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.takeRightWhile(users, ['active', false]);
     * // => objects for ['fred', 'pebbles']
     *
     * // The `_.property` iteratee shorthand.
     * _.takeRightWhile(users, 'active');
     * // => []
     */
    function takeRightWhile(array, predicate) {
      return (array && array.length)
        ? baseWhile(array, getIteratee(predicate, 3), false, true)
        : [];
    }

    /**
     * Creates a slice of `array` with elements taken from the beginning. Elements
     * are taken until `predicate` returns falsey. The predicate is invoked with
     * three arguments: (value, index, array).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Array
     * @param {Array} array The array to query.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the slice of `array`.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'active': false },
     *   { 'user': 'fred',    'active': false },
     *   { 'user': 'pebbles', 'active': true }
     * ];
     *
     * _.takeWhile(users, function(o) { return !o.active; });
     * // => objects for ['barney', 'fred']
     *
     * // The `_.matches` iteratee shorthand.
     * _.takeWhile(users, { 'user': 'barney', 'active': false });
     * // => objects for ['barney']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.takeWhile(users, ['active', false]);
     * // => objects for ['barney', 'fred']
     *
     * // The `_.property` iteratee shorthand.
     * _.takeWhile(users, 'active');
     * // => []
     */
    function takeWhile(array, predicate) {
      return (array && array.length)
        ? baseWhile(array, getIteratee(predicate, 3))
        : [];
    }

    /**
     * Creates an array of unique values, in order, from all given arrays using
     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @returns {Array} Returns the new array of combined values.
     * @example
     *
     * _.union([2], [1, 2]);
     * // => [2, 1]
     */
    var union = baseRest(function(arrays) {
      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
    });

    /**
     * This method is like `_.union` except that it accepts `iteratee` which is
     * invoked for each element of each `arrays` to generate the criterion by
     * which uniqueness is computed. Result values are chosen from the first
     * array in which the value occurs. The iteratee is invoked with one argument:
     * (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {Array} Returns the new array of combined values.
     * @example
     *
     * _.unionBy([2.1], [1.2, 2.3], Math.floor);
     * // => [2.1, 1.2]
     *
     * // The `_.property` iteratee shorthand.
     * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
     * // => [{ 'x': 1 }, { 'x': 2 }]
     */
    var unionBy = baseRest(function(arrays) {
      var iteratee = last(arrays);
      if (isArrayLikeObject(iteratee)) {
        iteratee = undefined;
      }
      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
    });

    /**
     * This method is like `_.union` except that it accepts `comparator` which
     * is invoked to compare elements of `arrays`. Result values are chosen from
     * the first array in which the value occurs. The comparator is invoked
     * with two arguments: (arrVal, othVal).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new array of combined values.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
     *
     * _.unionWith(objects, others, _.isEqual);
     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
     */
    var unionWith = baseRest(function(arrays) {
      var comparator = last(arrays);
      comparator = typeof comparator == 'function' ? comparator : undefined;
      return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
    });

    /**
     * Creates a duplicate-free version of an array, using
     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons, in which only the first occurrence of each element
     * is kept. The order of result values is determined by the order they occur
     * in the array.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @returns {Array} Returns the new duplicate free array.
     * @example
     *
     * _.uniq([2, 1, 2]);
     * // => [2, 1]
     */
    function uniq(array) {
      return (array && array.length) ? baseUniq(array) : [];
    }

    /**
     * This method is like `_.uniq` except that it accepts `iteratee` which is
     * invoked for each element in `array` to generate the criterion by which
     * uniqueness is computed. The order of result values is determined by the
     * order they occur in the array. The iteratee is invoked with one argument:
     * (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {Array} Returns the new duplicate free array.
     * @example
     *
     * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
     * // => [2.1, 1.2]
     *
     * // The `_.property` iteratee shorthand.
     * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
     * // => [{ 'x': 1 }, { 'x': 2 }]
     */
    function uniqBy(array, iteratee) {
      return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
    }

    /**
     * This method is like `_.uniq` except that it accepts `comparator` which
     * is invoked to compare elements of `array`. The order of result values is
     * determined by the order they occur in the array.The comparator is invoked
     * with two arguments: (arrVal, othVal).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new duplicate free array.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
     *
     * _.uniqWith(objects, _.isEqual);
     * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
     */
    function uniqWith(array, comparator) {
      comparator = typeof comparator == 'function' ? comparator : undefined;
      return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
    }

    /**
     * This method is like `_.zip` except that it accepts an array of grouped
     * elements and creates an array regrouping the elements to their pre-zip
     * configuration.
     *
     * @static
     * @memberOf _
     * @since 1.2.0
     * @category Array
     * @param {Array} array The array of grouped elements to process.
     * @returns {Array} Returns the new array of regrouped elements.
     * @example
     *
     * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
     * // => [['a', 1, true], ['b', 2, false]]
     *
     * _.unzip(zipped);
     * // => [['a', 'b'], [1, 2], [true, false]]
     */
    function unzip(array) {
      if (!(array && array.length)) {
        return [];
      }
      var length = 0;
      array = arrayFilter(array, function(group) {
        if (isArrayLikeObject(group)) {
          length = nativeMax(group.length, length);
          return true;
        }
      });
      return baseTimes(length, function(index) {
        return arrayMap(array, baseProperty(index));
      });
    }

    /**
     * This method is like `_.unzip` except that it accepts `iteratee` to specify
     * how regrouped values should be combined. The iteratee is invoked with the
     * elements of each group: (...group).
     *
     * @static
     * @memberOf _
     * @since 3.8.0
     * @category Array
     * @param {Array} array The array of grouped elements to process.
     * @param {Function} [iteratee=_.identity] The function to combine
     *  regrouped values.
     * @returns {Array} Returns the new array of regrouped elements.
     * @example
     *
     * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
     * // => [[1, 10, 100], [2, 20, 200]]
     *
     * _.unzipWith(zipped, _.add);
     * // => [3, 30, 300]
     */
    function unzipWith(array, iteratee) {
      if (!(array && array.length)) {
        return [];
      }
      var result = unzip(array);
      if (iteratee == null) {
        return result;
      }
      return arrayMap(result, function(group) {
        return apply(iteratee, undefined, group);
      });
    }

    /**
     * Creates an array excluding all given values using
     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * for equality comparisons.
     *
     * **Note:** Unlike `_.pull`, this method returns a new array.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {Array} array The array to inspect.
     * @param {...*} [values] The values to exclude.
     * @returns {Array} Returns the new array of filtered values.
     * @see _.difference, _.xor
     * @example
     *
     * _.without([2, 1, 2, 3], 1, 2);
     * // => [3]
     */
    var without = baseRest(function(array, values) {
      return isArrayLikeObject(array)
        ? baseDifference(array, values)
        : [];
    });

    /**
     * Creates an array of unique values that is the
     * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
     * of the given arrays. The order of result values is determined by the order
     * they occur in the arrays.
     *
     * @static
     * @memberOf _
     * @since 2.4.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @returns {Array} Returns the new array of filtered values.
     * @see _.difference, _.without
     * @example
     *
     * _.xor([2, 1], [2, 3]);
     * // => [1, 3]
     */
    var xor = baseRest(function(arrays) {
      return baseXor(arrayFilter(arrays, isArrayLikeObject));
    });

    /**
     * This method is like `_.xor` except that it accepts `iteratee` which is
     * invoked for each element of each `arrays` to generate the criterion by
     * which by which they're compared. The order of result values is determined
     * by the order they occur in the arrays. The iteratee is invoked with one
     * argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {Array} Returns the new array of filtered values.
     * @example
     *
     * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
     * // => [1.2, 3.4]
     *
     * // The `_.property` iteratee shorthand.
     * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
     * // => [{ 'x': 2 }]
     */
    var xorBy = baseRest(function(arrays) {
      var iteratee = last(arrays);
      if (isArrayLikeObject(iteratee)) {
        iteratee = undefined;
      }
      return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
    });

    /**
     * This method is like `_.xor` except that it accepts `comparator` which is
     * invoked to compare elements of `arrays`. The order of result values is
     * determined by the order they occur in the arrays. The comparator is invoked
     * with two arguments: (arrVal, othVal).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Array
     * @param {...Array} [arrays] The arrays to inspect.
     * @param {Function} [comparator] The comparator invoked per element.
     * @returns {Array} Returns the new array of filtered values.
     * @example
     *
     * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
     * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
     *
     * _.xorWith(objects, others, _.isEqual);
     * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
     */
    var xorWith = baseRest(function(arrays) {
      var comparator = last(arrays);
      comparator = typeof comparator == 'function' ? comparator : undefined;
      return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
    });

    /**
     * Creates an array of grouped elements, the first of which contains the
     * first elements of the given arrays, the second of which contains the
     * second elements of the given arrays, and so on.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Array
     * @param {...Array} [arrays] The arrays to process.
     * @returns {Array} Returns the new array of grouped elements.
     * @example
     *
     * _.zip(['a', 'b'], [1, 2], [true, false]);
     * // => [['a', 1, true], ['b', 2, false]]
     */
    var zip = baseRest(unzip);

    /**
     * This method is like `_.fromPairs` except that it accepts two arrays,
     * one of property identifiers and one of corresponding values.
     *
     * @static
     * @memberOf _
     * @since 0.4.0
     * @category Array
     * @param {Array} [props=[]] The property identifiers.
     * @param {Array} [values=[]] The property values.
     * @returns {Object} Returns the new object.
     * @example
     *
     * _.zipObject(['a', 'b'], [1, 2]);
     * // => { 'a': 1, 'b': 2 }
     */
    function zipObject(props, values) {
      return baseZipObject(props || [], values || [], assignValue);
    }

    /**
     * This method is like `_.zipObject` except that it supports property paths.
     *
     * @static
     * @memberOf _
     * @since 4.1.0
     * @category Array
     * @param {Array} [props=[]] The property identifiers.
     * @param {Array} [values=[]] The property values.
     * @returns {Object} Returns the new object.
     * @example
     *
     * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
     * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
     */
    function zipObjectDeep(props, values) {
      return baseZipObject(props || [], values || [], baseSet);
    }

    /**
     * This method is like `_.zip` except that it accepts `iteratee` to specify
     * how grouped values should be combined. The iteratee is invoked with the
     * elements of each group: (...group).
     *
     * @static
     * @memberOf _
     * @since 3.8.0
     * @category Array
     * @param {...Array} [arrays] The arrays to process.
     * @param {Function} [iteratee=_.identity] The function to combine
     *  grouped values.
     * @returns {Array} Returns the new array of grouped elements.
     * @example
     *
     * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
     *   return a + b + c;
     * });
     * // => [111, 222]
     */
    var zipWith = baseRest(function(arrays) {
      var length = arrays.length,
          iteratee = length > 1 ? arrays[length - 1] : undefined;

      iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
      return unzipWith(arrays, iteratee);
    });

    /*------------------------------------------------------------------------*/

    /**
     * Creates a `lodash` wrapper instance that wraps `value` with explicit method
     * chain sequences enabled. The result of such sequences must be unwrapped
     * with `_#value`.
     *
     * @static
     * @memberOf _
     * @since 1.3.0
     * @category Seq
     * @param {*} value The value to wrap.
     * @returns {Object} Returns the new `lodash` wrapper instance.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'age': 36 },
     *   { 'user': 'fred',    'age': 40 },
     *   { 'user': 'pebbles', 'age': 1 }
     * ];
     *
     * var youngest = _
     *   .chain(users)
     *   .sortBy('age')
     *   .map(function(o) {
     *     return o.user + ' is ' + o.age;
     *   })
     *   .head()
     *   .value();
     * // => 'pebbles is 1'
     */
    function chain(value) {
      var result = lodash(value);
      result.__chain__ = true;
      return result;
    }

    /**
     * This method invokes `interceptor` and returns `value`. The interceptor
     * is invoked with one argument; (value). The purpose of this method is to
     * "tap into" a method chain sequence in order to modify intermediate results.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Seq
     * @param {*} value The value to provide to `interceptor`.
     * @param {Function} interceptor The function to invoke.
     * @returns {*} Returns `value`.
     * @example
     *
     * _([1, 2, 3])
     *  .tap(function(array) {
     *    // Mutate input array.
     *    array.pop();
     *  })
     *  .reverse()
     *  .value();
     * // => [2, 1]
     */
    function tap(value, interceptor) {
      interceptor(value);
      return value;
    }

    /**
     * This method is like `_.tap` except that it returns the result of `interceptor`.
     * The purpose of this method is to "pass thru" values replacing intermediate
     * results in a method chain sequence.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Seq
     * @param {*} value The value to provide to `interceptor`.
     * @param {Function} interceptor The function to invoke.
     * @returns {*} Returns the result of `interceptor`.
     * @example
     *
     * _('  abc  ')
     *  .chain()
     *  .trim()
     *  .thru(function(value) {
     *    return [value];
     *  })
     *  .value();
     * // => ['abc']
     */
    function thru(value, interceptor) {
      return interceptor(value);
    }

    /**
     * This method is the wrapper version of `_.at`.
     *
     * @name at
     * @memberOf _
     * @since 1.0.0
     * @category Seq
     * @param {...(string|string[])} [paths] The property paths to pick.
     * @returns {Object} Returns the new `lodash` wrapper instance.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
     *
     * _(object).at(['a[0].b.c', 'a[1]']).value();
     * // => [3, 4]
     */
    var wrapperAt = flatRest(function(paths) {
      var length = paths.length,
          start = length ? paths[0] : 0,
          value = this.__wrapped__,
          interceptor = function(object) { return baseAt(object, paths); };

      if (length > 1 || this.__actions__.length ||
          !(value instanceof LazyWrapper) || !isIndex(start)) {
        return this.thru(interceptor);
      }
      value = value.slice(start, +start + (length ? 1 : 0));
      value.__actions__.push({
        'func': thru,
        'args': [interceptor],
        'thisArg': undefined
      });
      return new LodashWrapper(value, this.__chain__).thru(function(array) {
        if (length && !array.length) {
          array.push(undefined);
        }
        return array;
      });
    });

    /**
     * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
     *
     * @name chain
     * @memberOf _
     * @since 0.1.0
     * @category Seq
     * @returns {Object} Returns the new `lodash` wrapper instance.
     * @example
     *
     * var users = [
     *   { 'user': 'barney', 'age': 36 },
     *   { 'user': 'fred',   'age': 40 }
     * ];
     *
     * // A sequence without explicit chaining.
     * _(users).head();
     * // => { 'user': 'barney', 'age': 36 }
     *
     * // A sequence with explicit chaining.
     * _(users)
     *   .chain()
     *   .head()
     *   .pick('user')
     *   .value();
     * // => { 'user': 'barney' }
     */
    function wrapperChain() {
      return chain(this);
    }

    /**
     * Executes the chain sequence and returns the wrapped result.
     *
     * @name commit
     * @memberOf _
     * @since 3.2.0
     * @category Seq
     * @returns {Object} Returns the new `lodash` wrapper instance.
     * @example
     *
     * var array = [1, 2];
     * var wrapped = _(array).push(3);
     *
     * console.log(array);
     * // => [1, 2]
     *
     * wrapped = wrapped.commit();
     * console.log(array);
     * // => [1, 2, 3]
     *
     * wrapped.last();
     * // => 3
     *
     * console.log(array);
     * // => [1, 2, 3]
     */
    function wrapperCommit() {
      return new LodashWrapper(this.value(), this.__chain__);
    }

    /**
     * Gets the next value on a wrapped object following the
     * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
     *
     * @name next
     * @memberOf _
     * @since 4.0.0
     * @category Seq
     * @returns {Object} Returns the next iterator value.
     * @example
     *
     * var wrapped = _([1, 2]);
     *
     * wrapped.next();
     * // => { 'done': false, 'value': 1 }
     *
     * wrapped.next();
     * // => { 'done': false, 'value': 2 }
     *
     * wrapped.next();
     * // => { 'done': true, 'value': undefined }
     */
    function wrapperNext() {
      if (this.__values__ === undefined) {
        this.__values__ = toArray(this.value());
      }
      var done = this.__index__ >= this.__values__.length,
          value = done ? undefined : this.__values__[this.__index__++];

      return { 'done': done, 'value': value };
    }

    /**
     * Enables the wrapper to be iterable.
     *
     * @name Symbol.iterator
     * @memberOf _
     * @since 4.0.0
     * @category Seq
     * @returns {Object} Returns the wrapper object.
     * @example
     *
     * var wrapped = _([1, 2]);
     *
     * wrapped[Symbol.iterator]() === wrapped;
     * // => true
     *
     * Array.from(wrapped);
     * // => [1, 2]
     */
    function wrapperToIterator() {
      return this;
    }

    /**
     * Creates a clone of the chain sequence planting `value` as the wrapped value.
     *
     * @name plant
     * @memberOf _
     * @since 3.2.0
     * @category Seq
     * @param {*} value The value to plant.
     * @returns {Object} Returns the new `lodash` wrapper instance.
     * @example
     *
     * function square(n) {
     *   return n * n;
     * }
     *
     * var wrapped = _([1, 2]).map(square);
     * var other = wrapped.plant([3, 4]);
     *
     * other.value();
     * // => [9, 16]
     *
     * wrapped.value();
     * // => [1, 4]
     */
    function wrapperPlant(value) {
      var result,
          parent = this;

      while (parent instanceof baseLodash) {
        var clone = wrapperClone(parent);
        clone.__index__ = 0;
        clone.__values__ = undefined;
        if (result) {
          previous.__wrapped__ = clone;
        } else {
          result = clone;
        }
        var previous = clone;
        parent = parent.__wrapped__;
      }
      previous.__wrapped__ = value;
      return result;
    }

    /**
     * This method is the wrapper version of `_.reverse`.
     *
     * **Note:** This method mutates the wrapped array.
     *
     * @name reverse
     * @memberOf _
     * @since 0.1.0
     * @category Seq
     * @returns {Object} Returns the new `lodash` wrapper instance.
     * @example
     *
     * var array = [1, 2, 3];
     *
     * _(array).reverse().value()
     * // => [3, 2, 1]
     *
     * console.log(array);
     * // => [3, 2, 1]
     */
    function wrapperReverse() {
      var value = this.__wrapped__;
      if (value instanceof LazyWrapper) {
        var wrapped = value;
        if (this.__actions__.length) {
          wrapped = new LazyWrapper(this);
        }
        wrapped = wrapped.reverse();
        wrapped.__actions__.push({
          'func': thru,
          'args': [reverse],
          'thisArg': undefined
        });
        return new LodashWrapper(wrapped, this.__chain__);
      }
      return this.thru(reverse);
    }

    /**
     * Executes the chain sequence to resolve the unwrapped value.
     *
     * @name value
     * @memberOf _
     * @since 0.1.0
     * @alias toJSON, valueOf
     * @category Seq
     * @returns {*} Returns the resolved unwrapped value.
     * @example
     *
     * _([1, 2, 3]).value();
     * // => [1, 2, 3]
     */
    function wrapperValue() {
      return baseWrapperValue(this.__wrapped__, this.__actions__);
    }

    /*------------------------------------------------------------------------*/

    /**
     * Creates an object composed of keys generated from the results of running
     * each element of `collection` thru `iteratee`. The corresponding value of
     * each key is the number of times the key was returned by `iteratee`. The
     * iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 0.5.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
     * @returns {Object} Returns the composed aggregate object.
     * @example
     *
     * _.countBy([6.1, 4.2, 6.3], Math.floor);
     * // => { '4': 1, '6': 2 }
     *
     * // The `_.property` iteratee shorthand.
     * _.countBy(['one', 'two', 'three'], 'length');
     * // => { '3': 2, '5': 1 }
     */
    var countBy = createAggregator(function(result, value, key) {
      if (hasOwnProperty.call(result, key)) {
        ++result[key];
      } else {
        baseAssignValue(result, key, 1);
      }
    });

    /**
     * Checks if `predicate` returns truthy for **all** elements of `collection`.
     * Iteration is stopped once `predicate` returns falsey. The predicate is
     * invoked with three arguments: (value, index|key, collection).
     *
     * **Note:** This method returns `true` for
     * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
     * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
     * elements of empty collections.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {boolean} Returns `true` if all elements pass the predicate check,
     *  else `false`.
     * @example
     *
     * _.every([true, 1, null, 'yes'], Boolean);
     * // => false
     *
     * var users = [
     *   { 'user': 'barney', 'age': 36, 'active': false },
     *   { 'user': 'fred',   'age': 40, 'active': false }
     * ];
     *
     * // The `_.matches` iteratee shorthand.
     * _.every(users, { 'user': 'barney', 'active': false });
     * // => false
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.every(users, ['active', false]);
     * // => true
     *
     * // The `_.property` iteratee shorthand.
     * _.every(users, 'active');
     * // => false
     */
    function every(collection, predicate, guard) {
      var func = isArray(collection) ? arrayEvery : baseEvery;
      if (guard && isIterateeCall(collection, predicate, guard)) {
        predicate = undefined;
      }
      return func(collection, getIteratee(predicate, 3));
    }

    /**
     * Iterates over elements of `collection`, returning an array of all elements
     * `predicate` returns truthy for. The predicate is invoked with three
     * arguments: (value, index|key, collection).
     *
     * **Note:** Unlike `_.remove`, this method returns a new array.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the new filtered array.
     * @see _.reject
     * @example
     *
     * var users = [
     *   { 'user': 'barney', 'age': 36, 'active': true },
     *   { 'user': 'fred',   'age': 40, 'active': false }
     * ];
     *
     * _.filter(users, function(o) { return !o.active; });
     * // => objects for ['fred']
     *
     * // The `_.matches` iteratee shorthand.
     * _.filter(users, { 'age': 36, 'active': true });
     * // => objects for ['barney']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.filter(users, ['active', false]);
     * // => objects for ['fred']
     *
     * // The `_.property` iteratee shorthand.
     * _.filter(users, 'active');
     * // => objects for ['barney']
     */
    function filter(collection, predicate) {
      var func = isArray(collection) ? arrayFilter : baseFilter;
      return func(collection, getIteratee(predicate, 3));
    }

    /**
     * Iterates over elements of `collection`, returning the first element
     * `predicate` returns truthy for. The predicate is invoked with three
     * arguments: (value, index|key, collection).
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to inspect.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @param {number} [fromIndex=0] The index to search from.
     * @returns {*} Returns the matched element, else `undefined`.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'age': 36, 'active': true },
     *   { 'user': 'fred',    'age': 40, 'active': false },
     *   { 'user': 'pebbles', 'age': 1,  'active': true }
     * ];
     *
     * _.find(users, function(o) { return o.age < 40; });
     * // => object for 'barney'
     *
     * // The `_.matches` iteratee shorthand.
     * _.find(users, { 'age': 1, 'active': true });
     * // => object for 'pebbles'
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.find(users, ['active', false]);
     * // => object for 'fred'
     *
     * // The `_.property` iteratee shorthand.
     * _.find(users, 'active');
     * // => object for 'barney'
     */
    var find = createFind(findIndex);

    /**
     * This method is like `_.find` except that it iterates over elements of
     * `collection` from right to left.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to inspect.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @param {number} [fromIndex=collection.length-1] The index to search from.
     * @returns {*} Returns the matched element, else `undefined`.
     * @example
     *
     * _.findLast([1, 2, 3, 4], function(n) {
     *   return n % 2 == 1;
     * });
     * // => 3
     */
    var findLast = createFind(findLastIndex);

    /**
     * Creates a flattened array of values by running each element in `collection`
     * thru `iteratee` and flattening the mapped results. The iteratee is invoked
     * with three arguments: (value, index|key, collection).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the new flattened array.
     * @example
     *
     * function duplicate(n) {
     *   return [n, n];
     * }
     *
     * _.flatMap([1, 2], duplicate);
     * // => [1, 1, 2, 2]
     */
    function flatMap(collection, iteratee) {
      return baseFlatten(map(collection, iteratee), 1);
    }

    /**
     * This method is like `_.flatMap` except that it recursively flattens the
     * mapped results.
     *
     * @static
     * @memberOf _
     * @since 4.7.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the new flattened array.
     * @example
     *
     * function duplicate(n) {
     *   return [[[n, n]]];
     * }
     *
     * _.flatMapDeep([1, 2], duplicate);
     * // => [1, 1, 2, 2]
     */
    function flatMapDeep(collection, iteratee) {
      return baseFlatten(map(collection, iteratee), INFINITY);
    }

    /**
     * This method is like `_.flatMap` except that it recursively flattens the
     * mapped results up to `depth` times.
     *
     * @static
     * @memberOf _
     * @since 4.7.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @param {number} [depth=1] The maximum recursion depth.
     * @returns {Array} Returns the new flattened array.
     * @example
     *
     * function duplicate(n) {
     *   return [[[n, n]]];
     * }
     *
     * _.flatMapDepth([1, 2], duplicate, 2);
     * // => [[1, 1], [2, 2]]
     */
    function flatMapDepth(collection, iteratee, depth) {
      depth = depth === undefined ? 1 : toInteger(depth);
      return baseFlatten(map(collection, iteratee), depth);
    }

    /**
     * Iterates over elements of `collection` and invokes `iteratee` for each element.
     * The iteratee is invoked with three arguments: (value, index|key, collection).
     * Iteratee functions may exit iteration early by explicitly returning `false`.
     *
     * **Note:** As with other "Collections" methods, objects with a "length"
     * property are iterated like arrays. To avoid this behavior use `_.forIn`
     * or `_.forOwn` for object iteration.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @alias each
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Array|Object} Returns `collection`.
     * @see _.forEachRight
     * @example
     *
     * _.forEach([1, 2], function(value) {
     *   console.log(value);
     * });
     * // => Logs `1` then `2`.
     *
     * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
     *   console.log(key);
     * });
     * // => Logs 'a' then 'b' (iteration order is not guaranteed).
     */
    function forEach(collection, iteratee) {
      var func = isArray(collection) ? arrayEach : baseEach;
      return func(collection, getIteratee(iteratee, 3));
    }

    /**
     * This method is like `_.forEach` except that it iterates over elements of
     * `collection` from right to left.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @alias eachRight
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Array|Object} Returns `collection`.
     * @see _.forEach
     * @example
     *
     * _.forEachRight([1, 2], function(value) {
     *   console.log(value);
     * });
     * // => Logs `2` then `1`.
     */
    function forEachRight(collection, iteratee) {
      var func = isArray(collection) ? arrayEachRight : baseEachRight;
      return func(collection, getIteratee(iteratee, 3));
    }

    /**
     * Creates an object composed of keys generated from the results of running
     * each element of `collection` thru `iteratee`. The order of grouped values
     * is determined by the order they occur in `collection`. The corresponding
     * value of each key is an array of elements responsible for generating the
     * key. The iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
     * @returns {Object} Returns the composed aggregate object.
     * @example
     *
     * _.groupBy([6.1, 4.2, 6.3], Math.floor);
     * // => { '4': [4.2], '6': [6.1, 6.3] }
     *
     * // The `_.property` iteratee shorthand.
     * _.groupBy(['one', 'two', 'three'], 'length');
     * // => { '3': ['one', 'two'], '5': ['three'] }
     */
    var groupBy = createAggregator(function(result, value, key) {
      if (hasOwnProperty.call(result, key)) {
        result[key].push(value);
      } else {
        baseAssignValue(result, key, [value]);
      }
    });

    /**
     * Checks if `value` is in `collection`. If `collection` is a string, it's
     * checked for a substring of `value`, otherwise
     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * is used for equality comparisons. If `fromIndex` is negative, it's used as
     * the offset from the end of `collection`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object|string} collection The collection to inspect.
     * @param {*} value The value to search for.
     * @param {number} [fromIndex=0] The index to search from.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
     * @returns {boolean} Returns `true` if `value` is found, else `false`.
     * @example
     *
     * _.includes([1, 2, 3], 1);
     * // => true
     *
     * _.includes([1, 2, 3], 1, 2);
     * // => false
     *
     * _.includes({ 'a': 1, 'b': 2 }, 1);
     * // => true
     *
     * _.includes('abcd', 'bc');
     * // => true
     */
    function includes(collection, value, fromIndex, guard) {
      collection = isArrayLike(collection) ? collection : values(collection);
      fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;

      var length = collection.length;
      if (fromIndex < 0) {
        fromIndex = nativeMax(length + fromIndex, 0);
      }
      return isString(collection)
        ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
        : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
    }

    /**
     * Invokes the method at `path` of each element in `collection`, returning
     * an array of the results of each invoked method. Any additional arguments
     * are provided to each invoked method. If `path` is a function, it's invoked
     * for, and `this` bound to, each element in `collection`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Array|Function|string} path The path of the method to invoke or
     *  the function invoked per iteration.
     * @param {...*} [args] The arguments to invoke each method with.
     * @returns {Array} Returns the array of results.
     * @example
     *
     * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
     * // => [[1, 5, 7], [1, 2, 3]]
     *
     * _.invokeMap([123, 456], String.prototype.split, '');
     * // => [['1', '2', '3'], ['4', '5', '6']]
     */
    var invokeMap = baseRest(function(collection, path, args) {
      var index = -1,
          isFunc = typeof path == 'function',
          result = isArrayLike(collection) ? Array(collection.length) : [];

      baseEach(collection, function(value) {
        result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
      });
      return result;
    });

    /**
     * Creates an object composed of keys generated from the results of running
     * each element of `collection` thru `iteratee`. The corresponding value of
     * each key is the last element responsible for generating the key. The
     * iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
     * @returns {Object} Returns the composed aggregate object.
     * @example
     *
     * var array = [
     *   { 'dir': 'left', 'code': 97 },
     *   { 'dir': 'right', 'code': 100 }
     * ];
     *
     * _.keyBy(array, function(o) {
     *   return String.fromCharCode(o.code);
     * });
     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
     *
     * _.keyBy(array, 'dir');
     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
     */
    var keyBy = createAggregator(function(result, value, key) {
      baseAssignValue(result, key, value);
    });

    /**
     * Creates an array of values by running each element in `collection` thru
     * `iteratee`. The iteratee is invoked with three arguments:
     * (value, index|key, collection).
     *
     * Many lodash methods are guarded to work as iteratees for methods like
     * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
     *
     * The guarded methods are:
     * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
     * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
     * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
     * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the new mapped array.
     * @example
     *
     * function square(n) {
     *   return n * n;
     * }
     *
     * _.map([4, 8], square);
     * // => [16, 64]
     *
     * _.map({ 'a': 4, 'b': 8 }, square);
     * // => [16, 64] (iteration order is not guaranteed)
     *
     * var users = [
     *   { 'user': 'barney' },
     *   { 'user': 'fred' }
     * ];
     *
     * // The `_.property` iteratee shorthand.
     * _.map(users, 'user');
     * // => ['barney', 'fred']
     */
    function map(collection, iteratee) {
      var func = isArray(collection) ? arrayMap : baseMap;
      return func(collection, getIteratee(iteratee, 3));
    }

    /**
     * This method is like `_.sortBy` except that it allows specifying the sort
     * orders of the iteratees to sort by. If `orders` is unspecified, all values
     * are sorted in ascending order. Otherwise, specify an order of "desc" for
     * descending or "asc" for ascending sort order of corresponding values.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
     *  The iteratees to sort by.
     * @param {string[]} [orders] The sort orders of `iteratees`.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
     * @returns {Array} Returns the new sorted array.
     * @example
     *
     * var users = [
     *   { 'user': 'fred',   'age': 48 },
     *   { 'user': 'barney', 'age': 34 },
     *   { 'user': 'fred',   'age': 40 },
     *   { 'user': 'barney', 'age': 36 }
     * ];
     *
     * // Sort by `user` in ascending order and by `age` in descending order.
     * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
     * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
     */
    function orderBy(collection, iteratees, orders, guard) {
      if (collection == null) {
        return [];
      }
      if (!isArray(iteratees)) {
        iteratees = iteratees == null ? [] : [iteratees];
      }
      orders = guard ? undefined : orders;
      if (!isArray(orders)) {
        orders = orders == null ? [] : [orders];
      }
      return baseOrderBy(collection, iteratees, orders);
    }

    /**
     * Creates an array of elements split into two groups, the first of which
     * contains elements `predicate` returns truthy for, the second of which
     * contains elements `predicate` returns falsey for. The predicate is
     * invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the array of grouped elements.
     * @example
     *
     * var users = [
     *   { 'user': 'barney',  'age': 36, 'active': false },
     *   { 'user': 'fred',    'age': 40, 'active': true },
     *   { 'user': 'pebbles', 'age': 1,  'active': false }
     * ];
     *
     * _.partition(users, function(o) { return o.active; });
     * // => objects for [['fred'], ['barney', 'pebbles']]
     *
     * // The `_.matches` iteratee shorthand.
     * _.partition(users, { 'age': 1, 'active': false });
     * // => objects for [['pebbles'], ['barney', 'fred']]
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.partition(users, ['active', false]);
     * // => objects for [['barney', 'pebbles'], ['fred']]
     *
     * // The `_.property` iteratee shorthand.
     * _.partition(users, 'active');
     * // => objects for [['fred'], ['barney', 'pebbles']]
     */
    var partition = createAggregator(function(result, value, key) {
      result[key ? 0 : 1].push(value);
    }, function() { return [[], []]; });

    /**
     * Reduces `collection` to a value which is the accumulated result of running
     * each element in `collection` thru `iteratee`, where each successive
     * invocation is supplied the return value of the previous. If `accumulator`
     * is not given, the first element of `collection` is used as the initial
     * value. The iteratee is invoked with four arguments:
     * (accumulator, value, index|key, collection).
     *
     * Many lodash methods are guarded to work as iteratees for methods like
     * `_.reduce`, `_.reduceRight`, and `_.transform`.
     *
     * The guarded methods are:
     * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
     * and `sortBy`
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @param {*} [accumulator] The initial value.
     * @returns {*} Returns the accumulated value.
     * @see _.reduceRight
     * @example
     *
     * _.reduce([1, 2], function(sum, n) {
     *   return sum + n;
     * }, 0);
     * // => 3
     *
     * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
     *   (result[value] || (result[value] = [])).push(key);
     *   return result;
     * }, {});
     * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
     */
    function reduce(collection, iteratee, accumulator) {
      var func = isArray(collection) ? arrayReduce : baseReduce,
          initAccum = arguments.length < 3;

      return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
    }

    /**
     * This method is like `_.reduce` except that it iterates over elements of
     * `collection` from right to left.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @param {*} [accumulator] The initial value.
     * @returns {*} Returns the accumulated value.
     * @see _.reduce
     * @example
     *
     * var array = [[0, 1], [2, 3], [4, 5]];
     *
     * _.reduceRight(array, function(flattened, other) {
     *   return flattened.concat(other);
     * }, []);
     * // => [4, 5, 2, 3, 0, 1]
     */
    function reduceRight(collection, iteratee, accumulator) {
      var func = isArray(collection) ? arrayReduceRight : baseReduce,
          initAccum = arguments.length < 3;

      return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
    }

    /**
     * The opposite of `_.filter`; this method returns the elements of `collection`
     * that `predicate` does **not** return truthy for.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the new filtered array.
     * @see _.filter
     * @example
     *
     * var users = [
     *   { 'user': 'barney', 'age': 36, 'active': false },
     *   { 'user': 'fred',   'age': 40, 'active': true }
     * ];
     *
     * _.reject(users, function(o) { return !o.active; });
     * // => objects for ['fred']
     *
     * // The `_.matches` iteratee shorthand.
     * _.reject(users, { 'age': 40, 'active': true });
     * // => objects for ['barney']
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.reject(users, ['active', false]);
     * // => objects for ['fred']
     *
     * // The `_.property` iteratee shorthand.
     * _.reject(users, 'active');
     * // => objects for ['barney']
     */
    function reject(collection, predicate) {
      var func = isArray(collection) ? arrayFilter : baseFilter;
      return func(collection, negate(getIteratee(predicate, 3)));
    }

    /**
     * Gets a random element from `collection`.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to sample.
     * @returns {*} Returns the random element.
     * @example
     *
     * _.sample([1, 2, 3, 4]);
     * // => 2
     */
    function sample(collection) {
      var func = isArray(collection) ? arraySample : baseSample;
      return func(collection);
    }

    /**
     * Gets `n` random elements at unique keys from `collection` up to the
     * size of `collection`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Collection
     * @param {Array|Object} collection The collection to sample.
     * @param {number} [n=1] The number of elements to sample.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Array} Returns the random elements.
     * @example
     *
     * _.sampleSize([1, 2, 3], 2);
     * // => [3, 1]
     *
     * _.sampleSize([1, 2, 3], 4);
     * // => [2, 3, 1]
     */
    function sampleSize(collection, n, guard) {
      if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
        n = 1;
      } else {
        n = toInteger(n);
      }
      var func = isArray(collection) ? arraySampleSize : baseSampleSize;
      return func(collection, n);
    }

    /**
     * Creates an array of shuffled values, using a version of the
     * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to shuffle.
     * @returns {Array} Returns the new shuffled array.
     * @example
     *
     * _.shuffle([1, 2, 3, 4]);
     * // => [4, 1, 3, 2]
     */
    function shuffle(collection) {
      var func = isArray(collection) ? arrayShuffle : baseShuffle;
      return func(collection);
    }

    /**
     * Gets the size of `collection` by returning its length for array-like
     * values or the number of own enumerable string keyed properties for objects.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object|string} collection The collection to inspect.
     * @returns {number} Returns the collection size.
     * @example
     *
     * _.size([1, 2, 3]);
     * // => 3
     *
     * _.size({ 'a': 1, 'b': 2 });
     * // => 2
     *
     * _.size('pebbles');
     * // => 7
     */
    function size(collection) {
      if (collection == null) {
        return 0;
      }
      if (isArrayLike(collection)) {
        return isString(collection) ? stringSize(collection) : collection.length;
      }
      var tag = getTag(collection);
      if (tag == mapTag || tag == setTag) {
        return collection.size;
      }
      return baseKeys(collection).length;
    }

    /**
     * Checks if `predicate` returns truthy for **any** element of `collection`.
     * Iteration is stopped once `predicate` returns truthy. The predicate is
     * invoked with three arguments: (value, index|key, collection).
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {boolean} Returns `true` if any element passes the predicate check,
     *  else `false`.
     * @example
     *
     * _.some([null, 0, 'yes', false], Boolean);
     * // => true
     *
     * var users = [
     *   { 'user': 'barney', 'active': true },
     *   { 'user': 'fred',   'active': false }
     * ];
     *
     * // The `_.matches` iteratee shorthand.
     * _.some(users, { 'user': 'barney', 'active': false });
     * // => false
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.some(users, ['active', false]);
     * // => true
     *
     * // The `_.property` iteratee shorthand.
     * _.some(users, 'active');
     * // => true
     */
    function some(collection, predicate, guard) {
      var func = isArray(collection) ? arraySome : baseSome;
      if (guard && isIterateeCall(collection, predicate, guard)) {
        predicate = undefined;
      }
      return func(collection, getIteratee(predicate, 3));
    }

    /**
     * Creates an array of elements, sorted in ascending order by the results of
     * running each element in a collection thru each iteratee. This method
     * performs a stable sort, that is, it preserves the original sort order of
     * equal elements. The iteratees are invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Collection
     * @param {Array|Object} collection The collection to iterate over.
     * @param {...(Function|Function[])} [iteratees=[_.identity]]
     *  The iteratees to sort by.
     * @returns {Array} Returns the new sorted array.
     * @example
     *
     * var users = [
     *   { 'user': 'fred',   'age': 48 },
     *   { 'user': 'barney', 'age': 36 },
     *   { 'user': 'fred',   'age': 40 },
     *   { 'user': 'barney', 'age': 34 }
     * ];
     *
     * _.sortBy(users, [function(o) { return o.user; }]);
     * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
     *
     * _.sortBy(users, ['user', 'age']);
     * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
     */
    var sortBy = baseRest(function(collection, iteratees) {
      if (collection == null) {
        return [];
      }
      var length = iteratees.length;
      if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
        iteratees = [];
      } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
        iteratees = [iteratees[0]];
      }
      return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
    });

    /*------------------------------------------------------------------------*/

    /**
     * Gets the timestamp of the number of milliseconds that have elapsed since
     * the Unix epoch (1 January 1970 00:00:00 UTC).
     *
     * @static
     * @memberOf _
     * @since 2.4.0
     * @category Date
     * @returns {number} Returns the timestamp.
     * @example
     *
     * _.defer(function(stamp) {
     *   console.log(_.now() - stamp);
     * }, _.now());
     * // => Logs the number of milliseconds it took for the deferred invocation.
     */
    var now = ctxNow || function() {
      return root.Date.now();
    };

    /*------------------------------------------------------------------------*/

    /**
     * The opposite of `_.before`; this method creates a function that invokes
     * `func` once it's called `n` or more times.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {number} n The number of calls before `func` is invoked.
     * @param {Function} func The function to restrict.
     * @returns {Function} Returns the new restricted function.
     * @example
     *
     * var saves = ['profile', 'settings'];
     *
     * var done = _.after(saves.length, function() {
     *   console.log('done saving!');
     * });
     *
     * _.forEach(saves, function(type) {
     *   asyncSave({ 'type': type, 'complete': done });
     * });
     * // => Logs 'done saving!' after the two async saves have completed.
     */
    function after(n, func) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      n = toInteger(n);
      return function() {
        if (--n < 1) {
          return func.apply(this, arguments);
        }
      };
    }

    /**
     * Creates a function that invokes `func`, with up to `n` arguments,
     * ignoring any additional arguments.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Function
     * @param {Function} func The function to cap arguments for.
     * @param {number} [n=func.length] The arity cap.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Function} Returns the new capped function.
     * @example
     *
     * _.map(['6', '8', '10'], _.ary(parseInt, 1));
     * // => [6, 8, 10]
     */
    function ary(func, n, guard) {
      n = guard ? undefined : n;
      n = (func && n == null) ? func.length : n;
      return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
    }

    /**
     * Creates a function that invokes `func`, with the `this` binding and arguments
     * of the created function, while it's called less than `n` times. Subsequent
     * calls to the created function return the result of the last `func` invocation.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Function
     * @param {number} n The number of calls at which `func` is no longer invoked.
     * @param {Function} func The function to restrict.
     * @returns {Function} Returns the new restricted function.
     * @example
     *
     * jQuery(element).on('click', _.before(5, addContactToList));
     * // => Allows adding up to 4 contacts to the list.
     */
    function before(n, func) {
      var result;
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      n = toInteger(n);
      return function() {
        if (--n > 0) {
          result = func.apply(this, arguments);
        }
        if (n <= 1) {
          func = undefined;
        }
        return result;
      };
    }

    /**
     * Creates a function that invokes `func` with the `this` binding of `thisArg`
     * and `partials` prepended to the arguments it receives.
     *
     * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
     * may be used as a placeholder for partially applied arguments.
     *
     * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
     * property of bound functions.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {Function} func The function to bind.
     * @param {*} thisArg The `this` binding of `func`.
     * @param {...*} [partials] The arguments to be partially applied.
     * @returns {Function} Returns the new bound function.
     * @example
     *
     * function greet(greeting, punctuation) {
     *   return greeting + ' ' + this.user + punctuation;
     * }
     *
     * var object = { 'user': 'fred' };
     *
     * var bound = _.bind(greet, object, 'hi');
     * bound('!');
     * // => 'hi fred!'
     *
     * // Bound with placeholders.
     * var bound = _.bind(greet, object, _, '!');
     * bound('hi');
     * // => 'hi fred!'
     */
    var bind = baseRest(function(func, thisArg, partials) {
      var bitmask = WRAP_BIND_FLAG;
      if (partials.length) {
        var holders = replaceHolders(partials, getHolder(bind));
        bitmask |= WRAP_PARTIAL_FLAG;
      }
      return createWrap(func, bitmask, thisArg, partials, holders);
    });

    /**
     * Creates a function that invokes the method at `object[key]` with `partials`
     * prepended to the arguments it receives.
     *
     * This method differs from `_.bind` by allowing bound functions to reference
     * methods that may be redefined or don't yet exist. See
     * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
     * for more details.
     *
     * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
     * builds, may be used as a placeholder for partially applied arguments.
     *
     * @static
     * @memberOf _
     * @since 0.10.0
     * @category Function
     * @param {Object} object The object to invoke the method on.
     * @param {string} key The key of the method.
     * @param {...*} [partials] The arguments to be partially applied.
     * @returns {Function} Returns the new bound function.
     * @example
     *
     * var object = {
     *   'user': 'fred',
     *   'greet': function(greeting, punctuation) {
     *     return greeting + ' ' + this.user + punctuation;
     *   }
     * };
     *
     * var bound = _.bindKey(object, 'greet', 'hi');
     * bound('!');
     * // => 'hi fred!'
     *
     * object.greet = function(greeting, punctuation) {
     *   return greeting + 'ya ' + this.user + punctuation;
     * };
     *
     * bound('!');
     * // => 'hiya fred!'
     *
     * // Bound with placeholders.
     * var bound = _.bindKey(object, 'greet', _, '!');
     * bound('hi');
     * // => 'hiya fred!'
     */
    var bindKey = baseRest(function(object, key, partials) {
      var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
      if (partials.length) {
        var holders = replaceHolders(partials, getHolder(bindKey));
        bitmask |= WRAP_PARTIAL_FLAG;
      }
      return createWrap(key, bitmask, object, partials, holders);
    });

    /**
     * Creates a function that accepts arguments of `func` and either invokes
     * `func` returning its result, if at least `arity` number of arguments have
     * been provided, or returns a function that accepts the remaining `func`
     * arguments, and so on. The arity of `func` may be specified if `func.length`
     * is not sufficient.
     *
     * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
     * may be used as a placeholder for provided arguments.
     *
     * **Note:** This method doesn't set the "length" property of curried functions.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Function
     * @param {Function} func The function to curry.
     * @param {number} [arity=func.length] The arity of `func`.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Function} Returns the new curried function.
     * @example
     *
     * var abc = function(a, b, c) {
     *   return [a, b, c];
     * };
     *
     * var curried = _.curry(abc);
     *
     * curried(1)(2)(3);
     * // => [1, 2, 3]
     *
     * curried(1, 2)(3);
     * // => [1, 2, 3]
     *
     * curried(1, 2, 3);
     * // => [1, 2, 3]
     *
     * // Curried with placeholders.
     * curried(1)(_, 3)(2);
     * // => [1, 2, 3]
     */
    function curry(func, arity, guard) {
      arity = guard ? undefined : arity;
      var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
      result.placeholder = curry.placeholder;
      return result;
    }

    /**
     * This method is like `_.curry` except that arguments are applied to `func`
     * in the manner of `_.partialRight` instead of `_.partial`.
     *
     * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
     * builds, may be used as a placeholder for provided arguments.
     *
     * **Note:** This method doesn't set the "length" property of curried functions.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Function
     * @param {Function} func The function to curry.
     * @param {number} [arity=func.length] The arity of `func`.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Function} Returns the new curried function.
     * @example
     *
     * var abc = function(a, b, c) {
     *   return [a, b, c];
     * };
     *
     * var curried = _.curryRight(abc);
     *
     * curried(3)(2)(1);
     * // => [1, 2, 3]
     *
     * curried(2, 3)(1);
     * // => [1, 2, 3]
     *
     * curried(1, 2, 3);
     * // => [1, 2, 3]
     *
     * // Curried with placeholders.
     * curried(3)(1, _)(2);
     * // => [1, 2, 3]
     */
    function curryRight(func, arity, guard) {
      arity = guard ? undefined : arity;
      var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
      result.placeholder = curryRight.placeholder;
      return result;
    }

    /**
     * Creates a debounced function that delays invoking `func` until after `wait`
     * milliseconds have elapsed since the last time the debounced function was
     * invoked. The debounced function comes with a `cancel` method to cancel
     * delayed `func` invocations and a `flush` method to immediately invoke them.
     * Provide `options` to indicate whether `func` should be invoked on the
     * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
     * with the last arguments provided to the debounced function. Subsequent
     * calls to the debounced function return the result of the last `func`
     * invocation.
     *
     * **Note:** If `leading` and `trailing` options are `true`, `func` is
     * invoked on the trailing edge of the timeout only if the debounced function
     * is invoked more than once during the `wait` timeout.
     *
     * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
     * until to the next tick, similar to `setTimeout` with a timeout of `0`.
     *
     * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
     * for details over the differences between `_.debounce` and `_.throttle`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {Function} func The function to debounce.
     * @param {number} [wait=0] The number of milliseconds to delay.
     * @param {Object} [options={}] The options object.
     * @param {boolean} [options.leading=false]
     *  Specify invoking on the leading edge of the timeout.
     * @param {number} [options.maxWait]
     *  The maximum time `func` is allowed to be delayed before it's invoked.
     * @param {boolean} [options.trailing=true]
     *  Specify invoking on the trailing edge of the timeout.
     * @returns {Function} Returns the new debounced function.
     * @example
     *
     * // Avoid costly calculations while the window size is in flux.
     * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
     *
     * // Invoke `sendMail` when clicked, debouncing subsequent calls.
     * jQuery(element).on('click', _.debounce(sendMail, 300, {
     *   'leading': true,
     *   'trailing': false
     * }));
     *
     * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
     * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
     * var source = new EventSource('/stream');
     * jQuery(source).on('message', debounced);
     *
     * // Cancel the trailing debounced invocation.
     * jQuery(window).on('popstate', debounced.cancel);
     */
    function debounce(func, wait, options) {
      var lastArgs,
          lastThis,
          maxWait,
          result,
          timerId,
          lastCallTime,
          lastInvokeTime = 0,
          leading = false,
          maxing = false,
          trailing = true;

      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      wait = toNumber(wait) || 0;
      if (isObject(options)) {
        leading = !!options.leading;
        maxing = 'maxWait' in options;
        maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
        trailing = 'trailing' in options ? !!options.trailing : trailing;
      }

      function invokeFunc(time) {
        var args = lastArgs,
            thisArg = lastThis;

        lastArgs = lastThis = undefined;
        lastInvokeTime = time;
        result = func.apply(thisArg, args);
        return result;
      }

      function leadingEdge(time) {
        // Reset any `maxWait` timer.
        lastInvokeTime = time;
        // Start the timer for the trailing edge.
        timerId = setTimeout(timerExpired, wait);
        // Invoke the leading edge.
        return leading ? invokeFunc(time) : result;
      }

      function remainingWait(time) {
        var timeSinceLastCall = time - lastCallTime,
            timeSinceLastInvoke = time - lastInvokeTime,
            result = wait - timeSinceLastCall;

        return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
      }

      function shouldInvoke(time) {
        var timeSinceLastCall = time - lastCallTime,
            timeSinceLastInvoke = time - lastInvokeTime;

        // Either this is the first call, activity has stopped and we're at the
        // trailing edge, the system time has gone backwards and we're treating
        // it as the trailing edge, or we've hit the `maxWait` limit.
        return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
          (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
      }

      function timerExpired() {
        var time = now();
        if (shouldInvoke(time)) {
          return trailingEdge(time);
        }
        // Restart the timer.
        timerId = setTimeout(timerExpired, remainingWait(time));
      }

      function trailingEdge(time) {
        timerId = undefined;

        // Only invoke if we have `lastArgs` which means `func` has been
        // debounced at least once.
        if (trailing && lastArgs) {
          return invokeFunc(time);
        }
        lastArgs = lastThis = undefined;
        return result;
      }

      function cancel() {
        if (timerId !== undefined) {
          clearTimeout(timerId);
        }
        lastInvokeTime = 0;
        lastArgs = lastCallTime = lastThis = timerId = undefined;
      }

      function flush() {
        return timerId === undefined ? result : trailingEdge(now());
      }

      function debounced() {
        var time = now(),
            isInvoking = shouldInvoke(time);

        lastArgs = arguments;
        lastThis = this;
        lastCallTime = time;

        if (isInvoking) {
          if (timerId === undefined) {
            return leadingEdge(lastCallTime);
          }
          if (maxing) {
            // Handle invocations in a tight loop.
            timerId = setTimeout(timerExpired, wait);
            return invokeFunc(lastCallTime);
          }
        }
        if (timerId === undefined) {
          timerId = setTimeout(timerExpired, wait);
        }
        return result;
      }
      debounced.cancel = cancel;
      debounced.flush = flush;
      return debounced;
    }

    /**
     * Defers invoking the `func` until the current call stack has cleared. Any
     * additional arguments are provided to `func` when it's invoked.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {Function} func The function to defer.
     * @param {...*} [args] The arguments to invoke `func` with.
     * @returns {number} Returns the timer id.
     * @example
     *
     * _.defer(function(text) {
     *   console.log(text);
     * }, 'deferred');
     * // => Logs 'deferred' after one millisecond.
     */
    var defer = baseRest(function(func, args) {
      return baseDelay(func, 1, args);
    });

    /**
     * Invokes `func` after `wait` milliseconds. Any additional arguments are
     * provided to `func` when it's invoked.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {Function} func The function to delay.
     * @param {number} wait The number of milliseconds to delay invocation.
     * @param {...*} [args] The arguments to invoke `func` with.
     * @returns {number} Returns the timer id.
     * @example
     *
     * _.delay(function(text) {
     *   console.log(text);
     * }, 1000, 'later');
     * // => Logs 'later' after one second.
     */
    var delay = baseRest(function(func, wait, args) {
      return baseDelay(func, toNumber(wait) || 0, args);
    });

    /**
     * Creates a function that invokes `func` with arguments reversed.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Function
     * @param {Function} func The function to flip arguments for.
     * @returns {Function} Returns the new flipped function.
     * @example
     *
     * var flipped = _.flip(function() {
     *   return _.toArray(arguments);
     * });
     *
     * flipped('a', 'b', 'c', 'd');
     * // => ['d', 'c', 'b', 'a']
     */
    function flip(func) {
      return createWrap(func, WRAP_FLIP_FLAG);
    }

    /**
     * Creates a function that memoizes the result of `func`. If `resolver` is
     * provided, it determines the cache key for storing the result based on the
     * arguments provided to the memoized function. By default, the first argument
     * provided to the memoized function is used as the map cache key. The `func`
     * is invoked with the `this` binding of the memoized function.
     *
     * **Note:** The cache is exposed as the `cache` property on the memoized
     * function. Its creation may be customized by replacing the `_.memoize.Cache`
     * constructor with one whose instances implement the
     * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
     * method interface of `clear`, `delete`, `get`, `has`, and `set`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {Function} func The function to have its output memoized.
     * @param {Function} [resolver] The function to resolve the cache key.
     * @returns {Function} Returns the new memoized function.
     * @example
     *
     * var object = { 'a': 1, 'b': 2 };
     * var other = { 'c': 3, 'd': 4 };
     *
     * var values = _.memoize(_.values);
     * values(object);
     * // => [1, 2]
     *
     * values(other);
     * // => [3, 4]
     *
     * object.a = 2;
     * values(object);
     * // => [1, 2]
     *
     * // Modify the result cache.
     * values.cache.set(object, ['a', 'b']);
     * values(object);
     * // => ['a', 'b']
     *
     * // Replace `_.memoize.Cache`.
     * _.memoize.Cache = WeakMap;
     */
    function memoize(func, resolver) {
      if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      var memoized = function() {
        var args = arguments,
            key = resolver ? resolver.apply(this, args) : args[0],
            cache = memoized.cache;

        if (cache.has(key)) {
          return cache.get(key);
        }
        var result = func.apply(this, args);
        memoized.cache = cache.set(key, result) || cache;
        return result;
      };
      memoized.cache = new (memoize.Cache || MapCache);
      return memoized;
    }

    // Expose `MapCache`.
    memoize.Cache = MapCache;

    /**
     * Creates a function that negates the result of the predicate `func`. The
     * `func` predicate is invoked with the `this` binding and arguments of the
     * created function.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Function
     * @param {Function} predicate The predicate to negate.
     * @returns {Function} Returns the new negated function.
     * @example
     *
     * function isEven(n) {
     *   return n % 2 == 0;
     * }
     *
     * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
     * // => [1, 3, 5]
     */
    function negate(predicate) {
      if (typeof predicate != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      return function() {
        var args = arguments;
        switch (args.length) {
          case 0: return !predicate.call(this);
          case 1: return !predicate.call(this, args[0]);
          case 2: return !predicate.call(this, args[0], args[1]);
          case 3: return !predicate.call(this, args[0], args[1], args[2]);
        }
        return !predicate.apply(this, args);
      };
    }

    /**
     * Creates a function that is restricted to invoking `func` once. Repeat calls
     * to the function return the value of the first invocation. The `func` is
     * invoked with the `this` binding and arguments of the created function.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {Function} func The function to restrict.
     * @returns {Function} Returns the new restricted function.
     * @example
     *
     * var initialize = _.once(createApplication);
     * initialize();
     * initialize();
     * // => `createApplication` is invoked once
     */
    function once(func) {
      return before(2, func);
    }

    /**
     * Creates a function that invokes `func` with its arguments transformed.
     *
     * @static
     * @since 4.0.0
     * @memberOf _
     * @category Function
     * @param {Function} func The function to wrap.
     * @param {...(Function|Function[])} [transforms=[_.identity]]
     *  The argument transforms.
     * @returns {Function} Returns the new function.
     * @example
     *
     * function doubled(n) {
     *   return n * 2;
     * }
     *
     * function square(n) {
     *   return n * n;
     * }
     *
     * var func = _.overArgs(function(x, y) {
     *   return [x, y];
     * }, [square, doubled]);
     *
     * func(9, 3);
     * // => [81, 6]
     *
     * func(10, 5);
     * // => [100, 10]
     */
    var overArgs = castRest(function(func, transforms) {
      transforms = (transforms.length == 1 && isArray(transforms[0]))
        ? arrayMap(transforms[0], baseUnary(getIteratee()))
        : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));

      var funcsLength = transforms.length;
      return baseRest(function(args) {
        var index = -1,
            length = nativeMin(args.length, funcsLength);

        while (++index < length) {
          args[index] = transforms[index].call(this, args[index]);
        }
        return apply(func, this, args);
      });
    });

    /**
     * Creates a function that invokes `func` with `partials` prepended to the
     * arguments it receives. This method is like `_.bind` except it does **not**
     * alter the `this` binding.
     *
     * The `_.partial.placeholder` value, which defaults to `_` in monolithic
     * builds, may be used as a placeholder for partially applied arguments.
     *
     * **Note:** This method doesn't set the "length" property of partially
     * applied functions.
     *
     * @static
     * @memberOf _
     * @since 0.2.0
     * @category Function
     * @param {Function} func The function to partially apply arguments to.
     * @param {...*} [partials] The arguments to be partially applied.
     * @returns {Function} Returns the new partially applied function.
     * @example
     *
     * function greet(greeting, name) {
     *   return greeting + ' ' + name;
     * }
     *
     * var sayHelloTo = _.partial(greet, 'hello');
     * sayHelloTo('fred');
     * // => 'hello fred'
     *
     * // Partially applied with placeholders.
     * var greetFred = _.partial(greet, _, 'fred');
     * greetFred('hi');
     * // => 'hi fred'
     */
    var partial = baseRest(function(func, partials) {
      var holders = replaceHolders(partials, getHolder(partial));
      return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
    });

    /**
     * This method is like `_.partial` except that partially applied arguments
     * are appended to the arguments it receives.
     *
     * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
     * builds, may be used as a placeholder for partially applied arguments.
     *
     * **Note:** This method doesn't set the "length" property of partially
     * applied functions.
     *
     * @static
     * @memberOf _
     * @since 1.0.0
     * @category Function
     * @param {Function} func The function to partially apply arguments to.
     * @param {...*} [partials] The arguments to be partially applied.
     * @returns {Function} Returns the new partially applied function.
     * @example
     *
     * function greet(greeting, name) {
     *   return greeting + ' ' + name;
     * }
     *
     * var greetFred = _.partialRight(greet, 'fred');
     * greetFred('hi');
     * // => 'hi fred'
     *
     * // Partially applied with placeholders.
     * var sayHelloTo = _.partialRight(greet, 'hello', _);
     * sayHelloTo('fred');
     * // => 'hello fred'
     */
    var partialRight = baseRest(function(func, partials) {
      var holders = replaceHolders(partials, getHolder(partialRight));
      return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
    });

    /**
     * Creates a function that invokes `func` with arguments arranged according
     * to the specified `indexes` where the argument value at the first index is
     * provided as the first argument, the argument value at the second index is
     * provided as the second argument, and so on.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Function
     * @param {Function} func The function to rearrange arguments for.
     * @param {...(number|number[])} indexes The arranged argument indexes.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var rearged = _.rearg(function(a, b, c) {
     *   return [a, b, c];
     * }, [2, 0, 1]);
     *
     * rearged('b', 'c', 'a')
     * // => ['a', 'b', 'c']
     */
    var rearg = flatRest(function(func, indexes) {
      return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
    });

    /**
     * Creates a function that invokes `func` with the `this` binding of the
     * created function and arguments from `start` and beyond provided as
     * an array.
     *
     * **Note:** This method is based on the
     * [rest parameter](https://mdn.io/rest_parameters).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Function
     * @param {Function} func The function to apply a rest parameter to.
     * @param {number} [start=func.length-1] The start position of the rest parameter.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var say = _.rest(function(what, names) {
     *   return what + ' ' + _.initial(names).join(', ') +
     *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
     * });
     *
     * say('hello', 'fred', 'barney', 'pebbles');
     * // => 'hello fred, barney, & pebbles'
     */
    function rest(func, start) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      start = start === undefined ? start : toInteger(start);
      return baseRest(func, start);
    }

    /**
     * Creates a function that invokes `func` with the `this` binding of the
     * create function and an array of arguments much like
     * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
     *
     * **Note:** This method is based on the
     * [spread operator](https://mdn.io/spread_operator).
     *
     * @static
     * @memberOf _
     * @since 3.2.0
     * @category Function
     * @param {Function} func The function to spread arguments over.
     * @param {number} [start=0] The start position of the spread.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var say = _.spread(function(who, what) {
     *   return who + ' says ' + what;
     * });
     *
     * say(['fred', 'hello']);
     * // => 'fred says hello'
     *
     * var numbers = Promise.all([
     *   Promise.resolve(40),
     *   Promise.resolve(36)
     * ]);
     *
     * numbers.then(_.spread(function(x, y) {
     *   return x + y;
     * }));
     * // => a Promise of 76
     */
    function spread(func, start) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      start = start == null ? 0 : nativeMax(toInteger(start), 0);
      return baseRest(function(args) {
        var array = args[start],
            otherArgs = castSlice(args, 0, start);

        if (array) {
          arrayPush(otherArgs, array);
        }
        return apply(func, this, otherArgs);
      });
    }

    /**
     * Creates a throttled function that only invokes `func` at most once per
     * every `wait` milliseconds. The throttled function comes with a `cancel`
     * method to cancel delayed `func` invocations and a `flush` method to
     * immediately invoke them. Provide `options` to indicate whether `func`
     * should be invoked on the leading and/or trailing edge of the `wait`
     * timeout. The `func` is invoked with the last arguments provided to the
     * throttled function. Subsequent calls to the throttled function return the
     * result of the last `func` invocation.
     *
     * **Note:** If `leading` and `trailing` options are `true`, `func` is
     * invoked on the trailing edge of the timeout only if the throttled function
     * is invoked more than once during the `wait` timeout.
     *
     * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
     * until to the next tick, similar to `setTimeout` with a timeout of `0`.
     *
     * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
     * for details over the differences between `_.throttle` and `_.debounce`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {Function} func The function to throttle.
     * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
     * @param {Object} [options={}] The options object.
     * @param {boolean} [options.leading=true]
     *  Specify invoking on the leading edge of the timeout.
     * @param {boolean} [options.trailing=true]
     *  Specify invoking on the trailing edge of the timeout.
     * @returns {Function} Returns the new throttled function.
     * @example
     *
     * // Avoid excessively updating the position while scrolling.
     * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
     *
     * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
     * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
     * jQuery(element).on('click', throttled);
     *
     * // Cancel the trailing throttled invocation.
     * jQuery(window).on('popstate', throttled.cancel);
     */
    function throttle(func, wait, options) {
      var leading = true,
          trailing = true;

      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      if (isObject(options)) {
        leading = 'leading' in options ? !!options.leading : leading;
        trailing = 'trailing' in options ? !!options.trailing : trailing;
      }
      return debounce(func, wait, {
        'leading': leading,
        'maxWait': wait,
        'trailing': trailing
      });
    }

    /**
     * Creates a function that accepts up to one argument, ignoring any
     * additional arguments.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Function
     * @param {Function} func The function to cap arguments for.
     * @returns {Function} Returns the new capped function.
     * @example
     *
     * _.map(['6', '8', '10'], _.unary(parseInt));
     * // => [6, 8, 10]
     */
    function unary(func) {
      return ary(func, 1);
    }

    /**
     * Creates a function that provides `value` to `wrapper` as its first
     * argument. Any additional arguments provided to the function are appended
     * to those provided to the `wrapper`. The wrapper is invoked with the `this`
     * binding of the created function.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Function
     * @param {*} value The value to wrap.
     * @param {Function} [wrapper=identity] The wrapper function.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var p = _.wrap(_.escape, function(func, text) {
     *   return '<p>' + func(text) + '</p>';
     * });
     *
     * p('fred, barney, & pebbles');
     * // => '<p>fred, barney, &amp; pebbles</p>'
     */
    function wrap(value, wrapper) {
      return partial(castFunction(wrapper), value);
    }

    /*------------------------------------------------------------------------*/

    /**
     * Casts `value` as an array if it's not one.
     *
     * @static
     * @memberOf _
     * @since 4.4.0
     * @category Lang
     * @param {*} value The value to inspect.
     * @returns {Array} Returns the cast array.
     * @example
     *
     * _.castArray(1);
     * // => [1]
     *
     * _.castArray({ 'a': 1 });
     * // => [{ 'a': 1 }]
     *
     * _.castArray('abc');
     * // => ['abc']
     *
     * _.castArray(null);
     * // => [null]
     *
     * _.castArray(undefined);
     * // => [undefined]
     *
     * _.castArray();
     * // => []
     *
     * var array = [1, 2, 3];
     * console.log(_.castArray(array) === array);
     * // => true
     */
    function castArray() {
      if (!arguments.length) {
        return [];
      }
      var value = arguments[0];
      return isArray(value) ? value : [value];
    }

    /**
     * Creates a shallow clone of `value`.
     *
     * **Note:** This method is loosely based on the
     * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
     * and supports cloning arrays, array buffers, booleans, date objects, maps,
     * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
     * arrays. The own enumerable properties of `arguments` objects are cloned
     * as plain objects. An empty object is returned for uncloneable values such
     * as error objects, functions, DOM nodes, and WeakMaps.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to clone.
     * @returns {*} Returns the cloned value.
     * @see _.cloneDeep
     * @example
     *
     * var objects = [{ 'a': 1 }, { 'b': 2 }];
     *
     * var shallow = _.clone(objects);
     * console.log(shallow[0] === objects[0]);
     * // => true
     */
    function clone(value) {
      return baseClone(value, CLONE_SYMBOLS_FLAG);
    }

    /**
     * This method is like `_.clone` except that it accepts `customizer` which
     * is invoked to produce the cloned value. If `customizer` returns `undefined`,
     * cloning is handled by the method instead. The `customizer` is invoked with
     * up to four arguments; (value [, index|key, object, stack]).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to clone.
     * @param {Function} [customizer] The function to customize cloning.
     * @returns {*} Returns the cloned value.
     * @see _.cloneDeepWith
     * @example
     *
     * function customizer(value) {
     *   if (_.isElement(value)) {
     *     return value.cloneNode(false);
     *   }
     * }
     *
     * var el = _.cloneWith(document.body, customizer);
     *
     * console.log(el === document.body);
     * // => false
     * console.log(el.nodeName);
     * // => 'BODY'
     * console.log(el.childNodes.length);
     * // => 0
     */
    function cloneWith(value, customizer) {
      customizer = typeof customizer == 'function' ? customizer : undefined;
      return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
    }

    /**
     * This method is like `_.clone` except that it recursively clones `value`.
     *
     * @static
     * @memberOf _
     * @since 1.0.0
     * @category Lang
     * @param {*} value The value to recursively clone.
     * @returns {*} Returns the deep cloned value.
     * @see _.clone
     * @example
     *
     * var objects = [{ 'a': 1 }, { 'b': 2 }];
     *
     * var deep = _.cloneDeep(objects);
     * console.log(deep[0] === objects[0]);
     * // => false
     */
    function cloneDeep(value) {
      return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
    }

    /**
     * This method is like `_.cloneWith` except that it recursively clones `value`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to recursively clone.
     * @param {Function} [customizer] The function to customize cloning.
     * @returns {*} Returns the deep cloned value.
     * @see _.cloneWith
     * @example
     *
     * function customizer(value) {
     *   if (_.isElement(value)) {
     *     return value.cloneNode(true);
     *   }
     * }
     *
     * var el = _.cloneDeepWith(document.body, customizer);
     *
     * console.log(el === document.body);
     * // => false
     * console.log(el.nodeName);
     * // => 'BODY'
     * console.log(el.childNodes.length);
     * // => 20
     */
    function cloneDeepWith(value, customizer) {
      customizer = typeof customizer == 'function' ? customizer : undefined;
      return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
    }

    /**
     * Checks if `object` conforms to `source` by invoking the predicate
     * properties of `source` with the corresponding property values of `object`.
     *
     * **Note:** This method is equivalent to `_.conforms` when `source` is
     * partially applied.
     *
     * @static
     * @memberOf _
     * @since 4.14.0
     * @category Lang
     * @param {Object} object The object to inspect.
     * @param {Object} source The object of property predicates to conform to.
     * @returns {boolean} Returns `true` if `object` conforms, else `false`.
     * @example
     *
     * var object = { 'a': 1, 'b': 2 };
     *
     * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
     * // => true
     *
     * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
     * // => false
     */
    function conformsTo(object, source) {
      return source == null || baseConformsTo(object, source, keys(source));
    }

    /**
     * Performs a
     * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
     * comparison between two values to determine if they are equivalent.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
     * @example
     *
     * var object = { 'a': 1 };
     * var other = { 'a': 1 };
     *
     * _.eq(object, object);
     * // => true
     *
     * _.eq(object, other);
     * // => false
     *
     * _.eq('a', 'a');
     * // => true
     *
     * _.eq('a', Object('a'));
     * // => false
     *
     * _.eq(NaN, NaN);
     * // => true
     */
    function eq(value, other) {
      return value === other || (value !== value && other !== other);
    }

    /**
     * Checks if `value` is greater than `other`.
     *
     * @static
     * @memberOf _
     * @since 3.9.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if `value` is greater than `other`,
     *  else `false`.
     * @see _.lt
     * @example
     *
     * _.gt(3, 1);
     * // => true
     *
     * _.gt(3, 3);
     * // => false
     *
     * _.gt(1, 3);
     * // => false
     */
    var gt = createRelationalOperation(baseGt);

    /**
     * Checks if `value` is greater than or equal to `other`.
     *
     * @static
     * @memberOf _
     * @since 3.9.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if `value` is greater than or equal to
     *  `other`, else `false`.
     * @see _.lte
     * @example
     *
     * _.gte(3, 1);
     * // => true
     *
     * _.gte(3, 3);
     * // => true
     *
     * _.gte(1, 3);
     * // => false
     */
    var gte = createRelationalOperation(function(value, other) {
      return value >= other;
    });

    /**
     * Checks if `value` is likely an `arguments` object.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an `arguments` object,
     *  else `false`.
     * @example
     *
     * _.isArguments(function() { return arguments; }());
     * // => true
     *
     * _.isArguments([1, 2, 3]);
     * // => false
     */
    var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
      return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
        !propertyIsEnumerable.call(value, 'callee');
    };

    /**
     * Checks if `value` is classified as an `Array` object.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an array, else `false`.
     * @example
     *
     * _.isArray([1, 2, 3]);
     * // => true
     *
     * _.isArray(document.body.children);
     * // => false
     *
     * _.isArray('abc');
     * // => false
     *
     * _.isArray(_.noop);
     * // => false
     */
    var isArray = Array.isArray;

    /**
     * Checks if `value` is classified as an `ArrayBuffer` object.
     *
     * @static
     * @memberOf _
     * @since 4.3.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
     * @example
     *
     * _.isArrayBuffer(new ArrayBuffer(2));
     * // => true
     *
     * _.isArrayBuffer(new Array(2));
     * // => false
     */
    var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;

    /**
     * Checks if `value` is array-like. A value is considered array-like if it's
     * not a function and has a `value.length` that's an integer greater than or
     * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
     * @example
     *
     * _.isArrayLike([1, 2, 3]);
     * // => true
     *
     * _.isArrayLike(document.body.children);
     * // => true
     *
     * _.isArrayLike('abc');
     * // => true
     *
     * _.isArrayLike(_.noop);
     * // => false
     */
    function isArrayLike(value) {
      return value != null && isLength(value.length) && !isFunction(value);
    }

    /**
     * This method is like `_.isArrayLike` except that it also checks if `value`
     * is an object.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an array-like object,
     *  else `false`.
     * @example
     *
     * _.isArrayLikeObject([1, 2, 3]);
     * // => true
     *
     * _.isArrayLikeObject(document.body.children);
     * // => true
     *
     * _.isArrayLikeObject('abc');
     * // => false
     *
     * _.isArrayLikeObject(_.noop);
     * // => false
     */
    function isArrayLikeObject(value) {
      return isObjectLike(value) && isArrayLike(value);
    }

    /**
     * Checks if `value` is classified as a boolean primitive or object.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
     * @example
     *
     * _.isBoolean(false);
     * // => true
     *
     * _.isBoolean(null);
     * // => false
     */
    function isBoolean(value) {
      return value === true || value === false ||
        (isObjectLike(value) && baseGetTag(value) == boolTag);
    }

    /**
     * Checks if `value` is a buffer.
     *
     * @static
     * @memberOf _
     * @since 4.3.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
     * @example
     *
     * _.isBuffer(new Buffer(2));
     * // => true
     *
     * _.isBuffer(new Uint8Array(2));
     * // => false
     */
    var isBuffer = nativeIsBuffer || stubFalse;

    /**
     * Checks if `value` is classified as a `Date` object.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
     * @example
     *
     * _.isDate(new Date);
     * // => true
     *
     * _.isDate('Mon April 23 2012');
     * // => false
     */
    var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;

    /**
     * Checks if `value` is likely a DOM element.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
     * @example
     *
     * _.isElement(document.body);
     * // => true
     *
     * _.isElement('<body>');
     * // => false
     */
    function isElement(value) {
      return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
    }

    /**
     * Checks if `value` is an empty object, collection, map, or set.
     *
     * Objects are considered empty if they have no own enumerable string keyed
     * properties.
     *
     * Array-like values such as `arguments` objects, arrays, buffers, strings, or
     * jQuery-like collections are considered empty if they have a `length` of `0`.
     * Similarly, maps and sets are considered empty if they have a `size` of `0`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is empty, else `false`.
     * @example
     *
     * _.isEmpty(null);
     * // => true
     *
     * _.isEmpty(true);
     * // => true
     *
     * _.isEmpty(1);
     * // => true
     *
     * _.isEmpty([1, 2, 3]);
     * // => false
     *
     * _.isEmpty({ 'a': 1 });
     * // => false
     */
    function isEmpty(value) {
      if (value == null) {
        return true;
      }
      if (isArrayLike(value) &&
          (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
            isBuffer(value) || isTypedArray(value) || isArguments(value))) {
        return !value.length;
      }
      var tag = getTag(value);
      if (tag == mapTag || tag == setTag) {
        return !value.size;
      }
      if (isPrototype(value)) {
        return !baseKeys(value).length;
      }
      for (var key in value) {
        if (hasOwnProperty.call(value, key)) {
          return false;
        }
      }
      return true;
    }

    /**
     * Performs a deep comparison between two values to determine if they are
     * equivalent.
     *
     * **Note:** This method supports comparing arrays, array buffers, booleans,
     * date objects, error objects, maps, numbers, `Object` objects, regexes,
     * sets, strings, symbols, and typed arrays. `Object` objects are compared
     * by their own, not inherited, enumerable properties. Functions and DOM
     * nodes are compared by strict equality, i.e. `===`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
     * @example
     *
     * var object = { 'a': 1 };
     * var other = { 'a': 1 };
     *
     * _.isEqual(object, other);
     * // => true
     *
     * object === other;
     * // => false
     */
    function isEqual(value, other) {
      return baseIsEqual(value, other);
    }

    /**
     * This method is like `_.isEqual` except that it accepts `customizer` which
     * is invoked to compare values. If `customizer` returns `undefined`, comparisons
     * are handled by the method instead. The `customizer` is invoked with up to
     * six arguments: (objValue, othValue [, index|key, object, other, stack]).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @param {Function} [customizer] The function to customize comparisons.
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
     * @example
     *
     * function isGreeting(value) {
     *   return /^h(?:i|ello)$/.test(value);
     * }
     *
     * function customizer(objValue, othValue) {
     *   if (isGreeting(objValue) && isGreeting(othValue)) {
     *     return true;
     *   }
     * }
     *
     * var array = ['hello', 'goodbye'];
     * var other = ['hi', 'goodbye'];
     *
     * _.isEqualWith(array, other, customizer);
     * // => true
     */
    function isEqualWith(value, other, customizer) {
      customizer = typeof customizer == 'function' ? customizer : undefined;
      var result = customizer ? customizer(value, other) : undefined;
      return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
    }

    /**
     * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
     * `SyntaxError`, `TypeError`, or `URIError` object.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
     * @example
     *
     * _.isError(new Error);
     * // => true
     *
     * _.isError(Error);
     * // => false
     */
    function isError(value) {
      if (!isObjectLike(value)) {
        return false;
      }
      var tag = baseGetTag(value);
      return tag == errorTag || tag == domExcTag ||
        (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
    }

    /**
     * Checks if `value` is a finite primitive number.
     *
     * **Note:** This method is based on
     * [`Number.isFinite`](https://mdn.io/Number/isFinite).
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
     * @example
     *
     * _.isFinite(3);
     * // => true
     *
     * _.isFinite(Number.MIN_VALUE);
     * // => true
     *
     * _.isFinite(Infinity);
     * // => false
     *
     * _.isFinite('3');
     * // => false
     */
    function isFinite(value) {
      return typeof value == 'number' && nativeIsFinite(value);
    }

    /**
     * Checks if `value` is classified as a `Function` object.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a function, else `false`.
     * @example
     *
     * _.isFunction(_);
     * // => true
     *
     * _.isFunction(/abc/);
     * // => false
     */
    function isFunction(value) {
      if (!isObject(value)) {
        return false;
      }
      // The use of `Object#toString` avoids issues with the `typeof` operator
      // in Safari 9 which returns 'object' for typed arrays and other constructors.
      var tag = baseGetTag(value);
      return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
    }

    /**
     * Checks if `value` is an integer.
     *
     * **Note:** This method is based on
     * [`Number.isInteger`](https://mdn.io/Number/isInteger).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
     * @example
     *
     * _.isInteger(3);
     * // => true
     *
     * _.isInteger(Number.MIN_VALUE);
     * // => false
     *
     * _.isInteger(Infinity);
     * // => false
     *
     * _.isInteger('3');
     * // => false
     */
    function isInteger(value) {
      return typeof value == 'number' && value == toInteger(value);
    }

    /**
     * Checks if `value` is a valid array-like length.
     *
     * **Note:** This method is loosely based on
     * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
     * @example
     *
     * _.isLength(3);
     * // => true
     *
     * _.isLength(Number.MIN_VALUE);
     * // => false
     *
     * _.isLength(Infinity);
     * // => false
     *
     * _.isLength('3');
     * // => false
     */
    function isLength(value) {
      return typeof value == 'number' &&
        value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
    }

    /**
     * Checks if `value` is the
     * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
     * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is an object, else `false`.
     * @example
     *
     * _.isObject({});
     * // => true
     *
     * _.isObject([1, 2, 3]);
     * // => true
     *
     * _.isObject(_.noop);
     * // => true
     *
     * _.isObject(null);
     * // => false
     */
    function isObject(value) {
      var type = typeof value;
      return value != null && (type == 'object' || type == 'function');
    }

    /**
     * Checks if `value` is object-like. A value is object-like if it's not `null`
     * and has a `typeof` result of "object".
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
     * @example
     *
     * _.isObjectLike({});
     * // => true
     *
     * _.isObjectLike([1, 2, 3]);
     * // => true
     *
     * _.isObjectLike(_.noop);
     * // => false
     *
     * _.isObjectLike(null);
     * // => false
     */
    function isObjectLike(value) {
      return value != null && typeof value == 'object';
    }

    /**
     * Checks if `value` is classified as a `Map` object.
     *
     * @static
     * @memberOf _
     * @since 4.3.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a map, else `false`.
     * @example
     *
     * _.isMap(new Map);
     * // => true
     *
     * _.isMap(new WeakMap);
     * // => false
     */
    var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;

    /**
     * Performs a partial deep comparison between `object` and `source` to
     * determine if `object` contains equivalent property values.
     *
     * **Note:** This method is equivalent to `_.matches` when `source` is
     * partially applied.
     *
     * Partial comparisons will match empty array and empty object `source`
     * values against any array or object value, respectively. See `_.isEqual`
     * for a list of supported value comparisons.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Lang
     * @param {Object} object The object to inspect.
     * @param {Object} source The object of property values to match.
     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
     * @example
     *
     * var object = { 'a': 1, 'b': 2 };
     *
     * _.isMatch(object, { 'b': 2 });
     * // => true
     *
     * _.isMatch(object, { 'b': 1 });
     * // => false
     */
    function isMatch(object, source) {
      return object === source || baseIsMatch(object, source, getMatchData(source));
    }

    /**
     * This method is like `_.isMatch` except that it accepts `customizer` which
     * is invoked to compare values. If `customizer` returns `undefined`, comparisons
     * are handled by the method instead. The `customizer` is invoked with five
     * arguments: (objValue, srcValue, index|key, object, source).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {Object} object The object to inspect.
     * @param {Object} source The object of property values to match.
     * @param {Function} [customizer] The function to customize comparisons.
     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
     * @example
     *
     * function isGreeting(value) {
     *   return /^h(?:i|ello)$/.test(value);
     * }
     *
     * function customizer(objValue, srcValue) {
     *   if (isGreeting(objValue) && isGreeting(srcValue)) {
     *     return true;
     *   }
     * }
     *
     * var object = { 'greeting': 'hello' };
     * var source = { 'greeting': 'hi' };
     *
     * _.isMatchWith(object, source, customizer);
     * // => true
     */
    function isMatchWith(object, source, customizer) {
      customizer = typeof customizer == 'function' ? customizer : undefined;
      return baseIsMatch(object, source, getMatchData(source), customizer);
    }

    /**
     * Checks if `value` is `NaN`.
     *
     * **Note:** This method is based on
     * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
     * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
     * `undefined` and other non-number values.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
     * @example
     *
     * _.isNaN(NaN);
     * // => true
     *
     * _.isNaN(new Number(NaN));
     * // => true
     *
     * isNaN(undefined);
     * // => true
     *
     * _.isNaN(undefined);
     * // => false
     */
    function isNaN(value) {
      // An `NaN` primitive is the only value that is not equal to itself.
      // Perform the `toStringTag` check first to avoid errors with some
      // ActiveX objects in IE.
      return isNumber(value) && value != +value;
    }

    /**
     * Checks if `value` is a pristine native function.
     *
     * **Note:** This method can't reliably detect native functions in the presence
     * of the core-js package because core-js circumvents this kind of detection.
     * Despite multiple requests, the core-js maintainer has made it clear: any
     * attempt to fix the detection will be obstructed. As a result, we're left
     * with little choice but to throw an error. Unfortunately, this also affects
     * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
     * which rely on core-js.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a native function,
     *  else `false`.
     * @example
     *
     * _.isNative(Array.prototype.push);
     * // => true
     *
     * _.isNative(_);
     * // => false
     */
    function isNative(value) {
      if (isMaskable(value)) {
        throw new Error(CORE_ERROR_TEXT);
      }
      return baseIsNative(value);
    }

    /**
     * Checks if `value` is `null`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
     * @example
     *
     * _.isNull(null);
     * // => true
     *
     * _.isNull(void 0);
     * // => false
     */
    function isNull(value) {
      return value === null;
    }

    /**
     * Checks if `value` is `null` or `undefined`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
     * @example
     *
     * _.isNil(null);
     * // => true
     *
     * _.isNil(void 0);
     * // => true
     *
     * _.isNil(NaN);
     * // => false
     */
    function isNil(value) {
      return value == null;
    }

    /**
     * Checks if `value` is classified as a `Number` primitive or object.
     *
     * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
     * classified as numbers, use the `_.isFinite` method.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a number, else `false`.
     * @example
     *
     * _.isNumber(3);
     * // => true
     *
     * _.isNumber(Number.MIN_VALUE);
     * // => true
     *
     * _.isNumber(Infinity);
     * // => true
     *
     * _.isNumber('3');
     * // => false
     */
    function isNumber(value) {
      return typeof value == 'number' ||
        (isObjectLike(value) && baseGetTag(value) == numberTag);
    }

    /**
     * Checks if `value` is a plain object, that is, an object created by the
     * `Object` constructor or one with a `[[Prototype]]` of `null`.
     *
     * @static
     * @memberOf _
     * @since 0.8.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     * }
     *
     * _.isPlainObject(new Foo);
     * // => false
     *
     * _.isPlainObject([1, 2, 3]);
     * // => false
     *
     * _.isPlainObject({ 'x': 0, 'y': 0 });
     * // => true
     *
     * _.isPlainObject(Object.create(null));
     * // => true
     */
    function isPlainObject(value) {
      if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
        return false;
      }
      var proto = getPrototype(value);
      if (proto === null) {
        return true;
      }
      var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
      return typeof Ctor == 'function' && Ctor instanceof Ctor &&
        funcToString.call(Ctor) == objectCtorString;
    }

    /**
     * Checks if `value` is classified as a `RegExp` object.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
     * @example
     *
     * _.isRegExp(/abc/);
     * // => true
     *
     * _.isRegExp('/abc/');
     * // => false
     */
    var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;

    /**
     * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
     * double precision number which isn't the result of a rounded unsafe integer.
     *
     * **Note:** This method is based on
     * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
     * @example
     *
     * _.isSafeInteger(3);
     * // => true
     *
     * _.isSafeInteger(Number.MIN_VALUE);
     * // => false
     *
     * _.isSafeInteger(Infinity);
     * // => false
     *
     * _.isSafeInteger('3');
     * // => false
     */
    function isSafeInteger(value) {
      return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
    }

    /**
     * Checks if `value` is classified as a `Set` object.
     *
     * @static
     * @memberOf _
     * @since 4.3.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a set, else `false`.
     * @example
     *
     * _.isSet(new Set);
     * // => true
     *
     * _.isSet(new WeakSet);
     * // => false
     */
    var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;

    /**
     * Checks if `value` is classified as a `String` primitive or object.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a string, else `false`.
     * @example
     *
     * _.isString('abc');
     * // => true
     *
     * _.isString(1);
     * // => false
     */
    function isString(value) {
      return typeof value == 'string' ||
        (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
    }

    /**
     * Checks if `value` is classified as a `Symbol` primitive or object.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
     * @example
     *
     * _.isSymbol(Symbol.iterator);
     * // => true
     *
     * _.isSymbol('abc');
     * // => false
     */
    function isSymbol(value) {
      return typeof value == 'symbol' ||
        (isObjectLike(value) && baseGetTag(value) == symbolTag);
    }

    /**
     * Checks if `value` is classified as a typed array.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
     * @example
     *
     * _.isTypedArray(new Uint8Array);
     * // => true
     *
     * _.isTypedArray([]);
     * // => false
     */
    var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

    /**
     * Checks if `value` is `undefined`.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
     * @example
     *
     * _.isUndefined(void 0);
     * // => true
     *
     * _.isUndefined(null);
     * // => false
     */
    function isUndefined(value) {
      return value === undefined;
    }

    /**
     * Checks if `value` is classified as a `WeakMap` object.
     *
     * @static
     * @memberOf _
     * @since 4.3.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
     * @example
     *
     * _.isWeakMap(new WeakMap);
     * // => true
     *
     * _.isWeakMap(new Map);
     * // => false
     */
    function isWeakMap(value) {
      return isObjectLike(value) && getTag(value) == weakMapTag;
    }

    /**
     * Checks if `value` is classified as a `WeakSet` object.
     *
     * @static
     * @memberOf _
     * @since 4.3.0
     * @category Lang
     * @param {*} value The value to check.
     * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
     * @example
     *
     * _.isWeakSet(new WeakSet);
     * // => true
     *
     * _.isWeakSet(new Set);
     * // => false
     */
    function isWeakSet(value) {
      return isObjectLike(value) && baseGetTag(value) == weakSetTag;
    }

    /**
     * Checks if `value` is less than `other`.
     *
     * @static
     * @memberOf _
     * @since 3.9.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if `value` is less than `other`,
     *  else `false`.
     * @see _.gt
     * @example
     *
     * _.lt(1, 3);
     * // => true
     *
     * _.lt(3, 3);
     * // => false
     *
     * _.lt(3, 1);
     * // => false
     */
    var lt = createRelationalOperation(baseLt);

    /**
     * Checks if `value` is less than or equal to `other`.
     *
     * @static
     * @memberOf _
     * @since 3.9.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if `value` is less than or equal to
     *  `other`, else `false`.
     * @see _.gte
     * @example
     *
     * _.lte(1, 3);
     * // => true
     *
     * _.lte(3, 3);
     * // => true
     *
     * _.lte(3, 1);
     * // => false
     */
    var lte = createRelationalOperation(function(value, other) {
      return value <= other;
    });

    /**
     * Converts `value` to an array.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Lang
     * @param {*} value The value to convert.
     * @returns {Array} Returns the converted array.
     * @example
     *
     * _.toArray({ 'a': 1, 'b': 2 });
     * // => [1, 2]
     *
     * _.toArray('abc');
     * // => ['a', 'b', 'c']
     *
     * _.toArray(1);
     * // => []
     *
     * _.toArray(null);
     * // => []
     */
    function toArray(value) {
      if (!value) {
        return [];
      }
      if (isArrayLike(value)) {
        return isString(value) ? stringToArray(value) : copyArray(value);
      }
      if (symIterator && value[symIterator]) {
        return iteratorToArray(value[symIterator]());
      }
      var tag = getTag(value),
          func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);

      return func(value);
    }

    /**
     * Converts `value` to a finite number.
     *
     * @static
     * @memberOf _
     * @since 4.12.0
     * @category Lang
     * @param {*} value The value to convert.
     * @returns {number} Returns the converted number.
     * @example
     *
     * _.toFinite(3.2);
     * // => 3.2
     *
     * _.toFinite(Number.MIN_VALUE);
     * // => 5e-324
     *
     * _.toFinite(Infinity);
     * // => 1.7976931348623157e+308
     *
     * _.toFinite('3.2');
     * // => 3.2
     */
    function toFinite(value) {
      if (!value) {
        return value === 0 ? value : 0;
      }
      value = toNumber(value);
      if (value === INFINITY || value === -INFINITY) {
        var sign = (value < 0 ? -1 : 1);
        return sign * MAX_INTEGER;
      }
      return value === value ? value : 0;
    }

    /**
     * Converts `value` to an integer.
     *
     * **Note:** This method is loosely based on
     * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to convert.
     * @returns {number} Returns the converted integer.
     * @example
     *
     * _.toInteger(3.2);
     * // => 3
     *
     * _.toInteger(Number.MIN_VALUE);
     * // => 0
     *
     * _.toInteger(Infinity);
     * // => 1.7976931348623157e+308
     *
     * _.toInteger('3.2');
     * // => 3
     */
    function toInteger(value) {
      var result = toFinite(value),
          remainder = result % 1;

      return result === result ? (remainder ? result - remainder : result) : 0;
    }

    /**
     * Converts `value` to an integer suitable for use as the length of an
     * array-like object.
     *
     * **Note:** This method is based on
     * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to convert.
     * @returns {number} Returns the converted integer.
     * @example
     *
     * _.toLength(3.2);
     * // => 3
     *
     * _.toLength(Number.MIN_VALUE);
     * // => 0
     *
     * _.toLength(Infinity);
     * // => 4294967295
     *
     * _.toLength('3.2');
     * // => 3
     */
    function toLength(value) {
      return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
    }

    /**
     * Converts `value` to a number.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to process.
     * @returns {number} Returns the number.
     * @example
     *
     * _.toNumber(3.2);
     * // => 3.2
     *
     * _.toNumber(Number.MIN_VALUE);
     * // => 5e-324
     *
     * _.toNumber(Infinity);
     * // => Infinity
     *
     * _.toNumber('3.2');
     * // => 3.2
     */
    function toNumber(value) {
      if (typeof value == 'number') {
        return value;
      }
      if (isSymbol(value)) {
        return NAN;
      }
      if (isObject(value)) {
        var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
        value = isObject(other) ? (other + '') : other;
      }
      if (typeof value != 'string') {
        return value === 0 ? value : +value;
      }
      value = value.replace(reTrim, '');
      var isBinary = reIsBinary.test(value);
      return (isBinary || reIsOctal.test(value))
        ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
        : (reIsBadHex.test(value) ? NAN : +value);
    }

    /**
     * Converts `value` to a plain object flattening inherited enumerable string
     * keyed properties of `value` to own properties of the plain object.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Lang
     * @param {*} value The value to convert.
     * @returns {Object} Returns the converted plain object.
     * @example
     *
     * function Foo() {
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.assign({ 'a': 1 }, new Foo);
     * // => { 'a': 1, 'b': 2 }
     *
     * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
     * // => { 'a': 1, 'b': 2, 'c': 3 }
     */
    function toPlainObject(value) {
      return copyObject(value, keysIn(value));
    }

    /**
     * Converts `value` to a safe integer. A safe integer can be compared and
     * represented correctly.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to convert.
     * @returns {number} Returns the converted integer.
     * @example
     *
     * _.toSafeInteger(3.2);
     * // => 3
     *
     * _.toSafeInteger(Number.MIN_VALUE);
     * // => 0
     *
     * _.toSafeInteger(Infinity);
     * // => 9007199254740991
     *
     * _.toSafeInteger('3.2');
     * // => 3
     */
    function toSafeInteger(value) {
      return value
        ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
        : (value === 0 ? value : 0);
    }

    /**
     * Converts `value` to a string. An empty string is returned for `null`
     * and `undefined` values. The sign of `-0` is preserved.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Lang
     * @param {*} value The value to convert.
     * @returns {string} Returns the converted string.
     * @example
     *
     * _.toString(null);
     * // => ''
     *
     * _.toString(-0);
     * // => '-0'
     *
     * _.toString([1, 2, 3]);
     * // => '1,2,3'
     */
    function toString(value) {
      return value == null ? '' : baseToString(value);
    }

    /*------------------------------------------------------------------------*/

    /**
     * Assigns own enumerable string keyed properties of source objects to the
     * destination object. Source objects are applied from left to right.
     * Subsequent sources overwrite property assignments of previous sources.
     *
     * **Note:** This method mutates `object` and is loosely based on
     * [`Object.assign`](https://mdn.io/Object/assign).
     *
     * @static
     * @memberOf _
     * @since 0.10.0
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} [sources] The source objects.
     * @returns {Object} Returns `object`.
     * @see _.assignIn
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     * }
     *
     * function Bar() {
     *   this.c = 3;
     * }
     *
     * Foo.prototype.b = 2;
     * Bar.prototype.d = 4;
     *
     * _.assign({ 'a': 0 }, new Foo, new Bar);
     * // => { 'a': 1, 'c': 3 }
     */
    var assign = createAssigner(function(object, source) {
      if (isPrototype(source) || isArrayLike(source)) {
        copyObject(source, keys(source), object);
        return;
      }
      for (var key in source) {
        if (hasOwnProperty.call(source, key)) {
          assignValue(object, key, source[key]);
        }
      }
    });

    /**
     * This method is like `_.assign` except that it iterates over own and
     * inherited source properties.
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @alias extend
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} [sources] The source objects.
     * @returns {Object} Returns `object`.
     * @see _.assign
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     * }
     *
     * function Bar() {
     *   this.c = 3;
     * }
     *
     * Foo.prototype.b = 2;
     * Bar.prototype.d = 4;
     *
     * _.assignIn({ 'a': 0 }, new Foo, new Bar);
     * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
     */
    var assignIn = createAssigner(function(object, source) {
      copyObject(source, keysIn(source), object);
    });

    /**
     * This method is like `_.assignIn` except that it accepts `customizer`
     * which is invoked to produce the assigned values. If `customizer` returns
     * `undefined`, assignment is handled by the method instead. The `customizer`
     * is invoked with five arguments: (objValue, srcValue, key, object, source).
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @alias extendWith
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} sources The source objects.
     * @param {Function} [customizer] The function to customize assigned values.
     * @returns {Object} Returns `object`.
     * @see _.assignWith
     * @example
     *
     * function customizer(objValue, srcValue) {
     *   return _.isUndefined(objValue) ? srcValue : objValue;
     * }
     *
     * var defaults = _.partialRight(_.assignInWith, customizer);
     *
     * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
     * // => { 'a': 1, 'b': 2 }
     */
    var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
      copyObject(source, keysIn(source), object, customizer);
    });

    /**
     * This method is like `_.assign` except that it accepts `customizer`
     * which is invoked to produce the assigned values. If `customizer` returns
     * `undefined`, assignment is handled by the method instead. The `customizer`
     * is invoked with five arguments: (objValue, srcValue, key, object, source).
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} sources The source objects.
     * @param {Function} [customizer] The function to customize assigned values.
     * @returns {Object} Returns `object`.
     * @see _.assignInWith
     * @example
     *
     * function customizer(objValue, srcValue) {
     *   return _.isUndefined(objValue) ? srcValue : objValue;
     * }
     *
     * var defaults = _.partialRight(_.assignWith, customizer);
     *
     * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
     * // => { 'a': 1, 'b': 2 }
     */
    var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
      copyObject(source, keys(source), object, customizer);
    });

    /**
     * Creates an array of values corresponding to `paths` of `object`.
     *
     * @static
     * @memberOf _
     * @since 1.0.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {...(string|string[])} [paths] The property paths to pick.
     * @returns {Array} Returns the picked values.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
     *
     * _.at(object, ['a[0].b.c', 'a[1]']);
     * // => [3, 4]
     */
    var at = flatRest(baseAt);

    /**
     * Creates an object that inherits from the `prototype` object. If a
     * `properties` object is given, its own enumerable string keyed properties
     * are assigned to the created object.
     *
     * @static
     * @memberOf _
     * @since 2.3.0
     * @category Object
     * @param {Object} prototype The object to inherit from.
     * @param {Object} [properties] The properties to assign to the object.
     * @returns {Object} Returns the new object.
     * @example
     *
     * function Shape() {
     *   this.x = 0;
     *   this.y = 0;
     * }
     *
     * function Circle() {
     *   Shape.call(this);
     * }
     *
     * Circle.prototype = _.create(Shape.prototype, {
     *   'constructor': Circle
     * });
     *
     * var circle = new Circle;
     * circle instanceof Circle;
     * // => true
     *
     * circle instanceof Shape;
     * // => true
     */
    function create(prototype, properties) {
      var result = baseCreate(prototype);
      return properties == null ? result : baseAssign(result, properties);
    }

    /**
     * Assigns own and inherited enumerable string keyed properties of source
     * objects to the destination object for all destination properties that
     * resolve to `undefined`. Source objects are applied from left to right.
     * Once a property is set, additional values of the same property are ignored.
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} [sources] The source objects.
     * @returns {Object} Returns `object`.
     * @see _.defaultsDeep
     * @example
     *
     * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
     * // => { 'a': 1, 'b': 2 }
     */
    var defaults = baseRest(function(args) {
      args.push(undefined, customDefaultsAssignIn);
      return apply(assignInWith, undefined, args);
    });

    /**
     * This method is like `_.defaults` except that it recursively assigns
     * default properties.
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 3.10.0
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} [sources] The source objects.
     * @returns {Object} Returns `object`.
     * @see _.defaults
     * @example
     *
     * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
     * // => { 'a': { 'b': 2, 'c': 3 } }
     */
    var defaultsDeep = baseRest(function(args) {
      args.push(undefined, customDefaultsMerge);
      return apply(mergeWith, undefined, args);
    });

    /**
     * This method is like `_.find` except that it returns the key of the first
     * element `predicate` returns truthy for instead of the element itself.
     *
     * @static
     * @memberOf _
     * @since 1.1.0
     * @category Object
     * @param {Object} object The object to inspect.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {string|undefined} Returns the key of the matched element,
     *  else `undefined`.
     * @example
     *
     * var users = {
     *   'barney':  { 'age': 36, 'active': true },
     *   'fred':    { 'age': 40, 'active': false },
     *   'pebbles': { 'age': 1,  'active': true }
     * };
     *
     * _.findKey(users, function(o) { return o.age < 40; });
     * // => 'barney' (iteration order is not guaranteed)
     *
     * // The `_.matches` iteratee shorthand.
     * _.findKey(users, { 'age': 1, 'active': true });
     * // => 'pebbles'
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.findKey(users, ['active', false]);
     * // => 'fred'
     *
     * // The `_.property` iteratee shorthand.
     * _.findKey(users, 'active');
     * // => 'barney'
     */
    function findKey(object, predicate) {
      return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
    }

    /**
     * This method is like `_.findKey` except that it iterates over elements of
     * a collection in the opposite order.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Object
     * @param {Object} object The object to inspect.
     * @param {Function} [predicate=_.identity] The function invoked per iteration.
     * @returns {string|undefined} Returns the key of the matched element,
     *  else `undefined`.
     * @example
     *
     * var users = {
     *   'barney':  { 'age': 36, 'active': true },
     *   'fred':    { 'age': 40, 'active': false },
     *   'pebbles': { 'age': 1,  'active': true }
     * };
     *
     * _.findLastKey(users, function(o) { return o.age < 40; });
     * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
     *
     * // The `_.matches` iteratee shorthand.
     * _.findLastKey(users, { 'age': 36, 'active': true });
     * // => 'barney'
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.findLastKey(users, ['active', false]);
     * // => 'fred'
     *
     * // The `_.property` iteratee shorthand.
     * _.findLastKey(users, 'active');
     * // => 'pebbles'
     */
    function findLastKey(object, predicate) {
      return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
    }

    /**
     * Iterates over own and inherited enumerable string keyed properties of an
     * object and invokes `iteratee` for each property. The iteratee is invoked
     * with three arguments: (value, key, object). Iteratee functions may exit
     * iteration early by explicitly returning `false`.
     *
     * @static
     * @memberOf _
     * @since 0.3.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Object} Returns `object`.
     * @see _.forInRight
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.forIn(new Foo, function(value, key) {
     *   console.log(key);
     * });
     * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
     */
    function forIn(object, iteratee) {
      return object == null
        ? object
        : baseFor(object, getIteratee(iteratee, 3), keysIn);
    }

    /**
     * This method is like `_.forIn` except that it iterates over properties of
     * `object` in the opposite order.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Object} Returns `object`.
     * @see _.forIn
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.forInRight(new Foo, function(value, key) {
     *   console.log(key);
     * });
     * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
     */
    function forInRight(object, iteratee) {
      return object == null
        ? object
        : baseForRight(object, getIteratee(iteratee, 3), keysIn);
    }

    /**
     * Iterates over own enumerable string keyed properties of an object and
     * invokes `iteratee` for each property. The iteratee is invoked with three
     * arguments: (value, key, object). Iteratee functions may exit iteration
     * early by explicitly returning `false`.
     *
     * @static
     * @memberOf _
     * @since 0.3.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Object} Returns `object`.
     * @see _.forOwnRight
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.forOwn(new Foo, function(value, key) {
     *   console.log(key);
     * });
     * // => Logs 'a' then 'b' (iteration order is not guaranteed).
     */
    function forOwn(object, iteratee) {
      return object && baseForOwn(object, getIteratee(iteratee, 3));
    }

    /**
     * This method is like `_.forOwn` except that it iterates over properties of
     * `object` in the opposite order.
     *
     * @static
     * @memberOf _
     * @since 2.0.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Object} Returns `object`.
     * @see _.forOwn
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.forOwnRight(new Foo, function(value, key) {
     *   console.log(key);
     * });
     * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
     */
    function forOwnRight(object, iteratee) {
      return object && baseForOwnRight(object, getIteratee(iteratee, 3));
    }

    /**
     * Creates an array of function property names from own enumerable properties
     * of `object`.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The object to inspect.
     * @returns {Array} Returns the function names.
     * @see _.functionsIn
     * @example
     *
     * function Foo() {
     *   this.a = _.constant('a');
     *   this.b = _.constant('b');
     * }
     *
     * Foo.prototype.c = _.constant('c');
     *
     * _.functions(new Foo);
     * // => ['a', 'b']
     */
    function functions(object) {
      return object == null ? [] : baseFunctions(object, keys(object));
    }

    /**
     * Creates an array of function property names from own and inherited
     * enumerable properties of `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The object to inspect.
     * @returns {Array} Returns the function names.
     * @see _.functions
     * @example
     *
     * function Foo() {
     *   this.a = _.constant('a');
     *   this.b = _.constant('b');
     * }
     *
     * Foo.prototype.c = _.constant('c');
     *
     * _.functionsIn(new Foo);
     * // => ['a', 'b', 'c']
     */
    function functionsIn(object) {
      return object == null ? [] : baseFunctions(object, keysIn(object));
    }

    /**
     * Gets the value at `path` of `object`. If the resolved value is
     * `undefined`, the `defaultValue` is returned in its place.
     *
     * @static
     * @memberOf _
     * @since 3.7.0
     * @category Object
     * @param {Object} object The object to query.
     * @param {Array|string} path The path of the property to get.
     * @param {*} [defaultValue] The value returned for `undefined` resolved values.
     * @returns {*} Returns the resolved value.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
     *
     * _.get(object, 'a[0].b.c');
     * // => 3
     *
     * _.get(object, ['a', '0', 'b', 'c']);
     * // => 3
     *
     * _.get(object, 'a.b.c', 'default');
     * // => 'default'
     */
    function get(object, path, defaultValue) {
      var result = object == null ? undefined : baseGet(object, path);
      return result === undefined ? defaultValue : result;
    }

    /**
     * Checks if `path` is a direct property of `object`.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The object to query.
     * @param {Array|string} path The path to check.
     * @returns {boolean} Returns `true` if `path` exists, else `false`.
     * @example
     *
     * var object = { 'a': { 'b': 2 } };
     * var other = _.create({ 'a': _.create({ 'b': 2 }) });
     *
     * _.has(object, 'a');
     * // => true
     *
     * _.has(object, 'a.b');
     * // => true
     *
     * _.has(object, ['a', 'b']);
     * // => true
     *
     * _.has(other, 'a');
     * // => false
     */
    function has(object, path) {
      return object != null && hasPath(object, path, baseHas);
    }

    /**
     * Checks if `path` is a direct or inherited property of `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The object to query.
     * @param {Array|string} path The path to check.
     * @returns {boolean} Returns `true` if `path` exists, else `false`.
     * @example
     *
     * var object = _.create({ 'a': _.create({ 'b': 2 }) });
     *
     * _.hasIn(object, 'a');
     * // => true
     *
     * _.hasIn(object, 'a.b');
     * // => true
     *
     * _.hasIn(object, ['a', 'b']);
     * // => true
     *
     * _.hasIn(object, 'b');
     * // => false
     */
    function hasIn(object, path) {
      return object != null && hasPath(object, path, baseHasIn);
    }

    /**
     * Creates an object composed of the inverted keys and values of `object`.
     * If `object` contains duplicate values, subsequent values overwrite
     * property assignments of previous values.
     *
     * @static
     * @memberOf _
     * @since 0.7.0
     * @category Object
     * @param {Object} object The object to invert.
     * @returns {Object} Returns the new inverted object.
     * @example
     *
     * var object = { 'a': 1, 'b': 2, 'c': 1 };
     *
     * _.invert(object);
     * // => { '1': 'c', '2': 'b' }
     */
    var invert = createInverter(function(result, value, key) {
      result[value] = key;
    }, constant(identity));

    /**
     * This method is like `_.invert` except that the inverted object is generated
     * from the results of running each element of `object` thru `iteratee`. The
     * corresponding inverted value of each inverted key is an array of keys
     * responsible for generating the inverted value. The iteratee is invoked
     * with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.1.0
     * @category Object
     * @param {Object} object The object to invert.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {Object} Returns the new inverted object.
     * @example
     *
     * var object = { 'a': 1, 'b': 2, 'c': 1 };
     *
     * _.invertBy(object);
     * // => { '1': ['a', 'c'], '2': ['b'] }
     *
     * _.invertBy(object, function(value) {
     *   return 'group' + value;
     * });
     * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
     */
    var invertBy = createInverter(function(result, value, key) {
      if (hasOwnProperty.call(result, value)) {
        result[value].push(key);
      } else {
        result[value] = [key];
      }
    }, getIteratee);

    /**
     * Invokes the method at `path` of `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The object to query.
     * @param {Array|string} path The path of the method to invoke.
     * @param {...*} [args] The arguments to invoke the method with.
     * @returns {*} Returns the result of the invoked method.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
     *
     * _.invoke(object, 'a[0].b.c.slice', 1, 3);
     * // => [2, 3]
     */
    var invoke = baseRest(baseInvoke);

    /**
     * Creates an array of the own enumerable property names of `object`.
     *
     * **Note:** Non-object values are coerced to objects. See the
     * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
     * for more details.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.keys(new Foo);
     * // => ['a', 'b'] (iteration order is not guaranteed)
     *
     * _.keys('hi');
     * // => ['0', '1']
     */
    function keys(object) {
      return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
    }

    /**
     * Creates an array of the own and inherited enumerable property names of `object`.
     *
     * **Note:** Non-object values are coerced to objects.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property names.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.keysIn(new Foo);
     * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
     */
    function keysIn(object) {
      return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
    }

    /**
     * The opposite of `_.mapValues`; this method creates an object with the
     * same values as `object` and keys generated by running each own enumerable
     * string keyed property of `object` thru `iteratee`. The iteratee is invoked
     * with three arguments: (value, key, object).
     *
     * @static
     * @memberOf _
     * @since 3.8.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Object} Returns the new mapped object.
     * @see _.mapValues
     * @example
     *
     * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
     *   return key + value;
     * });
     * // => { 'a1': 1, 'b2': 2 }
     */
    function mapKeys(object, iteratee) {
      var result = {};
      iteratee = getIteratee(iteratee, 3);

      baseForOwn(object, function(value, key, object) {
        baseAssignValue(result, iteratee(value, key, object), value);
      });
      return result;
    }

    /**
     * Creates an object with the same keys as `object` and values generated
     * by running each own enumerable string keyed property of `object` thru
     * `iteratee`. The iteratee is invoked with three arguments:
     * (value, key, object).
     *
     * @static
     * @memberOf _
     * @since 2.4.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Object} Returns the new mapped object.
     * @see _.mapKeys
     * @example
     *
     * var users = {
     *   'fred':    { 'user': 'fred',    'age': 40 },
     *   'pebbles': { 'user': 'pebbles', 'age': 1 }
     * };
     *
     * _.mapValues(users, function(o) { return o.age; });
     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
     *
     * // The `_.property` iteratee shorthand.
     * _.mapValues(users, 'age');
     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
     */
    function mapValues(object, iteratee) {
      var result = {};
      iteratee = getIteratee(iteratee, 3);

      baseForOwn(object, function(value, key, object) {
        baseAssignValue(result, key, iteratee(value, key, object));
      });
      return result;
    }

    /**
     * This method is like `_.assign` except that it recursively merges own and
     * inherited enumerable string keyed properties of source objects into the
     * destination object. Source properties that resolve to `undefined` are
     * skipped if a destination value exists. Array and plain object properties
     * are merged recursively. Other objects and value types are overridden by
     * assignment. Source objects are applied from left to right. Subsequent
     * sources overwrite property assignments of previous sources.
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 0.5.0
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} [sources] The source objects.
     * @returns {Object} Returns `object`.
     * @example
     *
     * var object = {
     *   'a': [{ 'b': 2 }, { 'd': 4 }]
     * };
     *
     * var other = {
     *   'a': [{ 'c': 3 }, { 'e': 5 }]
     * };
     *
     * _.merge(object, other);
     * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
     */
    var merge = createAssigner(function(object, source, srcIndex) {
      baseMerge(object, source, srcIndex);
    });

    /**
     * This method is like `_.merge` except that it accepts `customizer` which
     * is invoked to produce the merged values of the destination and source
     * properties. If `customizer` returns `undefined`, merging is handled by the
     * method instead. The `customizer` is invoked with six arguments:
     * (objValue, srcValue, key, object, source, stack).
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The destination object.
     * @param {...Object} sources The source objects.
     * @param {Function} customizer The function to customize assigned values.
     * @returns {Object} Returns `object`.
     * @example
     *
     * function customizer(objValue, srcValue) {
     *   if (_.isArray(objValue)) {
     *     return objValue.concat(srcValue);
     *   }
     * }
     *
     * var object = { 'a': [1], 'b': [2] };
     * var other = { 'a': [3], 'b': [4] };
     *
     * _.mergeWith(object, other, customizer);
     * // => { 'a': [1, 3], 'b': [2, 4] }
     */
    var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
      baseMerge(object, source, srcIndex, customizer);
    });

    /**
     * The opposite of `_.pick`; this method creates an object composed of the
     * own and inherited enumerable property paths of `object` that are not omitted.
     *
     * **Note:** This method is considerably slower than `_.pick`.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The source object.
     * @param {...(string|string[])} [paths] The property paths to omit.
     * @returns {Object} Returns the new object.
     * @example
     *
     * var object = { 'a': 1, 'b': '2', 'c': 3 };
     *
     * _.omit(object, ['a', 'c']);
     * // => { 'b': '2' }
     */
    var omit = flatRest(function(object, paths) {
      var result = {};
      if (object == null) {
        return result;
      }
      var isDeep = false;
      paths = arrayMap(paths, function(path) {
        path = castPath(path, object);
        isDeep || (isDeep = path.length > 1);
        return path;
      });
      copyObject(object, getAllKeysIn(object), result);
      if (isDeep) {
        result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
      }
      var length = paths.length;
      while (length--) {
        baseUnset(result, paths[length]);
      }
      return result;
    });

    /**
     * The opposite of `_.pickBy`; this method creates an object composed of
     * the own and inherited enumerable string keyed properties of `object` that
     * `predicate` doesn't return truthy for. The predicate is invoked with two
     * arguments: (value, key).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The source object.
     * @param {Function} [predicate=_.identity] The function invoked per property.
     * @returns {Object} Returns the new object.
     * @example
     *
     * var object = { 'a': 1, 'b': '2', 'c': 3 };
     *
     * _.omitBy(object, _.isNumber);
     * // => { 'b': '2' }
     */
    function omitBy(object, predicate) {
      return pickBy(object, negate(getIteratee(predicate)));
    }

    /**
     * Creates an object composed of the picked `object` properties.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The source object.
     * @param {...(string|string[])} [paths] The property paths to pick.
     * @returns {Object} Returns the new object.
     * @example
     *
     * var object = { 'a': 1, 'b': '2', 'c': 3 };
     *
     * _.pick(object, ['a', 'c']);
     * // => { 'a': 1, 'c': 3 }
     */
    var pick = flatRest(function(object, paths) {
      return object == null ? {} : basePick(object, paths);
    });

    /**
     * Creates an object composed of the `object` properties `predicate` returns
     * truthy for. The predicate is invoked with two arguments: (value, key).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The source object.
     * @param {Function} [predicate=_.identity] The function invoked per property.
     * @returns {Object} Returns the new object.
     * @example
     *
     * var object = { 'a': 1, 'b': '2', 'c': 3 };
     *
     * _.pickBy(object, _.isNumber);
     * // => { 'a': 1, 'c': 3 }
     */
    function pickBy(object, predicate) {
      if (object == null) {
        return {};
      }
      var props = arrayMap(getAllKeysIn(object), function(prop) {
        return [prop];
      });
      predicate = getIteratee(predicate);
      return basePickBy(object, props, function(value, path) {
        return predicate(value, path[0]);
      });
    }

    /**
     * This method is like `_.get` except that if the resolved value is a
     * function it's invoked with the `this` binding of its parent object and
     * its result is returned.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The object to query.
     * @param {Array|string} path The path of the property to resolve.
     * @param {*} [defaultValue] The value returned for `undefined` resolved values.
     * @returns {*} Returns the resolved value.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
     *
     * _.result(object, 'a[0].b.c1');
     * // => 3
     *
     * _.result(object, 'a[0].b.c2');
     * // => 4
     *
     * _.result(object, 'a[0].b.c3', 'default');
     * // => 'default'
     *
     * _.result(object, 'a[0].b.c3', _.constant('default'));
     * // => 'default'
     */
    function result(object, path, defaultValue) {
      path = castPath(path, object);

      var index = -1,
          length = path.length;

      // Ensure the loop is entered when path is empty.
      if (!length) {
        length = 1;
        object = undefined;
      }
      while (++index < length) {
        var value = object == null ? undefined : object[toKey(path[index])];
        if (value === undefined) {
          index = length;
          value = defaultValue;
        }
        object = isFunction(value) ? value.call(object) : value;
      }
      return object;
    }

    /**
     * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
     * it's created. Arrays are created for missing index properties while objects
     * are created for all other missing properties. Use `_.setWith` to customize
     * `path` creation.
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 3.7.0
     * @category Object
     * @param {Object} object The object to modify.
     * @param {Array|string} path The path of the property to set.
     * @param {*} value The value to set.
     * @returns {Object} Returns `object`.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
     *
     * _.set(object, 'a[0].b.c', 4);
     * console.log(object.a[0].b.c);
     * // => 4
     *
     * _.set(object, ['x', '0', 'y', 'z'], 5);
     * console.log(object.x[0].y.z);
     * // => 5
     */
    function set(object, path, value) {
      return object == null ? object : baseSet(object, path, value);
    }

    /**
     * This method is like `_.set` except that it accepts `customizer` which is
     * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
     * path creation is handled by the method instead. The `customizer` is invoked
     * with three arguments: (nsValue, key, nsObject).
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The object to modify.
     * @param {Array|string} path The path of the property to set.
     * @param {*} value The value to set.
     * @param {Function} [customizer] The function to customize assigned values.
     * @returns {Object} Returns `object`.
     * @example
     *
     * var object = {};
     *
     * _.setWith(object, '[0][1]', 'a', Object);
     * // => { '0': { '1': 'a' } }
     */
    function setWith(object, path, value, customizer) {
      customizer = typeof customizer == 'function' ? customizer : undefined;
      return object == null ? object : baseSet(object, path, value, customizer);
    }

    /**
     * Creates an array of own enumerable string keyed-value pairs for `object`
     * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
     * entries are returned.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @alias entries
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the key-value pairs.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.toPairs(new Foo);
     * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
     */
    var toPairs = createToPairs(keys);

    /**
     * Creates an array of own and inherited enumerable string keyed-value pairs
     * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
     * or set, its entries are returned.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @alias entriesIn
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the key-value pairs.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.toPairsIn(new Foo);
     * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
     */
    var toPairsIn = createToPairs(keysIn);

    /**
     * An alternative to `_.reduce`; this method transforms `object` to a new
     * `accumulator` object which is the result of running each of its own
     * enumerable string keyed properties thru `iteratee`, with each invocation
     * potentially mutating the `accumulator` object. If `accumulator` is not
     * provided, a new object with the same `[[Prototype]]` will be used. The
     * iteratee is invoked with four arguments: (accumulator, value, key, object).
     * Iteratee functions may exit iteration early by explicitly returning `false`.
     *
     * @static
     * @memberOf _
     * @since 1.3.0
     * @category Object
     * @param {Object} object The object to iterate over.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @param {*} [accumulator] The custom accumulator value.
     * @returns {*} Returns the accumulated value.
     * @example
     *
     * _.transform([2, 3, 4], function(result, n) {
     *   result.push(n *= n);
     *   return n % 2 == 0;
     * }, []);
     * // => [4, 9]
     *
     * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
     *   (result[value] || (result[value] = [])).push(key);
     * }, {});
     * // => { '1': ['a', 'c'], '2': ['b'] }
     */
    function transform(object, iteratee, accumulator) {
      var isArr = isArray(object),
          isArrLike = isArr || isBuffer(object) || isTypedArray(object);

      iteratee = getIteratee(iteratee, 4);
      if (accumulator == null) {
        var Ctor = object && object.constructor;
        if (isArrLike) {
          accumulator = isArr ? new Ctor : [];
        }
        else if (isObject(object)) {
          accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
        }
        else {
          accumulator = {};
        }
      }
      (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
        return iteratee(accumulator, value, index, object);
      });
      return accumulator;
    }

    /**
     * Removes the property at `path` of `object`.
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Object
     * @param {Object} object The object to modify.
     * @param {Array|string} path The path of the property to unset.
     * @returns {boolean} Returns `true` if the property is deleted, else `false`.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c': 7 } }] };
     * _.unset(object, 'a[0].b.c');
     * // => true
     *
     * console.log(object);
     * // => { 'a': [{ 'b': {} }] };
     *
     * _.unset(object, ['a', '0', 'b', 'c']);
     * // => true
     *
     * console.log(object);
     * // => { 'a': [{ 'b': {} }] };
     */
    function unset(object, path) {
      return object == null ? true : baseUnset(object, path);
    }

    /**
     * This method is like `_.set` except that accepts `updater` to produce the
     * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
     * is invoked with one argument: (value).
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.6.0
     * @category Object
     * @param {Object} object The object to modify.
     * @param {Array|string} path The path of the property to set.
     * @param {Function} updater The function to produce the updated value.
     * @returns {Object} Returns `object`.
     * @example
     *
     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
     *
     * _.update(object, 'a[0].b.c', function(n) { return n * n; });
     * console.log(object.a[0].b.c);
     * // => 9
     *
     * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
     * console.log(object.x[0].y.z);
     * // => 0
     */
    function update(object, path, updater) {
      return object == null ? object : baseUpdate(object, path, castFunction(updater));
    }

    /**
     * This method is like `_.update` except that it accepts `customizer` which is
     * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
     * path creation is handled by the method instead. The `customizer` is invoked
     * with three arguments: (nsValue, key, nsObject).
     *
     * **Note:** This method mutates `object`.
     *
     * @static
     * @memberOf _
     * @since 4.6.0
     * @category Object
     * @param {Object} object The object to modify.
     * @param {Array|string} path The path of the property to set.
     * @param {Function} updater The function to produce the updated value.
     * @param {Function} [customizer] The function to customize assigned values.
     * @returns {Object} Returns `object`.
     * @example
     *
     * var object = {};
     *
     * _.updateWith(object, '[0][1]', _.constant('a'), Object);
     * // => { '0': { '1': 'a' } }
     */
    function updateWith(object, path, updater, customizer) {
      customizer = typeof customizer == 'function' ? customizer : undefined;
      return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
    }

    /**
     * Creates an array of the own enumerable string keyed property values of `object`.
     *
     * **Note:** Non-object values are coerced to objects.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property values.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.values(new Foo);
     * // => [1, 2] (iteration order is not guaranteed)
     *
     * _.values('hi');
     * // => ['h', 'i']
     */
    function values(object) {
      return object == null ? [] : baseValues(object, keys(object));
    }

    /**
     * Creates an array of the own and inherited enumerable string keyed property
     * values of `object`.
     *
     * **Note:** Non-object values are coerced to objects.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Object
     * @param {Object} object The object to query.
     * @returns {Array} Returns the array of property values.
     * @example
     *
     * function Foo() {
     *   this.a = 1;
     *   this.b = 2;
     * }
     *
     * Foo.prototype.c = 3;
     *
     * _.valuesIn(new Foo);
     * // => [1, 2, 3] (iteration order is not guaranteed)
     */
    function valuesIn(object) {
      return object == null ? [] : baseValues(object, keysIn(object));
    }

    /*------------------------------------------------------------------------*/

    /**
     * Clamps `number` within the inclusive `lower` and `upper` bounds.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Number
     * @param {number} number The number to clamp.
     * @param {number} [lower] The lower bound.
     * @param {number} upper The upper bound.
     * @returns {number} Returns the clamped number.
     * @example
     *
     * _.clamp(-10, -5, 5);
     * // => -5
     *
     * _.clamp(10, -5, 5);
     * // => 5
     */
    function clamp(number, lower, upper) {
      if (upper === undefined) {
        upper = lower;
        lower = undefined;
      }
      if (upper !== undefined) {
        upper = toNumber(upper);
        upper = upper === upper ? upper : 0;
      }
      if (lower !== undefined) {
        lower = toNumber(lower);
        lower = lower === lower ? lower : 0;
      }
      return baseClamp(toNumber(number), lower, upper);
    }

    /**
     * Checks if `n` is between `start` and up to, but not including, `end`. If
     * `end` is not specified, it's set to `start` with `start` then set to `0`.
     * If `start` is greater than `end` the params are swapped to support
     * negative ranges.
     *
     * @static
     * @memberOf _
     * @since 3.3.0
     * @category Number
     * @param {number} number The number to check.
     * @param {number} [start=0] The start of the range.
     * @param {number} end The end of the range.
     * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
     * @see _.range, _.rangeRight
     * @example
     *
     * _.inRange(3, 2, 4);
     * // => true
     *
     * _.inRange(4, 8);
     * // => true
     *
     * _.inRange(4, 2);
     * // => false
     *
     * _.inRange(2, 2);
     * // => false
     *
     * _.inRange(1.2, 2);
     * // => true
     *
     * _.inRange(5.2, 4);
     * // => false
     *
     * _.inRange(-3, -2, -6);
     * // => true
     */
    function inRange(number, start, end) {
      start = toFinite(start);
      if (end === undefined) {
        end = start;
        start = 0;
      } else {
        end = toFinite(end);
      }
      number = toNumber(number);
      return baseInRange(number, start, end);
    }

    /**
     * Produces a random number between the inclusive `lower` and `upper` bounds.
     * If only one argument is provided a number between `0` and the given number
     * is returned. If `floating` is `true`, or either `lower` or `upper` are
     * floats, a floating-point number is returned instead of an integer.
     *
     * **Note:** JavaScript follows the IEEE-754 standard for resolving
     * floating-point values which can produce unexpected results.
     *
     * @static
     * @memberOf _
     * @since 0.7.0
     * @category Number
     * @param {number} [lower=0] The lower bound.
     * @param {number} [upper=1] The upper bound.
     * @param {boolean} [floating] Specify returning a floating-point number.
     * @returns {number} Returns the random number.
     * @example
     *
     * _.random(0, 5);
     * // => an integer between 0 and 5
     *
     * _.random(5);
     * // => also an integer between 0 and 5
     *
     * _.random(5, true);
     * // => a floating-point number between 0 and 5
     *
     * _.random(1.2, 5.2);
     * // => a floating-point number between 1.2 and 5.2
     */
    function random(lower, upper, floating) {
      if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
        upper = floating = undefined;
      }
      if (floating === undefined) {
        if (typeof upper == 'boolean') {
          floating = upper;
          upper = undefined;
        }
        else if (typeof lower == 'boolean') {
          floating = lower;
          lower = undefined;
        }
      }
      if (lower === undefined && upper === undefined) {
        lower = 0;
        upper = 1;
      }
      else {
        lower = toFinite(lower);
        if (upper === undefined) {
          upper = lower;
          lower = 0;
        } else {
          upper = toFinite(upper);
        }
      }
      if (lower > upper) {
        var temp = lower;
        lower = upper;
        upper = temp;
      }
      if (floating || lower % 1 || upper % 1) {
        var rand = nativeRandom();
        return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
      }
      return baseRandom(lower, upper);
    }

    /*------------------------------------------------------------------------*/

    /**
     * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the camel cased string.
     * @example
     *
     * _.camelCase('Foo Bar');
     * // => 'fooBar'
     *
     * _.camelCase('--foo-bar--');
     * // => 'fooBar'
     *
     * _.camelCase('__FOO_BAR__');
     * // => 'fooBar'
     */
    var camelCase = createCompounder(function(result, word, index) {
      word = word.toLowerCase();
      return result + (index ? capitalize(word) : word);
    });

    /**
     * Converts the first character of `string` to upper case and the remaining
     * to lower case.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to capitalize.
     * @returns {string} Returns the capitalized string.
     * @example
     *
     * _.capitalize('FRED');
     * // => 'Fred'
     */
    function capitalize(string) {
      return upperFirst(toString(string).toLowerCase());
    }

    /**
     * Deburrs `string` by converting
     * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
     * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
     * letters to basic Latin letters and removing
     * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to deburr.
     * @returns {string} Returns the deburred string.
     * @example
     *
     * _.deburr('déjà vu');
     * // => 'deja vu'
     */
    function deburr(string) {
      string = toString(string);
      return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
    }

    /**
     * Checks if `string` ends with the given target string.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to inspect.
     * @param {string} [target] The string to search for.
     * @param {number} [position=string.length] The position to search up to.
     * @returns {boolean} Returns `true` if `string` ends with `target`,
     *  else `false`.
     * @example
     *
     * _.endsWith('abc', 'c');
     * // => true
     *
     * _.endsWith('abc', 'b');
     * // => false
     *
     * _.endsWith('abc', 'b', 2);
     * // => true
     */
    function endsWith(string, target, position) {
      string = toString(string);
      target = baseToString(target);

      var length = string.length;
      position = position === undefined
        ? length
        : baseClamp(toInteger(position), 0, length);

      var end = position;
      position -= target.length;
      return position >= 0 && string.slice(position, end) == target;
    }

    /**
     * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
     * corresponding HTML entities.
     *
     * **Note:** No other characters are escaped. To escape additional
     * characters use a third-party library like [_he_](https://mths.be/he).
     *
     * Though the ">" character is escaped for symmetry, characters like
     * ">" and "/" don't need escaping in HTML and have no special meaning
     * unless they're part of a tag or unquoted attribute value. See
     * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
     * (under "semi-related fun fact") for more details.
     *
     * When working with HTML you should always
     * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
     * XSS vectors.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category String
     * @param {string} [string=''] The string to escape.
     * @returns {string} Returns the escaped string.
     * @example
     *
     * _.escape('fred, barney, & pebbles');
     * // => 'fred, barney, &amp; pebbles'
     */
    function escape(string) {
      string = toString(string);
      return (string && reHasUnescapedHtml.test(string))
        ? string.replace(reUnescapedHtml, escapeHtmlChar)
        : string;
    }

    /**
     * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
     * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to escape.
     * @returns {string} Returns the escaped string.
     * @example
     *
     * _.escapeRegExp('[lodash](https://lodash.com/)');
     * // => '\[lodash\]\(https://lodash\.com/\)'
     */
    function escapeRegExp(string) {
      string = toString(string);
      return (string && reHasRegExpChar.test(string))
        ? string.replace(reRegExpChar, '\\$&')
        : string;
    }

    /**
     * Converts `string` to
     * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the kebab cased string.
     * @example
     *
     * _.kebabCase('Foo Bar');
     * // => 'foo-bar'
     *
     * _.kebabCase('fooBar');
     * // => 'foo-bar'
     *
     * _.kebabCase('__FOO_BAR__');
     * // => 'foo-bar'
     */
    var kebabCase = createCompounder(function(result, word, index) {
      return result + (index ? '-' : '') + word.toLowerCase();
    });

    /**
     * Converts `string`, as space separated words, to lower case.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the lower cased string.
     * @example
     *
     * _.lowerCase('--Foo-Bar--');
     * // => 'foo bar'
     *
     * _.lowerCase('fooBar');
     * // => 'foo bar'
     *
     * _.lowerCase('__FOO_BAR__');
     * // => 'foo bar'
     */
    var lowerCase = createCompounder(function(result, word, index) {
      return result + (index ? ' ' : '') + word.toLowerCase();
    });

    /**
     * Converts the first character of `string` to lower case.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the converted string.
     * @example
     *
     * _.lowerFirst('Fred');
     * // => 'fred'
     *
     * _.lowerFirst('FRED');
     * // => 'fRED'
     */
    var lowerFirst = createCaseFirst('toLowerCase');

    /**
     * Pads `string` on the left and right sides if it's shorter than `length`.
     * Padding characters are truncated if they can't be evenly divided by `length`.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to pad.
     * @param {number} [length=0] The padding length.
     * @param {string} [chars=' '] The string used as padding.
     * @returns {string} Returns the padded string.
     * @example
     *
     * _.pad('abc', 8);
     * // => '  abc   '
     *
     * _.pad('abc', 8, '_-');
     * // => '_-abc_-_'
     *
     * _.pad('abc', 3);
     * // => 'abc'
     */
    function pad(string, length, chars) {
      string = toString(string);
      length = toInteger(length);

      var strLength = length ? stringSize(string) : 0;
      if (!length || strLength >= length) {
        return string;
      }
      var mid = (length - strLength) / 2;
      return (
        createPadding(nativeFloor(mid), chars) +
        string +
        createPadding(nativeCeil(mid), chars)
      );
    }

    /**
     * Pads `string` on the right side if it's shorter than `length`. Padding
     * characters are truncated if they exceed `length`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to pad.
     * @param {number} [length=0] The padding length.
     * @param {string} [chars=' '] The string used as padding.
     * @returns {string} Returns the padded string.
     * @example
     *
     * _.padEnd('abc', 6);
     * // => 'abc   '
     *
     * _.padEnd('abc', 6, '_-');
     * // => 'abc_-_'
     *
     * _.padEnd('abc', 3);
     * // => 'abc'
     */
    function padEnd(string, length, chars) {
      string = toString(string);
      length = toInteger(length);

      var strLength = length ? stringSize(string) : 0;
      return (length && strLength < length)
        ? (string + createPadding(length - strLength, chars))
        : string;
    }

    /**
     * Pads `string` on the left side if it's shorter than `length`. Padding
     * characters are truncated if they exceed `length`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to pad.
     * @param {number} [length=0] The padding length.
     * @param {string} [chars=' '] The string used as padding.
     * @returns {string} Returns the padded string.
     * @example
     *
     * _.padStart('abc', 6);
     * // => '   abc'
     *
     * _.padStart('abc', 6, '_-');
     * // => '_-_abc'
     *
     * _.padStart('abc', 3);
     * // => 'abc'
     */
    function padStart(string, length, chars) {
      string = toString(string);
      length = toInteger(length);

      var strLength = length ? stringSize(string) : 0;
      return (length && strLength < length)
        ? (createPadding(length - strLength, chars) + string)
        : string;
    }

    /**
     * Converts `string` to an integer of the specified radix. If `radix` is
     * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
     * hexadecimal, in which case a `radix` of `16` is used.
     *
     * **Note:** This method aligns with the
     * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
     *
     * @static
     * @memberOf _
     * @since 1.1.0
     * @category String
     * @param {string} string The string to convert.
     * @param {number} [radix=10] The radix to interpret `value` by.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {number} Returns the converted integer.
     * @example
     *
     * _.parseInt('08');
     * // => 8
     *
     * _.map(['6', '08', '10'], _.parseInt);
     * // => [6, 8, 10]
     */
    function parseInt(string, radix, guard) {
      if (guard || radix == null) {
        radix = 0;
      } else if (radix) {
        radix = +radix;
      }
      return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
    }

    /**
     * Repeats the given string `n` times.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to repeat.
     * @param {number} [n=1] The number of times to repeat the string.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {string} Returns the repeated string.
     * @example
     *
     * _.repeat('*', 3);
     * // => '***'
     *
     * _.repeat('abc', 2);
     * // => 'abcabc'
     *
     * _.repeat('abc', 0);
     * // => ''
     */
    function repeat(string, n, guard) {
      if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
        n = 1;
      } else {
        n = toInteger(n);
      }
      return baseRepeat(toString(string), n);
    }

    /**
     * Replaces matches for `pattern` in `string` with `replacement`.
     *
     * **Note:** This method is based on
     * [`String#replace`](https://mdn.io/String/replace).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to modify.
     * @param {RegExp|string} pattern The pattern to replace.
     * @param {Function|string} replacement The match replacement.
     * @returns {string} Returns the modified string.
     * @example
     *
     * _.replace('Hi Fred', 'Fred', 'Barney');
     * // => 'Hi Barney'
     */
    function replace() {
      var args = arguments,
          string = toString(args[0]);

      return args.length < 3 ? string : string.replace(args[1], args[2]);
    }

    /**
     * Converts `string` to
     * [snake case](https://en.wikipedia.org/wiki/Snake_case).
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the snake cased string.
     * @example
     *
     * _.snakeCase('Foo Bar');
     * // => 'foo_bar'
     *
     * _.snakeCase('fooBar');
     * // => 'foo_bar'
     *
     * _.snakeCase('--FOO-BAR--');
     * // => 'foo_bar'
     */
    var snakeCase = createCompounder(function(result, word, index) {
      return result + (index ? '_' : '') + word.toLowerCase();
    });

    /**
     * Splits `string` by `separator`.
     *
     * **Note:** This method is based on
     * [`String#split`](https://mdn.io/String/split).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to split.
     * @param {RegExp|string} separator The separator pattern to split by.
     * @param {number} [limit] The length to truncate results to.
     * @returns {Array} Returns the string segments.
     * @example
     *
     * _.split('a-b-c', '-', 2);
     * // => ['a', 'b']
     */
    function split(string, separator, limit) {
      if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
        separator = limit = undefined;
      }
      limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
      if (!limit) {
        return [];
      }
      string = toString(string);
      if (string && (
            typeof separator == 'string' ||
            (separator != null && !isRegExp(separator))
          )) {
        separator = baseToString(separator);
        if (!separator && hasUnicode(string)) {
          return castSlice(stringToArray(string), 0, limit);
        }
      }
      return string.split(separator, limit);
    }

    /**
     * Converts `string` to
     * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
     *
     * @static
     * @memberOf _
     * @since 3.1.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the start cased string.
     * @example
     *
     * _.startCase('--foo-bar--');
     * // => 'Foo Bar'
     *
     * _.startCase('fooBar');
     * // => 'Foo Bar'
     *
     * _.startCase('__FOO_BAR__');
     * // => 'FOO BAR'
     */
    var startCase = createCompounder(function(result, word, index) {
      return result + (index ? ' ' : '') + upperFirst(word);
    });

    /**
     * Checks if `string` starts with the given target string.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to inspect.
     * @param {string} [target] The string to search for.
     * @param {number} [position=0] The position to search from.
     * @returns {boolean} Returns `true` if `string` starts with `target`,
     *  else `false`.
     * @example
     *
     * _.startsWith('abc', 'a');
     * // => true
     *
     * _.startsWith('abc', 'b');
     * // => false
     *
     * _.startsWith('abc', 'b', 1);
     * // => true
     */
    function startsWith(string, target, position) {
      string = toString(string);
      position = position == null
        ? 0
        : baseClamp(toInteger(position), 0, string.length);

      target = baseToString(target);
      return string.slice(position, position + target.length) == target;
    }

    /**
     * Creates a compiled template function that can interpolate data properties
     * in "interpolate" delimiters, HTML-escape interpolated data properties in
     * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
     * properties may be accessed as free variables in the template. If a setting
     * object is given, it takes precedence over `_.templateSettings` values.
     *
     * **Note:** In the development build `_.template` utilizes
     * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
     * for easier debugging.
     *
     * For more information on precompiling templates see
     * [lodash's custom builds documentation](https://lodash.com/custom-builds).
     *
     * For more information on Chrome extension sandboxes see
     * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category String
     * @param {string} [string=''] The template string.
     * @param {Object} [options={}] The options object.
     * @param {RegExp} [options.escape=_.templateSettings.escape]
     *  The HTML "escape" delimiter.
     * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
     *  The "evaluate" delimiter.
     * @param {Object} [options.imports=_.templateSettings.imports]
     *  An object to import into the template as free variables.
     * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
     *  The "interpolate" delimiter.
     * @param {string} [options.sourceURL='lodash.templateSources[n]']
     *  The sourceURL of the compiled template.
     * @param {string} [options.variable='obj']
     *  The data object variable name.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Function} Returns the compiled template function.
     * @example
     *
     * // Use the "interpolate" delimiter to create a compiled template.
     * var compiled = _.template('hello <%= user %>!');
     * compiled({ 'user': 'fred' });
     * // => 'hello fred!'
     *
     * // Use the HTML "escape" delimiter to escape data property values.
     * var compiled = _.template('<b><%- value %></b>');
     * compiled({ 'value': '<script>' });
     * // => '<b>&lt;script&gt;</b>'
     *
     * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
     * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
     * compiled({ 'users': ['fred', 'barney'] });
     * // => '<li>fred</li><li>barney</li>'
     *
     * // Use the internal `print` function in "evaluate" delimiters.
     * var compiled = _.template('<% print("hello " + user); %>!');
     * compiled({ 'user': 'barney' });
     * // => 'hello barney!'
     *
     * // Use the ES template literal delimiter as an "interpolate" delimiter.
     * // Disable support by replacing the "interpolate" delimiter.
     * var compiled = _.template('hello ${ user }!');
     * compiled({ 'user': 'pebbles' });
     * // => 'hello pebbles!'
     *
     * // Use backslashes to treat delimiters as plain text.
     * var compiled = _.template('<%= "\\<%- value %\\>" %>');
     * compiled({ 'value': 'ignored' });
     * // => '<%- value %>'
     *
     * // Use the `imports` option to import `jQuery` as `jq`.
     * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
     * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
     * compiled({ 'users': ['fred', 'barney'] });
     * // => '<li>fred</li><li>barney</li>'
     *
     * // Use the `sourceURL` option to specify a custom sourceURL for the template.
     * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
     * compiled(data);
     * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
     *
     * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
     * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
     * compiled.source;
     * // => function(data) {
     * //   var __t, __p = '';
     * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
     * //   return __p;
     * // }
     *
     * // Use custom template delimiters.
     * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
     * var compiled = _.template('hello {{ user }}!');
     * compiled({ 'user': 'mustache' });
     * // => 'hello mustache!'
     *
     * // Use the `source` property to inline compiled templates for meaningful
     * // line numbers in error messages and stack traces.
     * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
     *   var JST = {\
     *     "main": ' + _.template(mainText).source + '\
     *   };\
     * ');
     */
    function template(string, options, guard) {
      // Based on John Resig's `tmpl` implementation
      // (http://ejohn.org/blog/javascript-micro-templating/)
      // and Laura Doktorova's doT.js (https://github.com/olado/doT).
      var settings = lodash.templateSettings;

      if (guard && isIterateeCall(string, options, guard)) {
        options = undefined;
      }
      string = toString(string);
      options = assignInWith({}, options, settings, customDefaultsAssignIn);

      var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
          importsKeys = keys(imports),
          importsValues = baseValues(imports, importsKeys);

      var isEscaping,
          isEvaluating,
          index = 0,
          interpolate = options.interpolate || reNoMatch,
          source = "__p += '";

      // Compile the regexp to match each delimiter.
      var reDelimiters = RegExp(
        (options.escape || reNoMatch).source + '|' +
        interpolate.source + '|' +
        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
        (options.evaluate || reNoMatch).source + '|$'
      , 'g');

      // Use a sourceURL for easier debugging.
      var sourceURL = '//# sourceURL=' +
        ('sourceURL' in options
          ? options.sourceURL
          : ('lodash.templateSources[' + (++templateCounter) + ']')
        ) + '\n';

      string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
        interpolateValue || (interpolateValue = esTemplateValue);

        // Escape characters that can't be included in string literals.
        source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);

        // Replace delimiters with snippets.
        if (escapeValue) {
          isEscaping = true;
          source += "' +\n__e(" + escapeValue + ") +\n'";
        }
        if (evaluateValue) {
          isEvaluating = true;
          source += "';\n" + evaluateValue + ";\n__p += '";
        }
        if (interpolateValue) {
          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
        }
        index = offset + match.length;

        // The JS engine embedded in Adobe products needs `match` returned in
        // order to produce the correct `offset` value.
        return match;
      });

      source += "';\n";

      // If `variable` is not specified wrap a with-statement around the generated
      // code to add the data object to the top of the scope chain.
      var variable = options.variable;
      if (!variable) {
        source = 'with (obj) {\n' + source + '\n}\n';
      }
      // Cleanup code by stripping empty strings.
      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
        .replace(reEmptyStringMiddle, '$1')
        .replace(reEmptyStringTrailing, '$1;');

      // Frame code as the function body.
      source = 'function(' + (variable || 'obj') + ') {\n' +
        (variable
          ? ''
          : 'obj || (obj = {});\n'
        ) +
        "var __t, __p = ''" +
        (isEscaping
           ? ', __e = _.escape'
           : ''
        ) +
        (isEvaluating
          ? ', __j = Array.prototype.join;\n' +
            "function print() { __p += __j.call(arguments, '') }\n"
          : ';\n'
        ) +
        source +
        'return __p\n}';

      var result = attempt(function() {
        return Function(importsKeys, sourceURL + 'return ' + source)
          .apply(undefined, importsValues);
      });

      // Provide the compiled function's source by its `toString` method or
      // the `source` property as a convenience for inlining compiled templates.
      result.source = source;
      if (isError(result)) {
        throw result;
      }
      return result;
    }

    /**
     * Converts `string`, as a whole, to lower case just like
     * [String#toLowerCase](https://mdn.io/toLowerCase).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the lower cased string.
     * @example
     *
     * _.toLower('--Foo-Bar--');
     * // => '--foo-bar--'
     *
     * _.toLower('fooBar');
     * // => 'foobar'
     *
     * _.toLower('__FOO_BAR__');
     * // => '__foo_bar__'
     */
    function toLower(value) {
      return toString(value).toLowerCase();
    }

    /**
     * Converts `string`, as a whole, to upper case just like
     * [String#toUpperCase](https://mdn.io/toUpperCase).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the upper cased string.
     * @example
     *
     * _.toUpper('--foo-bar--');
     * // => '--FOO-BAR--'
     *
     * _.toUpper('fooBar');
     * // => 'FOOBAR'
     *
     * _.toUpper('__foo_bar__');
     * // => '__FOO_BAR__'
     */
    function toUpper(value) {
      return toString(value).toUpperCase();
    }

    /**
     * Removes leading and trailing whitespace or specified characters from `string`.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to trim.
     * @param {string} [chars=whitespace] The characters to trim.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {string} Returns the trimmed string.
     * @example
     *
     * _.trim('  abc  ');
     * // => 'abc'
     *
     * _.trim('-_-abc-_-', '_-');
     * // => 'abc'
     *
     * _.map(['  foo  ', '  bar  '], _.trim);
     * // => ['foo', 'bar']
     */
    function trim(string, chars, guard) {
      string = toString(string);
      if (string && (guard || chars === undefined)) {
        return string.replace(reTrim, '');
      }
      if (!string || !(chars = baseToString(chars))) {
        return string;
      }
      var strSymbols = stringToArray(string),
          chrSymbols = stringToArray(chars),
          start = charsStartIndex(strSymbols, chrSymbols),
          end = charsEndIndex(strSymbols, chrSymbols) + 1;

      return castSlice(strSymbols, start, end).join('');
    }

    /**
     * Removes trailing whitespace or specified characters from `string`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to trim.
     * @param {string} [chars=whitespace] The characters to trim.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {string} Returns the trimmed string.
     * @example
     *
     * _.trimEnd('  abc  ');
     * // => '  abc'
     *
     * _.trimEnd('-_-abc-_-', '_-');
     * // => '-_-abc'
     */
    function trimEnd(string, chars, guard) {
      string = toString(string);
      if (string && (guard || chars === undefined)) {
        return string.replace(reTrimEnd, '');
      }
      if (!string || !(chars = baseToString(chars))) {
        return string;
      }
      var strSymbols = stringToArray(string),
          end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;

      return castSlice(strSymbols, 0, end).join('');
    }

    /**
     * Removes leading whitespace or specified characters from `string`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to trim.
     * @param {string} [chars=whitespace] The characters to trim.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {string} Returns the trimmed string.
     * @example
     *
     * _.trimStart('  abc  ');
     * // => 'abc  '
     *
     * _.trimStart('-_-abc-_-', '_-');
     * // => 'abc-_-'
     */
    function trimStart(string, chars, guard) {
      string = toString(string);
      if (string && (guard || chars === undefined)) {
        return string.replace(reTrimStart, '');
      }
      if (!string || !(chars = baseToString(chars))) {
        return string;
      }
      var strSymbols = stringToArray(string),
          start = charsStartIndex(strSymbols, stringToArray(chars));

      return castSlice(strSymbols, start).join('');
    }

    /**
     * Truncates `string` if it's longer than the given maximum string length.
     * The last characters of the truncated string are replaced with the omission
     * string which defaults to "...".
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to truncate.
     * @param {Object} [options={}] The options object.
     * @param {number} [options.length=30] The maximum string length.
     * @param {string} [options.omission='...'] The string to indicate text is omitted.
     * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
     * @returns {string} Returns the truncated string.
     * @example
     *
     * _.truncate('hi-diddly-ho there, neighborino');
     * // => 'hi-diddly-ho there, neighbo...'
     *
     * _.truncate('hi-diddly-ho there, neighborino', {
     *   'length': 24,
     *   'separator': ' '
     * });
     * // => 'hi-diddly-ho there,...'
     *
     * _.truncate('hi-diddly-ho there, neighborino', {
     *   'length': 24,
     *   'separator': /,? +/
     * });
     * // => 'hi-diddly-ho there...'
     *
     * _.truncate('hi-diddly-ho there, neighborino', {
     *   'omission': ' [...]'
     * });
     * // => 'hi-diddly-ho there, neig [...]'
     */
    function truncate(string, options) {
      var length = DEFAULT_TRUNC_LENGTH,
          omission = DEFAULT_TRUNC_OMISSION;

      if (isObject(options)) {
        var separator = 'separator' in options ? options.separator : separator;
        length = 'length' in options ? toInteger(options.length) : length;
        omission = 'omission' in options ? baseToString(options.omission) : omission;
      }
      string = toString(string);

      var strLength = string.length;
      if (hasUnicode(string)) {
        var strSymbols = stringToArray(string);
        strLength = strSymbols.length;
      }
      if (length >= strLength) {
        return string;
      }
      var end = length - stringSize(omission);
      if (end < 1) {
        return omission;
      }
      var result = strSymbols
        ? castSlice(strSymbols, 0, end).join('')
        : string.slice(0, end);

      if (separator === undefined) {
        return result + omission;
      }
      if (strSymbols) {
        end += (result.length - end);
      }
      if (isRegExp(separator)) {
        if (string.slice(end).search(separator)) {
          var match,
              substring = result;

          if (!separator.global) {
            separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
          }
          separator.lastIndex = 0;
          while ((match = separator.exec(substring))) {
            var newEnd = match.index;
          }
          result = result.slice(0, newEnd === undefined ? end : newEnd);
        }
      } else if (string.indexOf(baseToString(separator), end) != end) {
        var index = result.lastIndexOf(separator);
        if (index > -1) {
          result = result.slice(0, index);
        }
      }
      return result + omission;
    }

    /**
     * The inverse of `_.escape`; this method converts the HTML entities
     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
     * their corresponding characters.
     *
     * **Note:** No other HTML entities are unescaped. To unescape additional
     * HTML entities use a third-party library like [_he_](https://mths.be/he).
     *
     * @static
     * @memberOf _
     * @since 0.6.0
     * @category String
     * @param {string} [string=''] The string to unescape.
     * @returns {string} Returns the unescaped string.
     * @example
     *
     * _.unescape('fred, barney, &amp; pebbles');
     * // => 'fred, barney, & pebbles'
     */
    function unescape(string) {
      string = toString(string);
      return (string && reHasEscapedHtml.test(string))
        ? string.replace(reEscapedHtml, unescapeHtmlChar)
        : string;
    }

    /**
     * Converts `string`, as space separated words, to upper case.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the upper cased string.
     * @example
     *
     * _.upperCase('--foo-bar');
     * // => 'FOO BAR'
     *
     * _.upperCase('fooBar');
     * // => 'FOO BAR'
     *
     * _.upperCase('__foo_bar__');
     * // => 'FOO BAR'
     */
    var upperCase = createCompounder(function(result, word, index) {
      return result + (index ? ' ' : '') + word.toUpperCase();
    });

    /**
     * Converts the first character of `string` to upper case.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category String
     * @param {string} [string=''] The string to convert.
     * @returns {string} Returns the converted string.
     * @example
     *
     * _.upperFirst('fred');
     * // => 'Fred'
     *
     * _.upperFirst('FRED');
     * // => 'FRED'
     */
    var upperFirst = createCaseFirst('toUpperCase');

    /**
     * Splits `string` into an array of its words.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category String
     * @param {string} [string=''] The string to inspect.
     * @param {RegExp|string} [pattern] The pattern to match words.
     * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
     * @returns {Array} Returns the words of `string`.
     * @example
     *
     * _.words('fred, barney, & pebbles');
     * // => ['fred', 'barney', 'pebbles']
     *
     * _.words('fred, barney, & pebbles', /[^, ]+/g);
     * // => ['fred', 'barney', '&', 'pebbles']
     */
    function words(string, pattern, guard) {
      string = toString(string);
      pattern = guard ? undefined : pattern;

      if (pattern === undefined) {
        return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
      }
      return string.match(pattern) || [];
    }

    /*------------------------------------------------------------------------*/

    /**
     * Attempts to invoke `func`, returning either the result or the caught error
     * object. Any additional arguments are provided to `func` when it's invoked.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Util
     * @param {Function} func The function to attempt.
     * @param {...*} [args] The arguments to invoke `func` with.
     * @returns {*} Returns the `func` result or error object.
     * @example
     *
     * // Avoid throwing errors for invalid selectors.
     * var elements = _.attempt(function(selector) {
     *   return document.querySelectorAll(selector);
     * }, '>_>');
     *
     * if (_.isError(elements)) {
     *   elements = [];
     * }
     */
    var attempt = baseRest(function(func, args) {
      try {
        return apply(func, undefined, args);
      } catch (e) {
        return isError(e) ? e : new Error(e);
      }
    });

    /**
     * Binds methods of an object to the object itself, overwriting the existing
     * method.
     *
     * **Note:** This method doesn't set the "length" property of bound functions.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Util
     * @param {Object} object The object to bind and assign the bound methods to.
     * @param {...(string|string[])} methodNames The object method names to bind.
     * @returns {Object} Returns `object`.
     * @example
     *
     * var view = {
     *   'label': 'docs',
     *   'click': function() {
     *     console.log('clicked ' + this.label);
     *   }
     * };
     *
     * _.bindAll(view, ['click']);
     * jQuery(element).on('click', view.click);
     * // => Logs 'clicked docs' when clicked.
     */
    var bindAll = flatRest(function(object, methodNames) {
      arrayEach(methodNames, function(key) {
        key = toKey(key);
        baseAssignValue(object, key, bind(object[key], object));
      });
      return object;
    });

    /**
     * Creates a function that iterates over `pairs` and invokes the corresponding
     * function of the first predicate to return truthy. The predicate-function
     * pairs are invoked with the `this` binding and arguments of the created
     * function.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {Array} pairs The predicate-function pairs.
     * @returns {Function} Returns the new composite function.
     * @example
     *
     * var func = _.cond([
     *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
     *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
     *   [_.stubTrue,                      _.constant('no match')]
     * ]);
     *
     * func({ 'a': 1, 'b': 2 });
     * // => 'matches A'
     *
     * func({ 'a': 0, 'b': 1 });
     * // => 'matches B'
     *
     * func({ 'a': '1', 'b': '2' });
     * // => 'no match'
     */
    function cond(pairs) {
      var length = pairs == null ? 0 : pairs.length,
          toIteratee = getIteratee();

      pairs = !length ? [] : arrayMap(pairs, function(pair) {
        if (typeof pair[1] != 'function') {
          throw new TypeError(FUNC_ERROR_TEXT);
        }
        return [toIteratee(pair[0]), pair[1]];
      });

      return baseRest(function(args) {
        var index = -1;
        while (++index < length) {
          var pair = pairs[index];
          if (apply(pair[0], this, args)) {
            return apply(pair[1], this, args);
          }
        }
      });
    }

    /**
     * Creates a function that invokes the predicate properties of `source` with
     * the corresponding property values of a given object, returning `true` if
     * all predicates return truthy, else `false`.
     *
     * **Note:** The created function is equivalent to `_.conformsTo` with
     * `source` partially applied.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {Object} source The object of property predicates to conform to.
     * @returns {Function} Returns the new spec function.
     * @example
     *
     * var objects = [
     *   { 'a': 2, 'b': 1 },
     *   { 'a': 1, 'b': 2 }
     * ];
     *
     * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
     * // => [{ 'a': 1, 'b': 2 }]
     */
    function conforms(source) {
      return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
    }

    /**
     * Creates a function that returns `value`.
     *
     * @static
     * @memberOf _
     * @since 2.4.0
     * @category Util
     * @param {*} value The value to return from the new function.
     * @returns {Function} Returns the new constant function.
     * @example
     *
     * var objects = _.times(2, _.constant({ 'a': 1 }));
     *
     * console.log(objects);
     * // => [{ 'a': 1 }, { 'a': 1 }]
     *
     * console.log(objects[0] === objects[1]);
     * // => true
     */
    function constant(value) {
      return function() {
        return value;
      };
    }

    /**
     * Checks `value` to determine whether a default value should be returned in
     * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
     * or `undefined`.
     *
     * @static
     * @memberOf _
     * @since 4.14.0
     * @category Util
     * @param {*} value The value to check.
     * @param {*} defaultValue The default value.
     * @returns {*} Returns the resolved value.
     * @example
     *
     * _.defaultTo(1, 10);
     * // => 1
     *
     * _.defaultTo(undefined, 10);
     * // => 10
     */
    function defaultTo(value, defaultValue) {
      return (value == null || value !== value) ? defaultValue : value;
    }

    /**
     * Creates a function that returns the result of invoking the given functions
     * with the `this` binding of the created function, where each successive
     * invocation is supplied the return value of the previous.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Util
     * @param {...(Function|Function[])} [funcs] The functions to invoke.
     * @returns {Function} Returns the new composite function.
     * @see _.flowRight
     * @example
     *
     * function square(n) {
     *   return n * n;
     * }
     *
     * var addSquare = _.flow([_.add, square]);
     * addSquare(1, 2);
     * // => 9
     */
    var flow = createFlow();

    /**
     * This method is like `_.flow` except that it creates a function that
     * invokes the given functions from right to left.
     *
     * @static
     * @since 3.0.0
     * @memberOf _
     * @category Util
     * @param {...(Function|Function[])} [funcs] The functions to invoke.
     * @returns {Function} Returns the new composite function.
     * @see _.flow
     * @example
     *
     * function square(n) {
     *   return n * n;
     * }
     *
     * var addSquare = _.flowRight([square, _.add]);
     * addSquare(1, 2);
     * // => 9
     */
    var flowRight = createFlow(true);

    /**
     * This method returns the first argument it receives.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Util
     * @param {*} value Any value.
     * @returns {*} Returns `value`.
     * @example
     *
     * var object = { 'a': 1 };
     *
     * console.log(_.identity(object) === object);
     * // => true
     */
    function identity(value) {
      return value;
    }

    /**
     * Creates a function that invokes `func` with the arguments of the created
     * function. If `func` is a property name, the created function returns the
     * property value for a given element. If `func` is an array or object, the
     * created function returns `true` for elements that contain the equivalent
     * source properties, otherwise it returns `false`.
     *
     * @static
     * @since 4.0.0
     * @memberOf _
     * @category Util
     * @param {*} [func=_.identity] The value to convert to a callback.
     * @returns {Function} Returns the callback.
     * @example
     *
     * var users = [
     *   { 'user': 'barney', 'age': 36, 'active': true },
     *   { 'user': 'fred',   'age': 40, 'active': false }
     * ];
     *
     * // The `_.matches` iteratee shorthand.
     * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
     * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
     *
     * // The `_.matchesProperty` iteratee shorthand.
     * _.filter(users, _.iteratee(['user', 'fred']));
     * // => [{ 'user': 'fred', 'age': 40 }]
     *
     * // The `_.property` iteratee shorthand.
     * _.map(users, _.iteratee('user'));
     * // => ['barney', 'fred']
     *
     * // Create custom iteratee shorthands.
     * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
     *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
     *     return func.test(string);
     *   };
     * });
     *
     * _.filter(['abc', 'def'], /ef/);
     * // => ['def']
     */
    function iteratee(func) {
      return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
    }

    /**
     * Creates a function that performs a partial deep comparison between a given
     * object and `source`, returning `true` if the given object has equivalent
     * property values, else `false`.
     *
     * **Note:** The created function is equivalent to `_.isMatch` with `source`
     * partially applied.
     *
     * Partial comparisons will match empty array and empty object `source`
     * values against any array or object value, respectively. See `_.isEqual`
     * for a list of supported value comparisons.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Util
     * @param {Object} source The object of property values to match.
     * @returns {Function} Returns the new spec function.
     * @example
     *
     * var objects = [
     *   { 'a': 1, 'b': 2, 'c': 3 },
     *   { 'a': 4, 'b': 5, 'c': 6 }
     * ];
     *
     * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
     * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
     */
    function matches(source) {
      return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
    }

    /**
     * Creates a function that performs a partial deep comparison between the
     * value at `path` of a given object to `srcValue`, returning `true` if the
     * object value is equivalent, else `false`.
     *
     * **Note:** Partial comparisons will match empty array and empty object
     * `srcValue` values against any array or object value, respectively. See
     * `_.isEqual` for a list of supported value comparisons.
     *
     * @static
     * @memberOf _
     * @since 3.2.0
     * @category Util
     * @param {Array|string} path The path of the property to get.
     * @param {*} srcValue The value to match.
     * @returns {Function} Returns the new spec function.
     * @example
     *
     * var objects = [
     *   { 'a': 1, 'b': 2, 'c': 3 },
     *   { 'a': 4, 'b': 5, 'c': 6 }
     * ];
     *
     * _.find(objects, _.matchesProperty('a', 4));
     * // => { 'a': 4, 'b': 5, 'c': 6 }
     */
    function matchesProperty(path, srcValue) {
      return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
    }

    /**
     * Creates a function that invokes the method at `path` of a given object.
     * Any additional arguments are provided to the invoked method.
     *
     * @static
     * @memberOf _
     * @since 3.7.0
     * @category Util
     * @param {Array|string} path The path of the method to invoke.
     * @param {...*} [args] The arguments to invoke the method with.
     * @returns {Function} Returns the new invoker function.
     * @example
     *
     * var objects = [
     *   { 'a': { 'b': _.constant(2) } },
     *   { 'a': { 'b': _.constant(1) } }
     * ];
     *
     * _.map(objects, _.method('a.b'));
     * // => [2, 1]
     *
     * _.map(objects, _.method(['a', 'b']));
     * // => [2, 1]
     */
    var method = baseRest(function(path, args) {
      return function(object) {
        return baseInvoke(object, path, args);
      };
    });

    /**
     * The opposite of `_.method`; this method creates a function that invokes
     * the method at a given path of `object`. Any additional arguments are
     * provided to the invoked method.
     *
     * @static
     * @memberOf _
     * @since 3.7.0
     * @category Util
     * @param {Object} object The object to query.
     * @param {...*} [args] The arguments to invoke the method with.
     * @returns {Function} Returns the new invoker function.
     * @example
     *
     * var array = _.times(3, _.constant),
     *     object = { 'a': array, 'b': array, 'c': array };
     *
     * _.map(['a[2]', 'c[0]'], _.methodOf(object));
     * // => [2, 0]
     *
     * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
     * // => [2, 0]
     */
    var methodOf = baseRest(function(object, args) {
      return function(path) {
        return baseInvoke(object, path, args);
      };
    });

    /**
     * Adds all own enumerable string keyed function properties of a source
     * object to the destination object. If `object` is a function, then methods
     * are added to its prototype as well.
     *
     * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
     * avoid conflicts caused by modifying the original.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Util
     * @param {Function|Object} [object=lodash] The destination object.
     * @param {Object} source The object of functions to add.
     * @param {Object} [options={}] The options object.
     * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
     * @returns {Function|Object} Returns `object`.
     * @example
     *
     * function vowels(string) {
     *   return _.filter(string, function(v) {
     *     return /[aeiou]/i.test(v);
     *   });
     * }
     *
     * _.mixin({ 'vowels': vowels });
     * _.vowels('fred');
     * // => ['e']
     *
     * _('fred').vowels().value();
     * // => ['e']
     *
     * _.mixin({ 'vowels': vowels }, { 'chain': false });
     * _('fred').vowels();
     * // => ['e']
     */
    function mixin(object, source, options) {
      var props = keys(source),
          methodNames = baseFunctions(source, props);

      if (options == null &&
          !(isObject(source) && (methodNames.length || !props.length))) {
        options = source;
        source = object;
        object = this;
        methodNames = baseFunctions(source, keys(source));
      }
      var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
          isFunc = isFunction(object);

      arrayEach(methodNames, function(methodName) {
        var func = source[methodName];
        object[methodName] = func;
        if (isFunc) {
          object.prototype[methodName] = function() {
            var chainAll = this.__chain__;
            if (chain || chainAll) {
              var result = object(this.__wrapped__),
                  actions = result.__actions__ = copyArray(this.__actions__);

              actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
              result.__chain__ = chainAll;
              return result;
            }
            return func.apply(object, arrayPush([this.value()], arguments));
          };
        }
      });

      return object;
    }

    /**
     * Reverts the `_` variable to its previous value and returns a reference to
     * the `lodash` function.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Util
     * @returns {Function} Returns the `lodash` function.
     * @example
     *
     * var lodash = _.noConflict();
     */
    function noConflict() {
      if (root._ === this) {
        root._ = oldDash;
      }
      return this;
    }

    /**
     * This method returns `undefined`.
     *
     * @static
     * @memberOf _
     * @since 2.3.0
     * @category Util
     * @example
     *
     * _.times(2, _.noop);
     * // => [undefined, undefined]
     */
    function noop() {
      // No operation performed.
    }

    /**
     * Creates a function that gets the argument at index `n`. If `n` is negative,
     * the nth argument from the end is returned.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {number} [n=0] The index of the argument to return.
     * @returns {Function} Returns the new pass-thru function.
     * @example
     *
     * var func = _.nthArg(1);
     * func('a', 'b', 'c', 'd');
     * // => 'b'
     *
     * var func = _.nthArg(-2);
     * func('a', 'b', 'c', 'd');
     * // => 'c'
     */
    function nthArg(n) {
      n = toInteger(n);
      return baseRest(function(args) {
        return baseNth(args, n);
      });
    }

    /**
     * Creates a function that invokes `iteratees` with the arguments it receives
     * and returns their results.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {...(Function|Function[])} [iteratees=[_.identity]]
     *  The iteratees to invoke.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var func = _.over([Math.max, Math.min]);
     *
     * func(1, 2, 3, 4);
     * // => [4, 1]
     */
    var over = createOver(arrayMap);

    /**
     * Creates a function that checks if **all** of the `predicates` return
     * truthy when invoked with the arguments it receives.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {...(Function|Function[])} [predicates=[_.identity]]
     *  The predicates to check.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var func = _.overEvery([Boolean, isFinite]);
     *
     * func('1');
     * // => true
     *
     * func(null);
     * // => false
     *
     * func(NaN);
     * // => false
     */
    var overEvery = createOver(arrayEvery);

    /**
     * Creates a function that checks if **any** of the `predicates` return
     * truthy when invoked with the arguments it receives.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {...(Function|Function[])} [predicates=[_.identity]]
     *  The predicates to check.
     * @returns {Function} Returns the new function.
     * @example
     *
     * var func = _.overSome([Boolean, isFinite]);
     *
     * func('1');
     * // => true
     *
     * func(null);
     * // => true
     *
     * func(NaN);
     * // => false
     */
    var overSome = createOver(arraySome);

    /**
     * Creates a function that returns the value at `path` of a given object.
     *
     * @static
     * @memberOf _
     * @since 2.4.0
     * @category Util
     * @param {Array|string} path The path of the property to get.
     * @returns {Function} Returns the new accessor function.
     * @example
     *
     * var objects = [
     *   { 'a': { 'b': 2 } },
     *   { 'a': { 'b': 1 } }
     * ];
     *
     * _.map(objects, _.property('a.b'));
     * // => [2, 1]
     *
     * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
     * // => [1, 2]
     */
    function property(path) {
      return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
    }

    /**
     * The opposite of `_.property`; this method creates a function that returns
     * the value at a given path of `object`.
     *
     * @static
     * @memberOf _
     * @since 3.0.0
     * @category Util
     * @param {Object} object The object to query.
     * @returns {Function} Returns the new accessor function.
     * @example
     *
     * var array = [0, 1, 2],
     *     object = { 'a': array, 'b': array, 'c': array };
     *
     * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
     * // => [2, 0]
     *
     * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
     * // => [2, 0]
     */
    function propertyOf(object) {
      return function(path) {
        return object == null ? undefined : baseGet(object, path);
      };
    }

    /**
     * Creates an array of numbers (positive and/or negative) progressing from
     * `start` up to, but not including, `end`. A step of `-1` is used if a negative
     * `start` is specified without an `end` or `step`. If `end` is not specified,
     * it's set to `start` with `start` then set to `0`.
     *
     * **Note:** JavaScript follows the IEEE-754 standard for resolving
     * floating-point values which can produce unexpected results.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Util
     * @param {number} [start=0] The start of the range.
     * @param {number} end The end of the range.
     * @param {number} [step=1] The value to increment or decrement by.
     * @returns {Array} Returns the range of numbers.
     * @see _.inRange, _.rangeRight
     * @example
     *
     * _.range(4);
     * // => [0, 1, 2, 3]
     *
     * _.range(-4);
     * // => [0, -1, -2, -3]
     *
     * _.range(1, 5);
     * // => [1, 2, 3, 4]
     *
     * _.range(0, 20, 5);
     * // => [0, 5, 10, 15]
     *
     * _.range(0, -4, -1);
     * // => [0, -1, -2, -3]
     *
     * _.range(1, 4, 0);
     * // => [1, 1, 1]
     *
     * _.range(0);
     * // => []
     */
    var range = createRange();

    /**
     * This method is like `_.range` except that it populates values in
     * descending order.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {number} [start=0] The start of the range.
     * @param {number} end The end of the range.
     * @param {number} [step=1] The value to increment or decrement by.
     * @returns {Array} Returns the range of numbers.
     * @see _.inRange, _.range
     * @example
     *
     * _.rangeRight(4);
     * // => [3, 2, 1, 0]
     *
     * _.rangeRight(-4);
     * // => [-3, -2, -1, 0]
     *
     * _.rangeRight(1, 5);
     * // => [4, 3, 2, 1]
     *
     * _.rangeRight(0, 20, 5);
     * // => [15, 10, 5, 0]
     *
     * _.rangeRight(0, -4, -1);
     * // => [-3, -2, -1, 0]
     *
     * _.rangeRight(1, 4, 0);
     * // => [1, 1, 1]
     *
     * _.rangeRight(0);
     * // => []
     */
    var rangeRight = createRange(true);

    /**
     * This method returns a new empty array.
     *
     * @static
     * @memberOf _
     * @since 4.13.0
     * @category Util
     * @returns {Array} Returns the new empty array.
     * @example
     *
     * var arrays = _.times(2, _.stubArray);
     *
     * console.log(arrays);
     * // => [[], []]
     *
     * console.log(arrays[0] === arrays[1]);
     * // => false
     */
    function stubArray() {
      return [];
    }

    /**
     * This method returns `false`.
     *
     * @static
     * @memberOf _
     * @since 4.13.0
     * @category Util
     * @returns {boolean} Returns `false`.
     * @example
     *
     * _.times(2, _.stubFalse);
     * // => [false, false]
     */
    function stubFalse() {
      return false;
    }

    /**
     * This method returns a new empty object.
     *
     * @static
     * @memberOf _
     * @since 4.13.0
     * @category Util
     * @returns {Object} Returns the new empty object.
     * @example
     *
     * var objects = _.times(2, _.stubObject);
     *
     * console.log(objects);
     * // => [{}, {}]
     *
     * console.log(objects[0] === objects[1]);
     * // => false
     */
    function stubObject() {
      return {};
    }

    /**
     * This method returns an empty string.
     *
     * @static
     * @memberOf _
     * @since 4.13.0
     * @category Util
     * @returns {string} Returns the empty string.
     * @example
     *
     * _.times(2, _.stubString);
     * // => ['', '']
     */
    function stubString() {
      return '';
    }

    /**
     * This method returns `true`.
     *
     * @static
     * @memberOf _
     * @since 4.13.0
     * @category Util
     * @returns {boolean} Returns `true`.
     * @example
     *
     * _.times(2, _.stubTrue);
     * // => [true, true]
     */
    function stubTrue() {
      return true;
    }

    /**
     * Invokes the iteratee `n` times, returning an array of the results of
     * each invocation. The iteratee is invoked with one argument; (index).
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Util
     * @param {number} n The number of times to invoke `iteratee`.
     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
     * @returns {Array} Returns the array of results.
     * @example
     *
     * _.times(3, String);
     * // => ['0', '1', '2']
     *
     *  _.times(4, _.constant(0));
     * // => [0, 0, 0, 0]
     */
    function times(n, iteratee) {
      n = toInteger(n);
      if (n < 1 || n > MAX_SAFE_INTEGER) {
        return [];
      }
      var index = MAX_ARRAY_LENGTH,
          length = nativeMin(n, MAX_ARRAY_LENGTH);

      iteratee = getIteratee(iteratee);
      n -= MAX_ARRAY_LENGTH;

      var result = baseTimes(length, iteratee);
      while (++index < n) {
        iteratee(index);
      }
      return result;
    }

    /**
     * Converts `value` to a property path array.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Util
     * @param {*} value The value to convert.
     * @returns {Array} Returns the new property path array.
     * @example
     *
     * _.toPath('a.b.c');
     * // => ['a', 'b', 'c']
     *
     * _.toPath('a[0].b.c');
     * // => ['a', '0', 'b', 'c']
     */
    function toPath(value) {
      if (isArray(value)) {
        return arrayMap(value, toKey);
      }
      return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
    }

    /**
     * Generates a unique ID. If `prefix` is given, the ID is appended to it.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Util
     * @param {string} [prefix=''] The value to prefix the ID with.
     * @returns {string} Returns the unique ID.
     * @example
     *
     * _.uniqueId('contact_');
     * // => 'contact_104'
     *
     * _.uniqueId();
     * // => '105'
     */
    function uniqueId(prefix) {
      var id = ++idCounter;
      return toString(prefix) + id;
    }

    /*------------------------------------------------------------------------*/

    /**
     * Adds two numbers.
     *
     * @static
     * @memberOf _
     * @since 3.4.0
     * @category Math
     * @param {number} augend The first number in an addition.
     * @param {number} addend The second number in an addition.
     * @returns {number} Returns the total.
     * @example
     *
     * _.add(6, 4);
     * // => 10
     */
    var add = createMathOperation(function(augend, addend) {
      return augend + addend;
    }, 0);

    /**
     * Computes `number` rounded up to `precision`.
     *
     * @static
     * @memberOf _
     * @since 3.10.0
     * @category Math
     * @param {number} number The number to round up.
     * @param {number} [precision=0] The precision to round up to.
     * @returns {number} Returns the rounded up number.
     * @example
     *
     * _.ceil(4.006);
     * // => 5
     *
     * _.ceil(6.004, 2);
     * // => 6.01
     *
     * _.ceil(6040, -2);
     * // => 6100
     */
    var ceil = createRound('ceil');

    /**
     * Divide two numbers.
     *
     * @static
     * @memberOf _
     * @since 4.7.0
     * @category Math
     * @param {number} dividend The first number in a division.
     * @param {number} divisor The second number in a division.
     * @returns {number} Returns the quotient.
     * @example
     *
     * _.divide(6, 4);
     * // => 1.5
     */
    var divide = createMathOperation(function(dividend, divisor) {
      return dividend / divisor;
    }, 1);

    /**
     * Computes `number` rounded down to `precision`.
     *
     * @static
     * @memberOf _
     * @since 3.10.0
     * @category Math
     * @param {number} number The number to round down.
     * @param {number} [precision=0] The precision to round down to.
     * @returns {number} Returns the rounded down number.
     * @example
     *
     * _.floor(4.006);
     * // => 4
     *
     * _.floor(0.046, 2);
     * // => 0.04
     *
     * _.floor(4060, -2);
     * // => 4000
     */
    var floor = createRound('floor');

    /**
     * Computes the maximum value of `array`. If `array` is empty or falsey,
     * `undefined` is returned.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Math
     * @param {Array} array The array to iterate over.
     * @returns {*} Returns the maximum value.
     * @example
     *
     * _.max([4, 2, 8, 6]);
     * // => 8
     *
     * _.max([]);
     * // => undefined
     */
    function max(array) {
      return (array && array.length)
        ? baseExtremum(array, identity, baseGt)
        : undefined;
    }

    /**
     * This method is like `_.max` except that it accepts `iteratee` which is
     * invoked for each element in `array` to generate the criterion by which
     * the value is ranked. The iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Math
     * @param {Array} array The array to iterate over.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {*} Returns the maximum value.
     * @example
     *
     * var objects = [{ 'n': 1 }, { 'n': 2 }];
     *
     * _.maxBy(objects, function(o) { return o.n; });
     * // => { 'n': 2 }
     *
     * // The `_.property` iteratee shorthand.
     * _.maxBy(objects, 'n');
     * // => { 'n': 2 }
     */
    function maxBy(array, iteratee) {
      return (array && array.length)
        ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
        : undefined;
    }

    /**
     * Computes the mean of the values in `array`.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Math
     * @param {Array} array The array to iterate over.
     * @returns {number} Returns the mean.
     * @example
     *
     * _.mean([4, 2, 8, 6]);
     * // => 5
     */
    function mean(array) {
      return baseMean(array, identity);
    }

    /**
     * This method is like `_.mean` except that it accepts `iteratee` which is
     * invoked for each element in `array` to generate the value to be averaged.
     * The iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.7.0
     * @category Math
     * @param {Array} array The array to iterate over.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {number} Returns the mean.
     * @example
     *
     * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
     *
     * _.meanBy(objects, function(o) { return o.n; });
     * // => 5
     *
     * // The `_.property` iteratee shorthand.
     * _.meanBy(objects, 'n');
     * // => 5
     */
    function meanBy(array, iteratee) {
      return baseMean(array, getIteratee(iteratee, 2));
    }

    /**
     * Computes the minimum value of `array`. If `array` is empty or falsey,
     * `undefined` is returned.
     *
     * @static
     * @since 0.1.0
     * @memberOf _
     * @category Math
     * @param {Array} array The array to iterate over.
     * @returns {*} Returns the minimum value.
     * @example
     *
     * _.min([4, 2, 8, 6]);
     * // => 2
     *
     * _.min([]);
     * // => undefined
     */
    function min(array) {
      return (array && array.length)
        ? baseExtremum(array, identity, baseLt)
        : undefined;
    }

    /**
     * This method is like `_.min` except that it accepts `iteratee` which is
     * invoked for each element in `array` to generate the criterion by which
     * the value is ranked. The iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Math
     * @param {Array} array The array to iterate over.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {*} Returns the minimum value.
     * @example
     *
     * var objects = [{ 'n': 1 }, { 'n': 2 }];
     *
     * _.minBy(objects, function(o) { return o.n; });
     * // => { 'n': 1 }
     *
     * // The `_.property` iteratee shorthand.
     * _.minBy(objects, 'n');
     * // => { 'n': 1 }
     */
    function minBy(array, iteratee) {
      return (array && array.length)
        ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
        : undefined;
    }

    /**
     * Multiply two numbers.
     *
     * @static
     * @memberOf _
     * @since 4.7.0
     * @category Math
     * @param {number} multiplier The first number in a multiplication.
     * @param {number} multiplicand The second number in a multiplication.
     * @returns {number} Returns the product.
     * @example
     *
     * _.multiply(6, 4);
     * // => 24
     */
    var multiply = createMathOperation(function(multiplier, multiplicand) {
      return multiplier * multiplicand;
    }, 1);

    /**
     * Computes `number` rounded to `precision`.
     *
     * @static
     * @memberOf _
     * @since 3.10.0
     * @category Math
     * @param {number} number The number to round.
     * @param {number} [precision=0] The precision to round to.
     * @returns {number} Returns the rounded number.
     * @example
     *
     * _.round(4.006);
     * // => 4
     *
     * _.round(4.006, 2);
     * // => 4.01
     *
     * _.round(4060, -2);
     * // => 4100
     */
    var round = createRound('round');

    /**
     * Subtract two numbers.
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Math
     * @param {number} minuend The first number in a subtraction.
     * @param {number} subtrahend The second number in a subtraction.
     * @returns {number} Returns the difference.
     * @example
     *
     * _.subtract(6, 4);
     * // => 2
     */
    var subtract = createMathOperation(function(minuend, subtrahend) {
      return minuend - subtrahend;
    }, 0);

    /**
     * Computes the sum of the values in `array`.
     *
     * @static
     * @memberOf _
     * @since 3.4.0
     * @category Math
     * @param {Array} array The array to iterate over.
     * @returns {number} Returns the sum.
     * @example
     *
     * _.sum([4, 2, 8, 6]);
     * // => 20
     */
    function sum(array) {
      return (array && array.length)
        ? baseSum(array, identity)
        : 0;
    }

    /**
     * This method is like `_.sum` except that it accepts `iteratee` which is
     * invoked for each element in `array` to generate the value to be summed.
     * The iteratee is invoked with one argument: (value).
     *
     * @static
     * @memberOf _
     * @since 4.0.0
     * @category Math
     * @param {Array} array The array to iterate over.
     * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
     * @returns {number} Returns the sum.
     * @example
     *
     * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
     *
     * _.sumBy(objects, function(o) { return o.n; });
     * // => 20
     *
     * // The `_.property` iteratee shorthand.
     * _.sumBy(objects, 'n');
     * // => 20
     */
    function sumBy(array, iteratee) {
      return (array && array.length)
        ? baseSum(array, getIteratee(iteratee, 2))
        : 0;
    }

    /*------------------------------------------------------------------------*/

    // Add methods that return wrapped values in chain sequences.
    lodash.after = after;
    lodash.ary = ary;
    lodash.assign = assign;
    lodash.assignIn = assignIn;
    lodash.assignInWith = assignInWith;
    lodash.assignWith = assignWith;
    lodash.at = at;
    lodash.before = before;
    lodash.bind = bind;
    lodash.bindAll = bindAll;
    lodash.bindKey = bindKey;
    lodash.castArray = castArray;
    lodash.chain = chain;
    lodash.chunk = chunk;
    lodash.compact = compact;
    lodash.concat = concat;
    lodash.cond = cond;
    lodash.conforms = conforms;
    lodash.constant = constant;
    lodash.countBy = countBy;
    lodash.create = create;
    lodash.curry = curry;
    lodash.curryRight = curryRight;
    lodash.debounce = debounce;
    lodash.defaults = defaults;
    lodash.defaultsDeep = defaultsDeep;
    lodash.defer = defer;
    lodash.delay = delay;
    lodash.difference = difference;
    lodash.differenceBy = differenceBy;
    lodash.differenceWith = differenceWith;
    lodash.drop = drop;
    lodash.dropRight = dropRight;
    lodash.dropRightWhile = dropRightWhile;
    lodash.dropWhile = dropWhile;
    lodash.fill = fill;
    lodash.filter = filter;
    lodash.flatMap = flatMap;
    lodash.flatMapDeep = flatMapDeep;
    lodash.flatMapDepth = flatMapDepth;
    lodash.flatten = flatten;
    lodash.flattenDeep = flattenDeep;
    lodash.flattenDepth = flattenDepth;
    lodash.flip = flip;
    lodash.flow = flow;
    lodash.flowRight = flowRight;
    lodash.fromPairs = fromPairs;
    lodash.functions = functions;
    lodash.functionsIn = functionsIn;
    lodash.groupBy = groupBy;
    lodash.initial = initial;
    lodash.intersection = intersection;
    lodash.intersectionBy = intersectionBy;
    lodash.intersectionWith = intersectionWith;
    lodash.invert = invert;
    lodash.invertBy = invertBy;
    lodash.invokeMap = invokeMap;
    lodash.iteratee = iteratee;
    lodash.keyBy = keyBy;
    lodash.keys = keys;
    lodash.keysIn = keysIn;
    lodash.map = map;
    lodash.mapKeys = mapKeys;
    lodash.mapValues = mapValues;
    lodash.matches = matches;
    lodash.matchesProperty = matchesProperty;
    lodash.memoize = memoize;
    lodash.merge = merge;
    lodash.mergeWith = mergeWith;
    lodash.method = method;
    lodash.methodOf = methodOf;
    lodash.mixin = mixin;
    lodash.negate = negate;
    lodash.nthArg = nthArg;
    lodash.omit = omit;
    lodash.omitBy = omitBy;
    lodash.once = once;
    lodash.orderBy = orderBy;
    lodash.over = over;
    lodash.overArgs = overArgs;
    lodash.overEvery = overEvery;
    lodash.overSome = overSome;
    lodash.partial = partial;
    lodash.partialRight = partialRight;
    lodash.partition = partition;
    lodash.pick = pick;
    lodash.pickBy = pickBy;
    lodash.property = property;
    lodash.propertyOf = propertyOf;
    lodash.pull = pull;
    lodash.pullAll = pullAll;
    lodash.pullAllBy = pullAllBy;
    lodash.pullAllWith = pullAllWith;
    lodash.pullAt = pullAt;
    lodash.range = range;
    lodash.rangeRight = rangeRight;
    lodash.rearg = rearg;
    lodash.reject = reject;
    lodash.remove = remove;
    lodash.rest = rest;
    lodash.reverse = reverse;
    lodash.sampleSize = sampleSize;
    lodash.set = set;
    lodash.setWith = setWith;
    lodash.shuffle = shuffle;
    lodash.slice = slice;
    lodash.sortBy = sortBy;
    lodash.sortedUniq = sortedUniq;
    lodash.sortedUniqBy = sortedUniqBy;
    lodash.split = split;
    lodash.spread = spread;
    lodash.tail = tail;
    lodash.take = take;
    lodash.takeRight = takeRight;
    lodash.takeRightWhile = takeRightWhile;
    lodash.takeWhile = takeWhile;
    lodash.tap = tap;
    lodash.throttle = throttle;
    lodash.thru = thru;
    lodash.toArray = toArray;
    lodash.toPairs = toPairs;
    lodash.toPairsIn = toPairsIn;
    lodash.toPath = toPath;
    lodash.toPlainObject = toPlainObject;
    lodash.transform = transform;
    lodash.unary = unary;
    lodash.union = union;
    lodash.unionBy = unionBy;
    lodash.unionWith = unionWith;
    lodash.uniq = uniq;
    lodash.uniqBy = uniqBy;
    lodash.uniqWith = uniqWith;
    lodash.unset = unset;
    lodash.unzip = unzip;
    lodash.unzipWith = unzipWith;
    lodash.update = update;
    lodash.updateWith = updateWith;
    lodash.values = values;
    lodash.valuesIn = valuesIn;
    lodash.without = without;
    lodash.words = words;
    lodash.wrap = wrap;
    lodash.xor = xor;
    lodash.xorBy = xorBy;
    lodash.xorWith = xorWith;
    lodash.zip = zip;
    lodash.zipObject = zipObject;
    lodash.zipObjectDeep = zipObjectDeep;
    lodash.zipWith = zipWith;

    // Add aliases.
    lodash.entries = toPairs;
    lodash.entriesIn = toPairsIn;
    lodash.extend = assignIn;
    lodash.extendWith = assignInWith;

    // Add methods to `lodash.prototype`.
    mixin(lodash, lodash);

    /*------------------------------------------------------------------------*/

    // Add methods that return unwrapped values in chain sequences.
    lodash.add = add;
    lodash.attempt = attempt;
    lodash.camelCase = camelCase;
    lodash.capitalize = capitalize;
    lodash.ceil = ceil;
    lodash.clamp = clamp;
    lodash.clone = clone;
    lodash.cloneDeep = cloneDeep;
    lodash.cloneDeepWith = cloneDeepWith;
    lodash.cloneWith = cloneWith;
    lodash.conformsTo = conformsTo;
    lodash.deburr = deburr;
    lodash.defaultTo = defaultTo;
    lodash.divide = divide;
    lodash.endsWith = endsWith;
    lodash.eq = eq;
    lodash.escape = escape;
    lodash.escapeRegExp = escapeRegExp;
    lodash.every = every;
    lodash.find = find;
    lodash.findIndex = findIndex;
    lodash.findKey = findKey;
    lodash.findLast = findLast;
    lodash.findLastIndex = findLastIndex;
    lodash.findLastKey = findLastKey;
    lodash.floor = floor;
    lodash.forEach = forEach;
    lodash.forEachRight = forEachRight;
    lodash.forIn = forIn;
    lodash.forInRight = forInRight;
    lodash.forOwn = forOwn;
    lodash.forOwnRight = forOwnRight;
    lodash.get = get;
    lodash.gt = gt;
    lodash.gte = gte;
    lodash.has = has;
    lodash.hasIn = hasIn;
    lodash.head = head;
    lodash.identity = identity;
    lodash.includes = includes;
    lodash.indexOf = indexOf;
    lodash.inRange = inRange;
    lodash.invoke = invoke;
    lodash.isArguments = isArguments;
    lodash.isArray = isArray;
    lodash.isArrayBuffer = isArrayBuffer;
    lodash.isArrayLike = isArrayLike;
    lodash.isArrayLikeObject = isArrayLikeObject;
    lodash.isBoolean = isBoolean;
    lodash.isBuffer = isBuffer;
    lodash.isDate = isDate;
    lodash.isElement = isElement;
    lodash.isEmpty = isEmpty;
    lodash.isEqual = isEqual;
    lodash.isEqualWith = isEqualWith;
    lodash.isError = isError;
    lodash.isFinite = isFinite;
    lodash.isFunction = isFunction;
    lodash.isInteger = isInteger;
    lodash.isLength = isLength;
    lodash.isMap = isMap;
    lodash.isMatch = isMatch;
    lodash.isMatchWith = isMatchWith;
    lodash.isNaN = isNaN;
    lodash.isNative = isNative;
    lodash.isNil = isNil;
    lodash.isNull = isNull;
    lodash.isNumber = isNumber;
    lodash.isObject = isObject;
    lodash.isObjectLike = isObjectLike;
    lodash.isPlainObject = isPlainObject;
    lodash.isRegExp = isRegExp;
    lodash.isSafeInteger = isSafeInteger;
    lodash.isSet = isSet;
    lodash.isString = isString;
    lodash.isSymbol = isSymbol;
    lodash.isTypedArray = isTypedArray;
    lodash.isUndefined = isUndefined;
    lodash.isWeakMap = isWeakMap;
    lodash.isWeakSet = isWeakSet;
    lodash.join = join;
    lodash.kebabCase = kebabCase;
    lodash.last = last;
    lodash.lastIndexOf = lastIndexOf;
    lodash.lowerCase = lowerCase;
    lodash.lowerFirst = lowerFirst;
    lodash.lt = lt;
    lodash.lte = lte;
    lodash.max = max;
    lodash.maxBy = maxBy;
    lodash.mean = mean;
    lodash.meanBy = meanBy;
    lodash.min = min;
    lodash.minBy = minBy;
    lodash.stubArray = stubArray;
    lodash.stubFalse = stubFalse;
    lodash.stubObject = stubObject;
    lodash.stubString = stubString;
    lodash.stubTrue = stubTrue;
    lodash.multiply = multiply;
    lodash.nth = nth;
    lodash.noConflict = noConflict;
    lodash.noop = noop;
    lodash.now = now;
    lodash.pad = pad;
    lodash.padEnd = padEnd;
    lodash.padStart = padStart;
    lodash.parseInt = parseInt;
    lodash.random = random;
    lodash.reduce = reduce;
    lodash.reduceRight = reduceRight;
    lodash.repeat = repeat;
    lodash.replace = replace;
    lodash.result = result;
    lodash.round = round;
    lodash.runInContext = runInContext;
    lodash.sample = sample;
    lodash.size = size;
    lodash.snakeCase = snakeCase;
    lodash.some = some;
    lodash.sortedIndex = sortedIndex;
    lodash.sortedIndexBy = sortedIndexBy;
    lodash.sortedIndexOf = sortedIndexOf;
    lodash.sortedLastIndex = sortedLastIndex;
    lodash.sortedLastIndexBy = sortedLastIndexBy;
    lodash.sortedLastIndexOf = sortedLastIndexOf;
    lodash.startCase = startCase;
    lodash.startsWith = startsWith;
    lodash.subtract = subtract;
    lodash.sum = sum;
    lodash.sumBy = sumBy;
    lodash.template = template;
    lodash.times = times;
    lodash.toFinite = toFinite;
    lodash.toInteger = toInteger;
    lodash.toLength = toLength;
    lodash.toLower = toLower;
    lodash.toNumber = toNumber;
    lodash.toSafeInteger = toSafeInteger;
    lodash.toString = toString;
    lodash.toUpper = toUpper;
    lodash.trim = trim;
    lodash.trimEnd = trimEnd;
    lodash.trimStart = trimStart;
    lodash.truncate = truncate;
    lodash.unescape = unescape;
    lodash.uniqueId = uniqueId;
    lodash.upperCase = upperCase;
    lodash.upperFirst = upperFirst;

    // Add aliases.
    lodash.each = forEach;
    lodash.eachRight = forEachRight;
    lodash.first = head;

    mixin(lodash, (function() {
      var source = {};
      baseForOwn(lodash, function(func, methodName) {
        if (!hasOwnProperty.call(lodash.prototype, methodName)) {
          source[methodName] = func;
        }
      });
      return source;
    }()), { 'chain': false });

    /*------------------------------------------------------------------------*/

    /**
     * The semantic version number.
     *
     * @static
     * @memberOf _
     * @type {string}
     */
    lodash.VERSION = VERSION;

    // Assign default placeholders.
    arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
      lodash[methodName].placeholder = lodash;
    });

    // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
    arrayEach(['drop', 'take'], function(methodName, index) {
      LazyWrapper.prototype[methodName] = function(n) {
        n = n === undefined ? 1 : nativeMax(toInteger(n), 0);

        var result = (this.__filtered__ && !index)
          ? new LazyWrapper(this)
          : this.clone();

        if (result.__filtered__) {
          result.__takeCount__ = nativeMin(n, result.__takeCount__);
        } else {
          result.__views__.push({
            'size': nativeMin(n, MAX_ARRAY_LENGTH),
            'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
          });
        }
        return result;
      };

      LazyWrapper.prototype[methodName + 'Right'] = function(n) {
        return this.reverse()[methodName](n).reverse();
      };
    });

    // Add `LazyWrapper` methods that accept an `iteratee` value.
    arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
      var type = index + 1,
          isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;

      LazyWrapper.prototype[methodName] = function(iteratee) {
        var result = this.clone();
        result.__iteratees__.push({
          'iteratee': getIteratee(iteratee, 3),
          'type': type
        });
        result.__filtered__ = result.__filtered__ || isFilter;
        return result;
      };
    });

    // Add `LazyWrapper` methods for `_.head` and `_.last`.
    arrayEach(['head', 'last'], function(methodName, index) {
      var takeName = 'take' + (index ? 'Right' : '');

      LazyWrapper.prototype[methodName] = function() {
        return this[takeName](1).value()[0];
      };
    });

    // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
    arrayEach(['initial', 'tail'], function(methodName, index) {
      var dropName = 'drop' + (index ? '' : 'Right');

      LazyWrapper.prototype[methodName] = function() {
        return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
      };
    });

    LazyWrapper.prototype.compact = function() {
      return this.filter(identity);
    };

    LazyWrapper.prototype.find = function(predicate) {
      return this.filter(predicate).head();
    };

    LazyWrapper.prototype.findLast = function(predicate) {
      return this.reverse().find(predicate);
    };

    LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
      if (typeof path == 'function') {
        return new LazyWrapper(this);
      }
      return this.map(function(value) {
        return baseInvoke(value, path, args);
      });
    });

    LazyWrapper.prototype.reject = function(predicate) {
      return this.filter(negate(getIteratee(predicate)));
    };

    LazyWrapper.prototype.slice = function(start, end) {
      start = toInteger(start);

      var result = this;
      if (result.__filtered__ && (start > 0 || end < 0)) {
        return new LazyWrapper(result);
      }
      if (start < 0) {
        result = result.takeRight(-start);
      } else if (start) {
        result = result.drop(start);
      }
      if (end !== undefined) {
        end = toInteger(end);
        result = end < 0 ? result.dropRight(-end) : result.take(end - start);
      }
      return result;
    };

    LazyWrapper.prototype.takeRightWhile = function(predicate) {
      return this.reverse().takeWhile(predicate).reverse();
    };

    LazyWrapper.prototype.toArray = function() {
      return this.take(MAX_ARRAY_LENGTH);
    };

    // Add `LazyWrapper` methods to `lodash.prototype`.
    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
      var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
          isTaker = /^(?:head|last)$/.test(methodName),
          lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
          retUnwrapped = isTaker || /^find/.test(methodName);

      if (!lodashFunc) {
        return;
      }
      lodash.prototype[methodName] = function() {
        var value = this.__wrapped__,
            args = isTaker ? [1] : arguments,
            isLazy = value instanceof LazyWrapper,
            iteratee = args[0],
            useLazy = isLazy || isArray(value);

        var interceptor = function(value) {
          var result = lodashFunc.apply(lodash, arrayPush([value], args));
          return (isTaker && chainAll) ? result[0] : result;
        };

        if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
          // Avoid lazy use if the iteratee has a "length" value other than `1`.
          isLazy = useLazy = false;
        }
        var chainAll = this.__chain__,
            isHybrid = !!this.__actions__.length,
            isUnwrapped = retUnwrapped && !chainAll,
            onlyLazy = isLazy && !isHybrid;

        if (!retUnwrapped && useLazy) {
          value = onlyLazy ? value : new LazyWrapper(this);
          var result = func.apply(value, args);
          result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
          return new LodashWrapper(result, chainAll);
        }
        if (isUnwrapped && onlyLazy) {
          return func.apply(this, args);
        }
        result = this.thru(interceptor);
        return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
      };
    });

    // Add `Array` methods to `lodash.prototype`.
    arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
      var func = arrayProto[methodName],
          chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
          retUnwrapped = /^(?:pop|shift)$/.test(methodName);

      lodash.prototype[methodName] = function() {
        var args = arguments;
        if (retUnwrapped && !this.__chain__) {
          var value = this.value();
          return func.apply(isArray(value) ? value : [], args);
        }
        return this[chainName](function(value) {
          return func.apply(isArray(value) ? value : [], args);
        });
      };
    });

    // Map minified method names to their real names.
    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
      var lodashFunc = lodash[methodName];
      if (lodashFunc) {
        var key = (lodashFunc.name + ''),
            names = realNames[key] || (realNames[key] = []);

        names.push({ 'name': methodName, 'func': lodashFunc });
      }
    });

    realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
      'name': 'wrapper',
      'func': undefined
    }];

    // Add methods to `LazyWrapper`.
    LazyWrapper.prototype.clone = lazyClone;
    LazyWrapper.prototype.reverse = lazyReverse;
    LazyWrapper.prototype.value = lazyValue;

    // Add chain sequence methods to the `lodash` wrapper.
    lodash.prototype.at = wrapperAt;
    lodash.prototype.chain = wrapperChain;
    lodash.prototype.commit = wrapperCommit;
    lodash.prototype.next = wrapperNext;
    lodash.prototype.plant = wrapperPlant;
    lodash.prototype.reverse = wrapperReverse;
    lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;

    // Add lazy aliases.
    lodash.prototype.first = lodash.prototype.head;

    if (symIterator) {
      lodash.prototype[symIterator] = wrapperToIterator;
    }
    return lodash;
  });

  /*--------------------------------------------------------------------------*/

  // Export lodash.
  var _ = runInContext();

  // Some AMD build optimizers, like r.js, check for condition patterns like:
  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
    // Expose Lodash on the global object to prevent errors when Lodash is
    // loaded by a script tag in the presence of an AMD loader.
    // See http://requirejs.org/docs/errors.html#mismatch for more details.
    // Use `_.noConflict` to remove Lodash from the global object.
    root._ = _;

    // Define as an anonymous module so, through path mapping, it can be
    // referenced as the "underscore" module.
    define('lodash',[],function() {
      return _;
    });
  }
  // Check for `exports` after `define` in case a build optimizer adds it.
  else if (freeModule) {
    // Export for Node.js.
    (freeModule.exports = _)._ = _;
    // Export for CommonJS support.
    freeExports._ = _;
  }
  else {
    // Export to the global object.
    root._ = _;
  }
}.call(this));

vendors/angular-md5/angular-md5.min.js
/*
  angular-md5 - v0.1.8 
  2015-07-27
*/

/* commonjs package manager support (eg componentjs) */
if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports) {
  module.exports = "angular-md5";
}

!function(a){a.module("angular-md5",["gdi2290.md5"]),a.module("ngMd5",["gdi2290.md5"]),a.module("gdi2290.md5",["gdi2290.gravatar-filter","gdi2290.md5-service","gdi2290.md5-filter"]),a.module("gdi2290.gravatar-filter",[]).filter("gravatar",["md5",function(a){var b={};return function(c,d){return b[c]||(d=d?a.createHash(d.toString().toLowerCase()):"",b[c]=c?a.createHash(c.toString().toLowerCase()):d),b[c]}}]),a.module("gdi2290.md5-filter",[]).filter("md5",["md5",function(a){return function(b){return b?a.createHash(b.toString().toLowerCase()):b}}]),a.module("gdi2290.md5-service",[]).factory("md5",[function(){var a={createHash:function(a){var b,c,d,e,f,g,h,i,j,k,l=function(a,b){return a<<b|a>>>32-b},m=function(a,b){var c,d,e,f,g;return e=2147483648&a,f=2147483648&b,c=1073741824&a,d=1073741824&b,g=(1073741823&a)+(1073741823&b),c&d?2147483648^g^e^f:c|d?1073741824&g?3221225472^g^e^f:1073741824^g^e^f:g^e^f},n=function(a,b,c){return a&b|~a&c},o=function(a,b,c){return a&c|b&~c},p=function(a,b,c){return a^b^c},q=function(a,b,c){return b^(a|~c)},r=function(a,b,c,d,e,f,g){return a=m(a,m(m(n(b,c,d),e),g)),m(l(a,f),b)},s=function(a,b,c,d,e,f,g){return a=m(a,m(m(o(b,c,d),e),g)),m(l(a,f),b)},t=function(a,b,c,d,e,f,g){return a=m(a,m(m(p(b,c,d),e),g)),m(l(a,f),b)},u=function(a,b,c,d,e,f,g){return a=m(a,m(m(q(b,c,d),e),g)),m(l(a,f),b)},v=function(a){for(var b,c=a.length,d=c+8,e=(d-d%64)/64,f=16*(e+1),g=new Array(f-1),h=0,i=0;c>i;)b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|a.charCodeAt(i)<<h,i++;return b=(i-i%4)/4,h=i%4*8,g[b]=g[b]|128<<h,g[f-2]=c<<3,g[f-1]=c>>>29,g},w=function(a){var b,c,d="",e="";for(c=0;3>=c;c++)b=a>>>8*c&255,e="0"+b.toString(16),d+=e.substr(e.length-2,2);return d},x=[],y=7,z=12,A=17,B=22,C=5,D=9,E=14,F=20,G=4,H=11,I=16,J=23,K=6,L=10,M=15,N=21;for(x=v(a),h=1732584193,i=4023233417,j=2562383102,k=271733878,b=x.length,c=0;b>c;c+=16)d=h,e=i,f=j,g=k,h=r(h,i,j,k,x[c+0],y,3614090360),k=r(k,h,i,j,x[c+1],z,3905402710),j=r(j,k,h,i,x[c+2],A,606105819),i=r(i,j,k,h,x[c+3],B,3250441966),h=r(h,i,j,k,x[c+4],y,4118548399),k=r(k,h,i,j,x[c+5],z,1200080426),j=r(j,k,h,i,x[c+6],A,2821735955),i=r(i,j,k,h,x[c+7],B,4249261313),h=r(h,i,j,k,x[c+8],y,1770035416),k=r(k,h,i,j,x[c+9],z,2336552879),j=r(j,k,h,i,x[c+10],A,4294925233),i=r(i,j,k,h,x[c+11],B,2304563134),h=r(h,i,j,k,x[c+12],y,1804603682),k=r(k,h,i,j,x[c+13],z,4254626195),j=r(j,k,h,i,x[c+14],A,2792965006),i=r(i,j,k,h,x[c+15],B,1236535329),h=s(h,i,j,k,x[c+1],C,4129170786),k=s(k,h,i,j,x[c+6],D,3225465664),j=s(j,k,h,i,x[c+11],E,643717713),i=s(i,j,k,h,x[c+0],F,3921069994),h=s(h,i,j,k,x[c+5],C,3593408605),k=s(k,h,i,j,x[c+10],D,38016083),j=s(j,k,h,i,x[c+15],E,3634488961),i=s(i,j,k,h,x[c+4],F,3889429448),h=s(h,i,j,k,x[c+9],C,568446438),k=s(k,h,i,j,x[c+14],D,3275163606),j=s(j,k,h,i,x[c+3],E,4107603335),i=s(i,j,k,h,x[c+8],F,1163531501),h=s(h,i,j,k,x[c+13],C,2850285829),k=s(k,h,i,j,x[c+2],D,4243563512),j=s(j,k,h,i,x[c+7],E,1735328473),i=s(i,j,k,h,x[c+12],F,2368359562),h=t(h,i,j,k,x[c+5],G,4294588738),k=t(k,h,i,j,x[c+8],H,2272392833),j=t(j,k,h,i,x[c+11],I,1839030562),i=t(i,j,k,h,x[c+14],J,4259657740),h=t(h,i,j,k,x[c+1],G,2763975236),k=t(k,h,i,j,x[c+4],H,1272893353),j=t(j,k,h,i,x[c+7],I,4139469664),i=t(i,j,k,h,x[c+10],J,3200236656),h=t(h,i,j,k,x[c+13],G,681279174),k=t(k,h,i,j,x[c+0],H,3936430074),j=t(j,k,h,i,x[c+3],I,3572445317),i=t(i,j,k,h,x[c+6],J,76029189),h=t(h,i,j,k,x[c+9],G,3654602809),k=t(k,h,i,j,x[c+12],H,3873151461),j=t(j,k,h,i,x[c+15],I,530742520),i=t(i,j,k,h,x[c+2],J,3299628645),h=u(h,i,j,k,x[c+0],K,4096336452),k=u(k,h,i,j,x[c+7],L,1126891415),j=u(j,k,h,i,x[c+14],M,2878612391),i=u(i,j,k,h,x[c+5],N,4237533241),h=u(h,i,j,k,x[c+12],K,1700485571),k=u(k,h,i,j,x[c+3],L,2399980690),j=u(j,k,h,i,x[c+10],M,4293915773),i=u(i,j,k,h,x[c+1],N,2240044497),h=u(h,i,j,k,x[c+8],K,1873313359),k=u(k,h,i,j,x[c+15],L,4264355552),j=u(j,k,h,i,x[c+6],M,2734768916),i=u(i,j,k,h,x[c+13],N,1309151649),h=u(h,i,j,k,x[c+4],K,4149444226),k=u(k,h,i,j,x[c+11],L,3174756917),j=u(j,k,h,i,x[c+2],M,718787259),i=u(i,j,k,h,x[c+9],N,3951481745),h=m(h,d),i=m(i,e),j=m(j,f),k=m(k,g);var O=w(h)+w(i)+w(j)+w(k);return O.toLowerCase()}};return a}])}(angular);
//# sourceMappingURL=angular-md5.min.js.map;
define("ngMd5", ["angular"], function(){});

vendors/muton/muton.window.js
window["muton"] =
/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	/**
	 * This is the Muton.js project - a feature toggle tool with support for feature throttling and Multivariance testing.
	 *
	 * Some notes on the chosen metaphor:
	 * I'm perfectly aware that every developer should write readable code and choose the metaphors carefully. However, it
	 * was a lot of fun writing the code this way. It was a challenge to use the cell metaphor. :)
	 *
	 * To make things easier, read the following resume.
	 *
	 * DNA replication consists on three steps:
	 *  1) Opening the double helix and separation of the DNA strands
	 *  2) The priming of the template strand, or laying the foundation for the new DNA
	 *  3) Assembly of the new DNA segment, which includes proof-reading the DNA strand.
	 *
	 * Here are the enzymes responsible for each step:
	 *  Step 1) is executed by the Helicase enzyme
	 *  Step 2) is executed by the Primase enzyme
	 *  Step 3) is executed by the Polymerase enzyme
	 *
	 *  That's it.
	 *
	 * If you want to get a little deeper, please have a look at:
	 * http://www.nature.com/scitable/topicpage/cells-can-replicate-their-dna-precisely-6524830
	 */

	var reduce = __webpack_require__(1);
	var filter = __webpack_require__(124);
	var map = __webpack_require__(126);
	var forEach = __webpack_require__(128);

	var helicase = __webpack_require__(131);
	var primase = __webpack_require__(133);
	var polymerase = __webpack_require__(192);
	var proofReading = __webpack_require__(199);

	function joinToggles(features, resolvedFeatures) {
	    features.toggles = reduce(resolvedFeatures, function (result, elem) {
	        result[elem.name] = elem.toggle;
	        return result;
	    }, features.toggles);
	}

	function joinThrottles(features, resolvedFeatures) {
	    var buckets = filter(resolvedFeatures, {type : 'bucket'});
	    var names = map(buckets, 'name');

	    features.buckets = features.buckets.concat(names);
	}

	function joinBuckets(features, resolvedFeatures) {
	    var throttles = filter(resolvedFeatures, {type : 'throttle'});
	    var names = map(throttles, 'name');

	    features.throttles = features.throttles.concat(names);
	}

	function joinMutations(features, resolvedFeatures) {
	    joinToggles(features, resolvedFeatures);
	    joinThrottles(features, resolvedFeatures);
	    joinBuckets(features, resolvedFeatures);
	}

	var muton = {

	    /**
	     * Given a list of user properties and feature instructions, it returns a collection of features toggles.
	     *
	     * @deprecated use getMutations or inheritMutations instead
	     *
	     * @param userProperties (optional) A collection of user properties
	     * @param featureInstructions A collection of feature instructions which can be organized as a hierarchy of properties.
	     * @returns An collection of feature toggles
	     */
	    getFeatureMutations: function (userProperties, featureInstructions) {
	        return this.getMutations(userProperties, featureInstructions).toggles;
	    },

	    /**
	     * Given a list of user properties and feature instructions, it returns a collection of features toggles.
	     *
	     * @param userProperties (optional) A collection of user properties
	     * @param featureInstructions A collection of feature instructions which can be organized as a hierarchy of properties.
	     * @returns {{toggles: {}, buckets: Array, throttles: Array}} An collection of feature toggles
	     */
	    getMutations: function (userProperties, featureInstructions) {
	        return this.inheritMutations(userProperties, featureInstructions, {});
	    },

	    /**
	     * Given a list of user properties and feature instructions, it returns a collection of features toggles. If specified,
	     * it can inherit ancestor genes for buckets and throttle mutations
	     *
	     * @param userProperties (optional) A collection of user properties
	     * @param featureInstructions A collection of feature instructions which can be organized as a hierarchy of properties.
	     * @param ancestorGenes (optional) The ancestor genes, which is the output of previous mutations from Muton
	     * @returns {{toggles: {}, buckets: Array, throttles: Array}} An collection of feature toggles
	     */
	    inheritMutations: function (userProperties, featureInstructions, ancestorGenes) {
	        var features = {
	            toggles: {},
	            buckets: [],
	            throttles: []
	        };

	        proofReading.checkFeatureInstructions(featureInstructions);

	        forEach(featureInstructions, function (feature, featureName) {
	            // Helicase will break the user properties and features apart into two different chains
	            var propertyChains = helicase.breakProperties(userProperties, feature);

	            // Read the chains and return a primer object that will contain a set of instructions
	            var primer = primase.preparePrimer(userProperties, feature, propertyChains, true);

	            // Pick the primer, proof-read the instructions and then assemble the collection of feature toggles
	            var resolvedFeatures = polymerase.assembleFeatures(featureName, primer, ancestorGenes);

	            // Join all the mutations
	            joinMutations(features, resolvedFeatures);
	        });

	        return features;
	    }
	};

	module.exports = muton;


/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	var arrayReduce = __webpack_require__(2),
	    baseEach = __webpack_require__(3),
	    baseIteratee = __webpack_require__(37),
	    baseReduce = __webpack_require__(123),
	    isArray = __webpack_require__(19);

	/**
	 * Reduces `collection` to a value which is the accumulated result of running
	 * each element in `collection` thru `iteratee`, where each successive
	 * invocation is supplied the return value of the previous. If `accumulator`
	 * is not given, the first element of `collection` is used as the initial
	 * value. The iteratee is invoked with four arguments:
	 * (accumulator, value, index|key, collection).
	 *
	 * Many lodash methods are guarded to work as iteratees for methods like
	 * `_.reduce`, `_.reduceRight`, and `_.transform`.
	 *
	 * The guarded methods are:
	 * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
	 * and `sortBy`
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Collection
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	 * @param {*} [accumulator] The initial value.
	 * @returns {*} Returns the accumulated value.
	 * @see _.reduceRight
	 * @example
	 *
	 * _.reduce([1, 2], function(sum, n) {
	 *   return sum + n;
	 * }, 0);
	 * // => 3
	 *
	 * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
	 *   (result[value] || (result[value] = [])).push(key);
	 *   return result;
	 * }, {});
	 * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
	 */
	function reduce(collection, iteratee, accumulator) {
	  var func = isArray(collection) ? arrayReduce : baseReduce,
	      initAccum = arguments.length < 3;

	  return func(collection, baseIteratee(iteratee, 4), accumulator, initAccum, baseEach);
	}

	module.exports = reduce;


/***/ },
/* 2 */
/***/ function(module, exports) {

	/**
	 * A specialized version of `_.reduce` for arrays without support for
	 * iteratee shorthands.
	 *
	 * @private
	 * @param {Array} [array] The array to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @param {*} [accumulator] The initial value.
	 * @param {boolean} [initAccum] Specify using the first element of `array` as
	 *  the initial value.
	 * @returns {*} Returns the accumulated value.
	 */
	function arrayReduce(array, iteratee, accumulator, initAccum) {
	  var index = -1,
	      length = array == null ? 0 : array.length;

	  if (initAccum && length) {
	    accumulator = array[++index];
	  }
	  while (++index < length) {
	    accumulator = iteratee(accumulator, array[index], index, array);
	  }
	  return accumulator;
	}

	module.exports = arrayReduce;


/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	var baseForOwn = __webpack_require__(4),
	    createBaseEach = __webpack_require__(36);

	/**
	 * The base implementation of `_.forEach` without support for iteratee shorthands.
	 *
	 * @private
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @returns {Array|Object} Returns `collection`.
	 */
	var baseEach = createBaseEach(baseForOwn);

	module.exports = baseEach;


/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

	var baseFor = __webpack_require__(5),
	    keys = __webpack_require__(7);

	/**
	 * The base implementation of `_.forOwn` without support for iteratee shorthands.
	 *
	 * @private
	 * @param {Object} object The object to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @returns {Object} Returns `object`.
	 */
	function baseForOwn(object, iteratee) {
	  return object && baseFor(object, iteratee, keys);
	}

	module.exports = baseForOwn;


/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {

	var createBaseFor = __webpack_require__(6);

	/**
	 * The base implementation of `baseForOwn` which iterates over `object`
	 * properties returned by `keysFunc` and invokes `iteratee` for each property.
	 * Iteratee functions may exit iteration early by explicitly returning `false`.
	 *
	 * @private
	 * @param {Object} object The object to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @param {Function} keysFunc The function to get the keys of `object`.
	 * @returns {Object} Returns `object`.
	 */
	var baseFor = createBaseFor();

	module.exports = baseFor;


/***/ },
/* 6 */
/***/ function(module, exports) {

	/**
	 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
	 *
	 * @private
	 * @param {boolean} [fromRight] Specify iterating from right to left.
	 * @returns {Function} Returns the new base function.
	 */
	function createBaseFor(fromRight) {
	  return function(object, iteratee, keysFunc) {
	    var index = -1,
	        iterable = Object(object),
	        props = keysFunc(object),
	        length = props.length;

	    while (length--) {
	      var key = props[fromRight ? length : ++index];
	      if (iteratee(iterable[key], key, iterable) === false) {
	        break;
	      }
	    }
	    return object;
	  };
	}

	module.exports = createBaseFor;


/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {

	var arrayLikeKeys = __webpack_require__(8),
	    baseKeys = __webpack_require__(29),
	    isArrayLike = __webpack_require__(33);

	/**
	 * Creates an array of the own enumerable property names of `object`.
	 *
	 * **Note:** Non-object values are coerced to objects. See the
	 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
	 * for more details.
	 *
	 * @static
	 * @since 0.1.0
	 * @memberOf _
	 * @category Object
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of property names.
	 * @example
	 *
	 * function Foo() {
	 *   this.a = 1;
	 *   this.b = 2;
	 * }
	 *
	 * Foo.prototype.c = 3;
	 *
	 * _.keys(new Foo);
	 * // => ['a', 'b'] (iteration order is not guaranteed)
	 *
	 * _.keys('hi');
	 * // => ['0', '1']
	 */
	function keys(object) {
	  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
	}

	module.exports = keys;


/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {

	var baseTimes = __webpack_require__(9),
	    isArguments = __webpack_require__(10),
	    isArray = __webpack_require__(19),
	    isBuffer = __webpack_require__(20),
	    isIndex = __webpack_require__(23),
	    isTypedArray = __webpack_require__(24);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * Creates an array of the enumerable property names of the array-like `value`.
	 *
	 * @private
	 * @param {*} value The value to query.
	 * @param {boolean} inherited Specify returning inherited property names.
	 * @returns {Array} Returns the array of property names.
	 */
	function arrayLikeKeys(value, inherited) {
	  var isArr = isArray(value),
	      isArg = !isArr && isArguments(value),
	      isBuff = !isArr && !isArg && isBuffer(value),
	      isType = !isArr && !isArg && !isBuff && isTypedArray(value),
	      skipIndexes = isArr || isArg || isBuff || isType,
	      result = skipIndexes ? baseTimes(value.length, String) : [],
	      length = result.length;

	  for (var key in value) {
	    if ((inherited || hasOwnProperty.call(value, key)) &&
	        !(skipIndexes && (
	           // Safari 9 has enumerable `arguments.length` in strict mode.
	           key == 'length' ||
	           // Node.js 0.10 has enumerable non-index properties on buffers.
	           (isBuff && (key == 'offset' || key == 'parent')) ||
	           // PhantomJS 2 has enumerable non-index properties on typed arrays.
	           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
	           // Skip index properties.
	           isIndex(key, length)
	        ))) {
	      result.push(key);
	    }
	  }
	  return result;
	}

	module.exports = arrayLikeKeys;


/***/ },
/* 9 */
/***/ function(module, exports) {

	/**
	 * The base implementation of `_.times` without support for iteratee shorthands
	 * or max array length checks.
	 *
	 * @private
	 * @param {number} n The number of times to invoke `iteratee`.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @returns {Array} Returns the array of results.
	 */
	function baseTimes(n, iteratee) {
	  var index = -1,
	      result = Array(n);

	  while (++index < n) {
	    result[index] = iteratee(index);
	  }
	  return result;
	}

	module.exports = baseTimes;


/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {

	var baseIsArguments = __webpack_require__(11),
	    isObjectLike = __webpack_require__(18);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/** Built-in value references. */
	var propertyIsEnumerable = objectProto.propertyIsEnumerable;

	/**
	 * Checks if `value` is likely an `arguments` object.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
	 *  else `false`.
	 * @example
	 *
	 * _.isArguments(function() { return arguments; }());
	 * // => true
	 *
	 * _.isArguments([1, 2, 3]);
	 * // => false
	 */
	var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
	  return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
	    !propertyIsEnumerable.call(value, 'callee');
	};

	module.exports = isArguments;


/***/ },
/* 11 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetTag = __webpack_require__(12),
	    isObjectLike = __webpack_require__(18);

	/** `Object#toString` result references. */
	var argsTag = '[object Arguments]';

	/**
	 * The base implementation of `_.isArguments`.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
	 */
	function baseIsArguments(value) {
	  return isObjectLike(value) && baseGetTag(value) == argsTag;
	}

	module.exports = baseIsArguments;


/***/ },
/* 12 */
/***/ function(module, exports, __webpack_require__) {

	var Symbol = __webpack_require__(13),
	    getRawTag = __webpack_require__(16),
	    objectToString = __webpack_require__(17);

	/** `Object#toString` result references. */
	var nullTag = '[object Null]',
	    undefinedTag = '[object Undefined]';

	/** Built-in value references. */
	var symToStringTag = Symbol ? Symbol.toStringTag : undefined;

	/**
	 * The base implementation of `getTag` without fallbacks for buggy environments.
	 *
	 * @private
	 * @param {*} value The value to query.
	 * @returns {string} Returns the `toStringTag`.
	 */
	function baseGetTag(value) {
	  if (value == null) {
	    return value === undefined ? undefinedTag : nullTag;
	  }
	  return (symToStringTag && symToStringTag in Object(value))
	    ? getRawTag(value)
	    : objectToString(value);
	}

	module.exports = baseGetTag;


/***/ },
/* 13 */
/***/ function(module, exports, __webpack_require__) {

	var root = __webpack_require__(14);

	/** Built-in value references. */
	var Symbol = root.Symbol;

	module.exports = Symbol;


/***/ },
/* 14 */
/***/ function(module, exports, __webpack_require__) {

	var freeGlobal = __webpack_require__(15);

	/** Detect free variable `self`. */
	var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

	/** Used as a reference to the global object. */
	var root = freeGlobal || freeSelf || Function('return this')();

	module.exports = root;


/***/ },
/* 15 */
/***/ function(module, exports) {

	/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
	var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

	module.exports = freeGlobal;

	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },
/* 16 */
/***/ function(module, exports, __webpack_require__) {

	var Symbol = __webpack_require__(13);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * Used to resolve the
	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
	 * of values.
	 */
	var nativeObjectToString = objectProto.toString;

	/** Built-in value references. */
	var symToStringTag = Symbol ? Symbol.toStringTag : undefined;

	/**
	 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
	 *
	 * @private
	 * @param {*} value The value to query.
	 * @returns {string} Returns the raw `toStringTag`.
	 */
	function getRawTag(value) {
	  var isOwn = hasOwnProperty.call(value, symToStringTag),
	      tag = value[symToStringTag];

	  try {
	    value[symToStringTag] = undefined;
	    var unmasked = true;
	  } catch (e) {}

	  var result = nativeObjectToString.call(value);
	  if (unmasked) {
	    if (isOwn) {
	      value[symToStringTag] = tag;
	    } else {
	      delete value[symToStringTag];
	    }
	  }
	  return result;
	}

	module.exports = getRawTag;


/***/ },
/* 17 */
/***/ function(module, exports) {

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/**
	 * Used to resolve the
	 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
	 * of values.
	 */
	var nativeObjectToString = objectProto.toString;

	/**
	 * Converts `value` to a string using `Object.prototype.toString`.
	 *
	 * @private
	 * @param {*} value The value to convert.
	 * @returns {string} Returns the converted string.
	 */
	function objectToString(value) {
	  return nativeObjectToString.call(value);
	}

	module.exports = objectToString;


/***/ },
/* 18 */
/***/ function(module, exports) {

	/**
	 * Checks if `value` is object-like. A value is object-like if it's not `null`
	 * and has a `typeof` result of "object".
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
	 * @example
	 *
	 * _.isObjectLike({});
	 * // => true
	 *
	 * _.isObjectLike([1, 2, 3]);
	 * // => true
	 *
	 * _.isObjectLike(_.noop);
	 * // => false
	 *
	 * _.isObjectLike(null);
	 * // => false
	 */
	function isObjectLike(value) {
	  return value != null && typeof value == 'object';
	}

	module.exports = isObjectLike;


/***/ },
/* 19 */
/***/ function(module, exports) {

	/**
	 * Checks if `value` is classified as an `Array` object.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
	 * @example
	 *
	 * _.isArray([1, 2, 3]);
	 * // => true
	 *
	 * _.isArray(document.body.children);
	 * // => false
	 *
	 * _.isArray('abc');
	 * // => false
	 *
	 * _.isArray(_.noop);
	 * // => false
	 */
	var isArray = Array.isArray;

	module.exports = isArray;


/***/ },
/* 20 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(14),
	    stubFalse = __webpack_require__(22);

	/** Detect free variable `exports`. */
	var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

	/** Detect free variable `module`. */
	var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

	/** Detect the popular CommonJS extension `module.exports`. */
	var moduleExports = freeModule && freeModule.exports === freeExports;

	/** Built-in value references. */
	var Buffer = moduleExports ? root.Buffer : undefined;

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;

	/**
	 * Checks if `value` is a buffer.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.3.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
	 * @example
	 *
	 * _.isBuffer(new Buffer(2));
	 * // => true
	 *
	 * _.isBuffer(new Uint8Array(2));
	 * // => false
	 */
	var isBuffer = nativeIsBuffer || stubFalse;

	module.exports = isBuffer;

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(21)(module)))

/***/ },
/* 21 */
/***/ function(module, exports) {

	module.exports = function(module) {
		if(!module.webpackPolyfill) {
			module.deprecate = function() {};
			module.paths = [];
			// module.parent = undefined by default
			module.children = [];
			module.webpackPolyfill = 1;
		}
		return module;
	}


/***/ },
/* 22 */
/***/ function(module, exports) {

	/**
	 * This method returns `false`.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.13.0
	 * @category Util
	 * @returns {boolean} Returns `false`.
	 * @example
	 *
	 * _.times(2, _.stubFalse);
	 * // => [false, false]
	 */
	function stubFalse() {
	  return false;
	}

	module.exports = stubFalse;


/***/ },
/* 23 */
/***/ function(module, exports) {

	/** Used as references for various `Number` constants. */
	var MAX_SAFE_INTEGER = 9007199254740991;

	/** Used to detect unsigned integer values. */
	var reIsUint = /^(?:0|[1-9]\d*)$/;

	/**
	 * Checks if `value` is a valid array-like index.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
	 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
	 */
	function isIndex(value, length) {
	  length = length == null ? MAX_SAFE_INTEGER : length;
	  return !!length &&
	    (typeof value == 'number' || reIsUint.test(value)) &&
	    (value > -1 && value % 1 == 0 && value < length);
	}

	module.exports = isIndex;


/***/ },
/* 24 */
/***/ function(module, exports, __webpack_require__) {

	var baseIsTypedArray = __webpack_require__(25),
	    baseUnary = __webpack_require__(27),
	    nodeUtil = __webpack_require__(28);

	/* Node.js helper references. */
	var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

	/**
	 * Checks if `value` is classified as a typed array.
	 *
	 * @static
	 * @memberOf _
	 * @since 3.0.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
	 * @example
	 *
	 * _.isTypedArray(new Uint8Array);
	 * // => true
	 *
	 * _.isTypedArray([]);
	 * // => false
	 */
	var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

	module.exports = isTypedArray;


/***/ },
/* 25 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetTag = __webpack_require__(12),
	    isLength = __webpack_require__(26),
	    isObjectLike = __webpack_require__(18);

	/** `Object#toString` result references. */
	var argsTag = '[object Arguments]',
	    arrayTag = '[object Array]',
	    boolTag = '[object Boolean]',
	    dateTag = '[object Date]',
	    errorTag = '[object Error]',
	    funcTag = '[object Function]',
	    mapTag = '[object Map]',
	    numberTag = '[object Number]',
	    objectTag = '[object Object]',
	    regexpTag = '[object RegExp]',
	    setTag = '[object Set]',
	    stringTag = '[object String]',
	    weakMapTag = '[object WeakMap]';

	var arrayBufferTag = '[object ArrayBuffer]',
	    dataViewTag = '[object DataView]',
	    float32Tag = '[object Float32Array]',
	    float64Tag = '[object Float64Array]',
	    int8Tag = '[object Int8Array]',
	    int16Tag = '[object Int16Array]',
	    int32Tag = '[object Int32Array]',
	    uint8Tag = '[object Uint8Array]',
	    uint8ClampedTag = '[object Uint8ClampedArray]',
	    uint16Tag = '[object Uint16Array]',
	    uint32Tag = '[object Uint32Array]';

	/** Used to identify `toStringTag` values of typed arrays. */
	var typedArrayTags = {};
	typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
	typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
	typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
	typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
	typedArrayTags[uint32Tag] = true;
	typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
	typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
	typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
	typedArrayTags[errorTag] = typedArrayTags[funcTag] =
	typedArrayTags[mapTag] = typedArrayTags[numberTag] =
	typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
	typedArrayTags[setTag] = typedArrayTags[stringTag] =
	typedArrayTags[weakMapTag] = false;

	/**
	 * The base implementation of `_.isTypedArray` without Node.js optimizations.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
	 */
	function baseIsTypedArray(value) {
	  return isObjectLike(value) &&
	    isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
	}

	module.exports = baseIsTypedArray;


/***/ },
/* 26 */
/***/ function(module, exports) {

	/** Used as references for various `Number` constants. */
	var MAX_SAFE_INTEGER = 9007199254740991;

	/**
	 * Checks if `value` is a valid array-like length.
	 *
	 * **Note:** This method is loosely based on
	 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
	 * @example
	 *
	 * _.isLength(3);
	 * // => true
	 *
	 * _.isLength(Number.MIN_VALUE);
	 * // => false
	 *
	 * _.isLength(Infinity);
	 * // => false
	 *
	 * _.isLength('3');
	 * // => false
	 */
	function isLength(value) {
	  return typeof value == 'number' &&
	    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
	}

	module.exports = isLength;


/***/ },
/* 27 */
/***/ function(module, exports) {

	/**
	 * The base implementation of `_.unary` without support for storing metadata.
	 *
	 * @private
	 * @param {Function} func The function to cap arguments for.
	 * @returns {Function} Returns the new capped function.
	 */
	function baseUnary(func) {
	  return function(value) {
	    return func(value);
	  };
	}

	module.exports = baseUnary;


/***/ },
/* 28 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(15);

	/** Detect free variable `exports`. */
	var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

	/** Detect free variable `module`. */
	var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

	/** Detect the popular CommonJS extension `module.exports`. */
	var moduleExports = freeModule && freeModule.exports === freeExports;

	/** Detect free variable `process` from Node.js. */
	var freeProcess = moduleExports && freeGlobal.process;

	/** Used to access faster Node.js helpers. */
	var nodeUtil = (function() {
	  try {
	    return freeProcess && freeProcess.binding && freeProcess.binding('util');
	  } catch (e) {}
	}());

	module.exports = nodeUtil;

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(21)(module)))

/***/ },
/* 29 */
/***/ function(module, exports, __webpack_require__) {

	var isPrototype = __webpack_require__(30),
	    nativeKeys = __webpack_require__(31);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of property names.
	 */
	function baseKeys(object) {
	  if (!isPrototype(object)) {
	    return nativeKeys(object);
	  }
	  var result = [];
	  for (var key in Object(object)) {
	    if (hasOwnProperty.call(object, key) && key != 'constructor') {
	      result.push(key);
	    }
	  }
	  return result;
	}

	module.exports = baseKeys;


/***/ },
/* 30 */
/***/ function(module, exports) {

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/**
	 * Checks if `value` is likely a prototype object.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
	 */
	function isPrototype(value) {
	  var Ctor = value && value.constructor,
	      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

	  return value === proto;
	}

	module.exports = isPrototype;


/***/ },
/* 31 */
/***/ function(module, exports, __webpack_require__) {

	var overArg = __webpack_require__(32);

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeKeys = overArg(Object.keys, Object);

	module.exports = nativeKeys;


/***/ },
/* 32 */
/***/ function(module, exports) {

	/**
	 * Creates a unary function that invokes `func` with its argument transformed.
	 *
	 * @private
	 * @param {Function} func The function to wrap.
	 * @param {Function} transform The argument transform.
	 * @returns {Function} Returns the new function.
	 */
	function overArg(func, transform) {
	  return function(arg) {
	    return func(transform(arg));
	  };
	}

	module.exports = overArg;


/***/ },
/* 33 */
/***/ function(module, exports, __webpack_require__) {

	var isFunction = __webpack_require__(34),
	    isLength = __webpack_require__(26);

	/**
	 * Checks if `value` is array-like. A value is considered array-like if it's
	 * not a function and has a `value.length` that's an integer greater than or
	 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
	 * @example
	 *
	 * _.isArrayLike([1, 2, 3]);
	 * // => true
	 *
	 * _.isArrayLike(document.body.children);
	 * // => true
	 *
	 * _.isArrayLike('abc');
	 * // => true
	 *
	 * _.isArrayLike(_.noop);
	 * // => false
	 */
	function isArrayLike(value) {
	  return value != null && isLength(value.length) && !isFunction(value);
	}

	module.exports = isArrayLike;


/***/ },
/* 34 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetTag = __webpack_require__(12),
	    isObject = __webpack_require__(35);

	/** `Object#toString` result references. */
	var asyncTag = '[object AsyncFunction]',
	    funcTag = '[object Function]',
	    genTag = '[object GeneratorFunction]',
	    proxyTag = '[object Proxy]';

	/**
	 * Checks if `value` is classified as a `Function` object.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
	 * @example
	 *
	 * _.isFunction(_);
	 * // => true
	 *
	 * _.isFunction(/abc/);
	 * // => false
	 */
	function isFunction(value) {
	  if (!isObject(value)) {
	    return false;
	  }
	  // The use of `Object#toString` avoids issues with the `typeof` operator
	  // in Safari 9 which returns 'object' for typed arrays and other constructors.
	  var tag = baseGetTag(value);
	  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
	}

	module.exports = isFunction;


/***/ },
/* 35 */
/***/ function(module, exports) {

	/**
	 * Checks if `value` is the
	 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
	 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
	 * @example
	 *
	 * _.isObject({});
	 * // => true
	 *
	 * _.isObject([1, 2, 3]);
	 * // => true
	 *
	 * _.isObject(_.noop);
	 * // => true
	 *
	 * _.isObject(null);
	 * // => false
	 */
	function isObject(value) {
	  var type = typeof value;
	  return value != null && (type == 'object' || type == 'function');
	}

	module.exports = isObject;


/***/ },
/* 36 */
/***/ function(module, exports, __webpack_require__) {

	var isArrayLike = __webpack_require__(33);

	/**
	 * Creates a `baseEach` or `baseEachRight` function.
	 *
	 * @private
	 * @param {Function} eachFunc The function to iterate over a collection.
	 * @param {boolean} [fromRight] Specify iterating from right to left.
	 * @returns {Function} Returns the new base function.
	 */
	function createBaseEach(eachFunc, fromRight) {
	  return function(collection, iteratee) {
	    if (collection == null) {
	      return collection;
	    }
	    if (!isArrayLike(collection)) {
	      return eachFunc(collection, iteratee);
	    }
	    var length = collection.length,
	        index = fromRight ? length : -1,
	        iterable = Object(collection);

	    while ((fromRight ? index-- : ++index < length)) {
	      if (iteratee(iterable[index], index, iterable) === false) {
	        break;
	      }
	    }
	    return collection;
	  };
	}

	module.exports = createBaseEach;


/***/ },
/* 37 */
/***/ function(module, exports, __webpack_require__) {

	var baseMatches = __webpack_require__(38),
	    baseMatchesProperty = __webpack_require__(103),
	    identity = __webpack_require__(119),
	    isArray = __webpack_require__(19),
	    property = __webpack_require__(120);

	/**
	 * The base implementation of `_.iteratee`.
	 *
	 * @private
	 * @param {*} [value=_.identity] The value to convert to an iteratee.
	 * @returns {Function} Returns the iteratee.
	 */
	function baseIteratee(value) {
	  // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
	  // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
	  if (typeof value == 'function') {
	    return value;
	  }
	  if (value == null) {
	    return identity;
	  }
	  if (typeof value == 'object') {
	    return isArray(value)
	      ? baseMatchesProperty(value[0], value[1])
	      : baseMatches(value);
	  }
	  return property(value);
	}

	module.exports = baseIteratee;


/***/ },
/* 38 */
/***/ function(module, exports, __webpack_require__) {

	var baseIsMatch = __webpack_require__(39),
	    getMatchData = __webpack_require__(100),
	    matchesStrictComparable = __webpack_require__(102);

	/**
	 * The base implementation of `_.matches` which doesn't clone `source`.
	 *
	 * @private
	 * @param {Object} source The object of property values to match.
	 * @returns {Function} Returns the new spec function.
	 */
	function baseMatches(source) {
	  var matchData = getMatchData(source);
	  if (matchData.length == 1 && matchData[0][2]) {
	    return matchesStrictComparable(matchData[0][0], matchData[0][1]);
	  }
	  return function(object) {
	    return object === source || baseIsMatch(object, source, matchData);
	  };
	}

	module.exports = baseMatches;


/***/ },
/* 39 */
/***/ function(module, exports, __webpack_require__) {

	var Stack = __webpack_require__(40),
	    baseIsEqual = __webpack_require__(76);

	/** Used to compose bitmasks for value comparisons. */
	var COMPARE_PARTIAL_FLAG = 1,
	    COMPARE_UNORDERED_FLAG = 2;

	/**
	 * The base implementation of `_.isMatch` without support for iteratee shorthands.
	 *
	 * @private
	 * @param {Object} object The object to inspect.
	 * @param {Object} source The object of property values to match.
	 * @param {Array} matchData The property names, values, and compare flags to match.
	 * @param {Function} [customizer] The function to customize comparisons.
	 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
	 */
	function baseIsMatch(object, source, matchData, customizer) {
	  var index = matchData.length,
	      length = index,
	      noCustomizer = !customizer;

	  if (object == null) {
	    return !length;
	  }
	  object = Object(object);
	  while (index--) {
	    var data = matchData[index];
	    if ((noCustomizer && data[2])
	          ? data[1] !== object[data[0]]
	          : !(data[0] in object)
	        ) {
	      return false;
	    }
	  }
	  while (++index < length) {
	    data = matchData[index];
	    var key = data[0],
	        objValue = object[key],
	        srcValue = data[1];

	    if (noCustomizer && data[2]) {
	      if (objValue === undefined && !(key in object)) {
	        return false;
	      }
	    } else {
	      var stack = new Stack;
	      if (customizer) {
	        var result = customizer(objValue, srcValue, key, object, source, stack);
	      }
	      if (!(result === undefined
	            ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
	            : result
	          )) {
	        return false;
	      }
	    }
	  }
	  return true;
	}

	module.exports = baseIsMatch;


/***/ },
/* 40 */
/***/ function(module, exports, __webpack_require__) {

	var ListCache = __webpack_require__(41),
	    stackClear = __webpack_require__(49),
	    stackDelete = __webpack_require__(50),
	    stackGet = __webpack_require__(51),
	    stackHas = __webpack_require__(52),
	    stackSet = __webpack_require__(53);

	/**
	 * Creates a stack cache object to store key-value pairs.
	 *
	 * @private
	 * @constructor
	 * @param {Array} [entries] The key-value pairs to cache.
	 */
	function Stack(entries) {
	  var data = this.__data__ = new ListCache(entries);
	  this.size = data.size;
	}

	// Add methods to `Stack`.
	Stack.prototype.clear = stackClear;
	Stack.prototype['delete'] = stackDelete;
	Stack.prototype.get = stackGet;
	Stack.prototype.has = stackHas;
	Stack.prototype.set = stackSet;

	module.exports = Stack;


/***/ },
/* 41 */
/***/ function(module, exports, __webpack_require__) {

	var listCacheClear = __webpack_require__(42),
	    listCacheDelete = __webpack_require__(43),
	    listCacheGet = __webpack_require__(46),
	    listCacheHas = __webpack_require__(47),
	    listCacheSet = __webpack_require__(48);

	/**
	 * Creates an list cache object.
	 *
	 * @private
	 * @constructor
	 * @param {Array} [entries] The key-value pairs to cache.
	 */
	function ListCache(entries) {
	  var index = -1,
	      length = entries == null ? 0 : entries.length;

	  this.clear();
	  while (++index < length) {
	    var entry = entries[index];
	    this.set(entry[0], entry[1]);
	  }
	}

	// Add methods to `ListCache`.
	ListCache.prototype.clear = listCacheClear;
	ListCache.prototype['delete'] = listCacheDelete;
	ListCache.prototype.get = listCacheGet;
	ListCache.prototype.has = listCacheHas;
	ListCache.prototype.set = listCacheSet;

	module.exports = ListCache;


/***/ },
/* 42 */
/***/ function(module, exports) {

	/**
	 * Removes all key-value entries from the list cache.
	 *
	 * @private
	 * @name clear
	 * @memberOf ListCache
	 */
	function listCacheClear() {
	  this.__data__ = [];
	  this.size = 0;
	}

	module.exports = listCacheClear;


/***/ },
/* 43 */
/***/ function(module, exports, __webpack_require__) {

	var assocIndexOf = __webpack_require__(44);

	/** Used for built-in method references. */
	var arrayProto = Array.prototype;

	/** Built-in value references. */
	var splice = arrayProto.splice;

	/**
	 * Removes `key` and its value from the list cache.
	 *
	 * @private
	 * @name delete
	 * @memberOf ListCache
	 * @param {string} key The key of the value to remove.
	 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	 */
	function listCacheDelete(key) {
	  var data = this.__data__,
	      index = assocIndexOf(data, key);

	  if (index < 0) {
	    return false;
	  }
	  var lastIndex = data.length - 1;
	  if (index == lastIndex) {
	    data.pop();
	  } else {
	    splice.call(data, index, 1);
	  }
	  --this.size;
	  return true;
	}

	module.exports = listCacheDelete;


/***/ },
/* 44 */
/***/ function(module, exports, __webpack_require__) {

	var eq = __webpack_require__(45);

	/**
	 * Gets the index at which the `key` is found in `array` of key-value pairs.
	 *
	 * @private
	 * @param {Array} array The array to inspect.
	 * @param {*} key The key to search for.
	 * @returns {number} Returns the index of the matched value, else `-1`.
	 */
	function assocIndexOf(array, key) {
	  var length = array.length;
	  while (length--) {
	    if (eq(array[length][0], key)) {
	      return length;
	    }
	  }
	  return -1;
	}

	module.exports = assocIndexOf;


/***/ },
/* 45 */
/***/ function(module, exports) {

	/**
	 * Performs a
	 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
	 * comparison between two values to determine if they are equivalent.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to compare.
	 * @param {*} other The other value to compare.
	 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
	 * @example
	 *
	 * var object = { 'a': 1 };
	 * var other = { 'a': 1 };
	 *
	 * _.eq(object, object);
	 * // => true
	 *
	 * _.eq(object, other);
	 * // => false
	 *
	 * _.eq('a', 'a');
	 * // => true
	 *
	 * _.eq('a', Object('a'));
	 * // => false
	 *
	 * _.eq(NaN, NaN);
	 * // => true
	 */
	function eq(value, other) {
	  return value === other || (value !== value && other !== other);
	}

	module.exports = eq;


/***/ },
/* 46 */
/***/ function(module, exports, __webpack_require__) {

	var assocIndexOf = __webpack_require__(44);

	/**
	 * Gets the list cache value for `key`.
	 *
	 * @private
	 * @name get
	 * @memberOf ListCache
	 * @param {string} key The key of the value to get.
	 * @returns {*} Returns the entry value.
	 */
	function listCacheGet(key) {
	  var data = this.__data__,
	      index = assocIndexOf(data, key);

	  return index < 0 ? undefined : data[index][1];
	}

	module.exports = listCacheGet;


/***/ },
/* 47 */
/***/ function(module, exports, __webpack_require__) {

	var assocIndexOf = __webpack_require__(44);

	/**
	 * Checks if a list cache value for `key` exists.
	 *
	 * @private
	 * @name has
	 * @memberOf ListCache
	 * @param {string} key The key of the entry to check.
	 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	 */
	function listCacheHas(key) {
	  return assocIndexOf(this.__data__, key) > -1;
	}

	module.exports = listCacheHas;


/***/ },
/* 48 */
/***/ function(module, exports, __webpack_require__) {

	var assocIndexOf = __webpack_require__(44);

	/**
	 * Sets the list cache `key` to `value`.
	 *
	 * @private
	 * @name set
	 * @memberOf ListCache
	 * @param {string} key The key of the value to set.
	 * @param {*} value The value to set.
	 * @returns {Object} Returns the list cache instance.
	 */
	function listCacheSet(key, value) {
	  var data = this.__data__,
	      index = assocIndexOf(data, key);

	  if (index < 0) {
	    ++this.size;
	    data.push([key, value]);
	  } else {
	    data[index][1] = value;
	  }
	  return this;
	}

	module.exports = listCacheSet;


/***/ },
/* 49 */
/***/ function(module, exports, __webpack_require__) {

	var ListCache = __webpack_require__(41);

	/**
	 * Removes all key-value entries from the stack.
	 *
	 * @private
	 * @name clear
	 * @memberOf Stack
	 */
	function stackClear() {
	  this.__data__ = new ListCache;
	  this.size = 0;
	}

	module.exports = stackClear;


/***/ },
/* 50 */
/***/ function(module, exports) {

	/**
	 * Removes `key` and its value from the stack.
	 *
	 * @private
	 * @name delete
	 * @memberOf Stack
	 * @param {string} key The key of the value to remove.
	 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	 */
	function stackDelete(key) {
	  var data = this.__data__,
	      result = data['delete'](key);

	  this.size = data.size;
	  return result;
	}

	module.exports = stackDelete;


/***/ },
/* 51 */
/***/ function(module, exports) {

	/**
	 * Gets the stack value for `key`.
	 *
	 * @private
	 * @name get
	 * @memberOf Stack
	 * @param {string} key The key of the value to get.
	 * @returns {*} Returns the entry value.
	 */
	function stackGet(key) {
	  return this.__data__.get(key);
	}

	module.exports = stackGet;


/***/ },
/* 52 */
/***/ function(module, exports) {

	/**
	 * Checks if a stack value for `key` exists.
	 *
	 * @private
	 * @name has
	 * @memberOf Stack
	 * @param {string} key The key of the entry to check.
	 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	 */
	function stackHas(key) {
	  return this.__data__.has(key);
	}

	module.exports = stackHas;


/***/ },
/* 53 */
/***/ function(module, exports, __webpack_require__) {

	var ListCache = __webpack_require__(41),
	    Map = __webpack_require__(54),
	    MapCache = __webpack_require__(61);

	/** Used as the size to enable large array optimizations. */
	var LARGE_ARRAY_SIZE = 200;

	/**
	 * Sets the stack `key` to `value`.
	 *
	 * @private
	 * @name set
	 * @memberOf Stack
	 * @param {string} key The key of the value to set.
	 * @param {*} value The value to set.
	 * @returns {Object} Returns the stack cache instance.
	 */
	function stackSet(key, value) {
	  var data = this.__data__;
	  if (data instanceof ListCache) {
	    var pairs = data.__data__;
	    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
	      pairs.push([key, value]);
	      this.size = ++data.size;
	      return this;
	    }
	    data = this.__data__ = new MapCache(pairs);
	  }
	  data.set(key, value);
	  this.size = data.size;
	  return this;
	}

	module.exports = stackSet;


/***/ },
/* 54 */
/***/ function(module, exports, __webpack_require__) {

	var getNative = __webpack_require__(55),
	    root = __webpack_require__(14);

	/* Built-in method references that are verified to be native. */
	var Map = getNative(root, 'Map');

	module.exports = Map;


/***/ },
/* 55 */
/***/ function(module, exports, __webpack_require__) {

	var baseIsNative = __webpack_require__(56),
	    getValue = __webpack_require__(60);

	/**
	 * Gets the native function at `key` of `object`.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @param {string} key The key of the method to get.
	 * @returns {*} Returns the function if it's native, else `undefined`.
	 */
	function getNative(object, key) {
	  var value = getValue(object, key);
	  return baseIsNative(value) ? value : undefined;
	}

	module.exports = getNative;


/***/ },
/* 56 */
/***/ function(module, exports, __webpack_require__) {

	var isFunction = __webpack_require__(34),
	    isMasked = __webpack_require__(57),
	    isObject = __webpack_require__(35),
	    toSource = __webpack_require__(59);

	/**
	 * Used to match `RegExp`
	 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
	 */
	var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

	/** Used to detect host constructors (Safari). */
	var reIsHostCtor = /^\[object .+?Constructor\]$/;

	/** Used for built-in method references. */
	var funcProto = Function.prototype,
	    objectProto = Object.prototype;

	/** Used to resolve the decompiled source of functions. */
	var funcToString = funcProto.toString;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/** Used to detect if a method is native. */
	var reIsNative = RegExp('^' +
	  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
	  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
	);

	/**
	 * The base implementation of `_.isNative` without bad shim checks.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a native function,
	 *  else `false`.
	 */
	function baseIsNative(value) {
	  if (!isObject(value) || isMasked(value)) {
	    return false;
	  }
	  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
	  return pattern.test(toSource(value));
	}

	module.exports = baseIsNative;


/***/ },
/* 57 */
/***/ function(module, exports, __webpack_require__) {

	var coreJsData = __webpack_require__(58);

	/** Used to detect methods masquerading as native. */
	var maskSrcKey = (function() {
	  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
	  return uid ? ('Symbol(src)_1.' + uid) : '';
	}());

	/**
	 * Checks if `func` has its source masked.
	 *
	 * @private
	 * @param {Function} func The function to check.
	 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
	 */
	function isMasked(func) {
	  return !!maskSrcKey && (maskSrcKey in func);
	}

	module.exports = isMasked;


/***/ },
/* 58 */
/***/ function(module, exports, __webpack_require__) {

	var root = __webpack_require__(14);

	/** Used to detect overreaching core-js shims. */
	var coreJsData = root['__core-js_shared__'];

	module.exports = coreJsData;


/***/ },
/* 59 */
/***/ function(module, exports) {

	/** Used for built-in method references. */
	var funcProto = Function.prototype;

	/** Used to resolve the decompiled source of functions. */
	var funcToString = funcProto.toString;

	/**
	 * Converts `func` to its source code.
	 *
	 * @private
	 * @param {Function} func The function to convert.
	 * @returns {string} Returns the source code.
	 */
	function toSource(func) {
	  if (func != null) {
	    try {
	      return funcToString.call(func);
	    } catch (e) {}
	    try {
	      return (func + '');
	    } catch (e) {}
	  }
	  return '';
	}

	module.exports = toSource;


/***/ },
/* 60 */
/***/ function(module, exports) {

	/**
	 * Gets the value at `key` of `object`.
	 *
	 * @private
	 * @param {Object} [object] The object to query.
	 * @param {string} key The key of the property to get.
	 * @returns {*} Returns the property value.
	 */
	function getValue(object, key) {
	  return object == null ? undefined : object[key];
	}

	module.exports = getValue;


/***/ },
/* 61 */
/***/ function(module, exports, __webpack_require__) {

	var mapCacheClear = __webpack_require__(62),
	    mapCacheDelete = __webpack_require__(70),
	    mapCacheGet = __webpack_require__(73),
	    mapCacheHas = __webpack_require__(74),
	    mapCacheSet = __webpack_require__(75);

	/**
	 * Creates a map cache object to store key-value pairs.
	 *
	 * @private
	 * @constructor
	 * @param {Array} [entries] The key-value pairs to cache.
	 */
	function MapCache(entries) {
	  var index = -1,
	      length = entries == null ? 0 : entries.length;

	  this.clear();
	  while (++index < length) {
	    var entry = entries[index];
	    this.set(entry[0], entry[1]);
	  }
	}

	// Add methods to `MapCache`.
	MapCache.prototype.clear = mapCacheClear;
	MapCache.prototype['delete'] = mapCacheDelete;
	MapCache.prototype.get = mapCacheGet;
	MapCache.prototype.has = mapCacheHas;
	MapCache.prototype.set = mapCacheSet;

	module.exports = MapCache;


/***/ },
/* 62 */
/***/ function(module, exports, __webpack_require__) {

	var Hash = __webpack_require__(63),
	    ListCache = __webpack_require__(41),
	    Map = __webpack_require__(54);

	/**
	 * Removes all key-value entries from the map.
	 *
	 * @private
	 * @name clear
	 * @memberOf MapCache
	 */
	function mapCacheClear() {
	  this.size = 0;
	  this.__data__ = {
	    'hash': new Hash,
	    'map': new (Map || ListCache),
	    'string': new Hash
	  };
	}

	module.exports = mapCacheClear;


/***/ },
/* 63 */
/***/ function(module, exports, __webpack_require__) {

	var hashClear = __webpack_require__(64),
	    hashDelete = __webpack_require__(66),
	    hashGet = __webpack_require__(67),
	    hashHas = __webpack_require__(68),
	    hashSet = __webpack_require__(69);

	/**
	 * Creates a hash object.
	 *
	 * @private
	 * @constructor
	 * @param {Array} [entries] The key-value pairs to cache.
	 */
	function Hash(entries) {
	  var index = -1,
	      length = entries == null ? 0 : entries.length;

	  this.clear();
	  while (++index < length) {
	    var entry = entries[index];
	    this.set(entry[0], entry[1]);
	  }
	}

	// Add methods to `Hash`.
	Hash.prototype.clear = hashClear;
	Hash.prototype['delete'] = hashDelete;
	Hash.prototype.get = hashGet;
	Hash.prototype.has = hashHas;
	Hash.prototype.set = hashSet;

	module.exports = Hash;


/***/ },
/* 64 */
/***/ function(module, exports, __webpack_require__) {

	var nativeCreate = __webpack_require__(65);

	/**
	 * Removes all key-value entries from the hash.
	 *
	 * @private
	 * @name clear
	 * @memberOf Hash
	 */
	function hashClear() {
	  this.__data__ = nativeCreate ? nativeCreate(null) : {};
	  this.size = 0;
	}

	module.exports = hashClear;


/***/ },
/* 65 */
/***/ function(module, exports, __webpack_require__) {

	var getNative = __webpack_require__(55);

	/* Built-in method references that are verified to be native. */
	var nativeCreate = getNative(Object, 'create');

	module.exports = nativeCreate;


/***/ },
/* 66 */
/***/ function(module, exports) {

	/**
	 * Removes `key` and its value from the hash.
	 *
	 * @private
	 * @name delete
	 * @memberOf Hash
	 * @param {Object} hash The hash to modify.
	 * @param {string} key The key of the value to remove.
	 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	 */
	function hashDelete(key) {
	  var result = this.has(key) && delete this.__data__[key];
	  this.size -= result ? 1 : 0;
	  return result;
	}

	module.exports = hashDelete;


/***/ },
/* 67 */
/***/ function(module, exports, __webpack_require__) {

	var nativeCreate = __webpack_require__(65);

	/** Used to stand-in for `undefined` hash values. */
	var HASH_UNDEFINED = '__lodash_hash_undefined__';

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * Gets the hash value for `key`.
	 *
	 * @private
	 * @name get
	 * @memberOf Hash
	 * @param {string} key The key of the value to get.
	 * @returns {*} Returns the entry value.
	 */
	function hashGet(key) {
	  var data = this.__data__;
	  if (nativeCreate) {
	    var result = data[key];
	    return result === HASH_UNDEFINED ? undefined : result;
	  }
	  return hasOwnProperty.call(data, key) ? data[key] : undefined;
	}

	module.exports = hashGet;


/***/ },
/* 68 */
/***/ function(module, exports, __webpack_require__) {

	var nativeCreate = __webpack_require__(65);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * Checks if a hash value for `key` exists.
	 *
	 * @private
	 * @name has
	 * @memberOf Hash
	 * @param {string} key The key of the entry to check.
	 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	 */
	function hashHas(key) {
	  var data = this.__data__;
	  return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
	}

	module.exports = hashHas;


/***/ },
/* 69 */
/***/ function(module, exports, __webpack_require__) {

	var nativeCreate = __webpack_require__(65);

	/** Used to stand-in for `undefined` hash values. */
	var HASH_UNDEFINED = '__lodash_hash_undefined__';

	/**
	 * Sets the hash `key` to `value`.
	 *
	 * @private
	 * @name set
	 * @memberOf Hash
	 * @param {string} key The key of the value to set.
	 * @param {*} value The value to set.
	 * @returns {Object} Returns the hash instance.
	 */
	function hashSet(key, value) {
	  var data = this.__data__;
	  this.size += this.has(key) ? 0 : 1;
	  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
	  return this;
	}

	module.exports = hashSet;


/***/ },
/* 70 */
/***/ function(module, exports, __webpack_require__) {

	var getMapData = __webpack_require__(71);

	/**
	 * Removes `key` and its value from the map.
	 *
	 * @private
	 * @name delete
	 * @memberOf MapCache
	 * @param {string} key The key of the value to remove.
	 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
	 */
	function mapCacheDelete(key) {
	  var result = getMapData(this, key)['delete'](key);
	  this.size -= result ? 1 : 0;
	  return result;
	}

	module.exports = mapCacheDelete;


/***/ },
/* 71 */
/***/ function(module, exports, __webpack_require__) {

	var isKeyable = __webpack_require__(72);

	/**
	 * Gets the data for `map`.
	 *
	 * @private
	 * @param {Object} map The map to query.
	 * @param {string} key The reference key.
	 * @returns {*} Returns the map data.
	 */
	function getMapData(map, key) {
	  var data = map.__data__;
	  return isKeyable(key)
	    ? data[typeof key == 'string' ? 'string' : 'hash']
	    : data.map;
	}

	module.exports = getMapData;


/***/ },
/* 72 */
/***/ function(module, exports) {

	/**
	 * Checks if `value` is suitable for use as unique object key.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
	 */
	function isKeyable(value) {
	  var type = typeof value;
	  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
	    ? (value !== '__proto__')
	    : (value === null);
	}

	module.exports = isKeyable;


/***/ },
/* 73 */
/***/ function(module, exports, __webpack_require__) {

	var getMapData = __webpack_require__(71);

	/**
	 * Gets the map value for `key`.
	 *
	 * @private
	 * @name get
	 * @memberOf MapCache
	 * @param {string} key The key of the value to get.
	 * @returns {*} Returns the entry value.
	 */
	function mapCacheGet(key) {
	  return getMapData(this, key).get(key);
	}

	module.exports = mapCacheGet;


/***/ },
/* 74 */
/***/ function(module, exports, __webpack_require__) {

	var getMapData = __webpack_require__(71);

	/**
	 * Checks if a map value for `key` exists.
	 *
	 * @private
	 * @name has
	 * @memberOf MapCache
	 * @param {string} key The key of the entry to check.
	 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	 */
	function mapCacheHas(key) {
	  return getMapData(this, key).has(key);
	}

	module.exports = mapCacheHas;


/***/ },
/* 75 */
/***/ function(module, exports, __webpack_require__) {

	var getMapData = __webpack_require__(71);

	/**
	 * Sets the map `key` to `value`.
	 *
	 * @private
	 * @name set
	 * @memberOf MapCache
	 * @param {string} key The key of the value to set.
	 * @param {*} value The value to set.
	 * @returns {Object} Returns the map cache instance.
	 */
	function mapCacheSet(key, value) {
	  var data = getMapData(this, key),
	      size = data.size;

	  data.set(key, value);
	  this.size += data.size == size ? 0 : 1;
	  return this;
	}

	module.exports = mapCacheSet;


/***/ },
/* 76 */
/***/ function(module, exports, __webpack_require__) {

	var baseIsEqualDeep = __webpack_require__(77),
	    isObjectLike = __webpack_require__(18);

	/**
	 * The base implementation of `_.isEqual` which supports partial comparisons
	 * and tracks traversed objects.
	 *
	 * @private
	 * @param {*} value The value to compare.
	 * @param {*} other The other value to compare.
	 * @param {boolean} bitmask The bitmask flags.
	 *  1 - Unordered comparison
	 *  2 - Partial comparison
	 * @param {Function} [customizer] The function to customize comparisons.
	 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
	 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
	 */
	function baseIsEqual(value, other, bitmask, customizer, stack) {
	  if (value === other) {
	    return true;
	  }
	  if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
	    return value !== value && other !== other;
	  }
	  return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
	}

	module.exports = baseIsEqual;


/***/ },
/* 77 */
/***/ function(module, exports, __webpack_require__) {

	var Stack = __webpack_require__(40),
	    equalArrays = __webpack_require__(78),
	    equalByTag = __webpack_require__(84),
	    equalObjects = __webpack_require__(88),
	    getTag = __webpack_require__(95),
	    isArray = __webpack_require__(19),
	    isBuffer = __webpack_require__(20),
	    isTypedArray = __webpack_require__(24);

	/** Used to compose bitmasks for value comparisons. */
	var COMPARE_PARTIAL_FLAG = 1;

	/** `Object#toString` result references. */
	var argsTag = '[object Arguments]',
	    arrayTag = '[object Array]',
	    objectTag = '[object Object]';

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * A specialized version of `baseIsEqual` for arrays and objects which performs
	 * deep comparisons and tracks traversed objects enabling objects with circular
	 * references to be compared.
	 *
	 * @private
	 * @param {Object} object The object to compare.
	 * @param {Object} other The other object to compare.
	 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
	 * @param {Function} customizer The function to customize comparisons.
	 * @param {Function} equalFunc The function to determine equivalents of values.
	 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
	 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
	 */
	function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
	  var objIsArr = isArray(object),
	      othIsArr = isArray(other),
	      objTag = objIsArr ? arrayTag : getTag(object),
	      othTag = othIsArr ? arrayTag : getTag(other);

	  objTag = objTag == argsTag ? objectTag : objTag;
	  othTag = othTag == argsTag ? objectTag : othTag;

	  var objIsObj = objTag == objectTag,
	      othIsObj = othTag == objectTag,
	      isSameTag = objTag == othTag;

	  if (isSameTag && isBuffer(object)) {
	    if (!isBuffer(other)) {
	      return false;
	    }
	    objIsArr = true;
	    objIsObj = false;
	  }
	  if (isSameTag && !objIsObj) {
	    stack || (stack = new Stack);
	    return (objIsArr || isTypedArray(object))
	      ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
	      : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
	  }
	  if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
	    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
	        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

	    if (objIsWrapped || othIsWrapped) {
	      var objUnwrapped = objIsWrapped ? object.value() : object,
	          othUnwrapped = othIsWrapped ? other.value() : other;

	      stack || (stack = new Stack);
	      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
	    }
	  }
	  if (!isSameTag) {
	    return false;
	  }
	  stack || (stack = new Stack);
	  return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
	}

	module.exports = baseIsEqualDeep;


/***/ },
/* 78 */
/***/ function(module, exports, __webpack_require__) {

	var SetCache = __webpack_require__(79),
	    arraySome = __webpack_require__(82),
	    cacheHas = __webpack_require__(83);

	/** Used to compose bitmasks for value comparisons. */
	var COMPARE_PARTIAL_FLAG = 1,
	    COMPARE_UNORDERED_FLAG = 2;

	/**
	 * A specialized version of `baseIsEqualDeep` for arrays with support for
	 * partial deep comparisons.
	 *
	 * @private
	 * @param {Array} array The array to compare.
	 * @param {Array} other The other array to compare.
	 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
	 * @param {Function} customizer The function to customize comparisons.
	 * @param {Function} equalFunc The function to determine equivalents of values.
	 * @param {Object} stack Tracks traversed `array` and `other` objects.
	 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
	 */
	function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
	  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
	      arrLength = array.length,
	      othLength = other.length;

	  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
	    return false;
	  }
	  // Assume cyclic values are equal.
	  var stacked = stack.get(array);
	  if (stacked && stack.get(other)) {
	    return stacked == other;
	  }
	  var index = -1,
	      result = true,
	      seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;

	  stack.set(array, other);
	  stack.set(other, array);

	  // Ignore non-index properties.
	  while (++index < arrLength) {
	    var arrValue = array[index],
	        othValue = other[index];

	    if (customizer) {
	      var compared = isPartial
	        ? customizer(othValue, arrValue, index, other, array, stack)
	        : customizer(arrValue, othValue, index, array, other, stack);
	    }
	    if (compared !== undefined) {
	      if (compared) {
	        continue;
	      }
	      result = false;
	      break;
	    }
	    // Recursively compare arrays (susceptible to call stack limits).
	    if (seen) {
	      if (!arraySome(other, function(othValue, othIndex) {
	            if (!cacheHas(seen, othIndex) &&
	                (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
	              return seen.push(othIndex);
	            }
	          })) {
	        result = false;
	        break;
	      }
	    } else if (!(
	          arrValue === othValue ||
	            equalFunc(arrValue, othValue, bitmask, customizer, stack)
	        )) {
	      result = false;
	      break;
	    }
	  }
	  stack['delete'](array);
	  stack['delete'](other);
	  return result;
	}

	module.exports = equalArrays;


/***/ },
/* 79 */
/***/ function(module, exports, __webpack_require__) {

	var MapCache = __webpack_require__(61),
	    setCacheAdd = __webpack_require__(80),
	    setCacheHas = __webpack_require__(81);

	/**
	 *
	 * Creates an array cache object to store unique values.
	 *
	 * @private
	 * @constructor
	 * @param {Array} [values] The values to cache.
	 */
	function SetCache(values) {
	  var index = -1,
	      length = values == null ? 0 : values.length;

	  this.__data__ = new MapCache;
	  while (++index < length) {
	    this.add(values[index]);
	  }
	}

	// Add methods to `SetCache`.
	SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
	SetCache.prototype.has = setCacheHas;

	module.exports = SetCache;


/***/ },
/* 80 */
/***/ function(module, exports) {

	/** Used to stand-in for `undefined` hash values. */
	var HASH_UNDEFINED = '__lodash_hash_undefined__';

	/**
	 * Adds `value` to the array cache.
	 *
	 * @private
	 * @name add
	 * @memberOf SetCache
	 * @alias push
	 * @param {*} value The value to cache.
	 * @returns {Object} Returns the cache instance.
	 */
	function setCacheAdd(value) {
	  this.__data__.set(value, HASH_UNDEFINED);
	  return this;
	}

	module.exports = setCacheAdd;


/***/ },
/* 81 */
/***/ function(module, exports) {

	/**
	 * Checks if `value` is in the array cache.
	 *
	 * @private
	 * @name has
	 * @memberOf SetCache
	 * @param {*} value The value to search for.
	 * @returns {number} Returns `true` if `value` is found, else `false`.
	 */
	function setCacheHas(value) {
	  return this.__data__.has(value);
	}

	module.exports = setCacheHas;


/***/ },
/* 82 */
/***/ function(module, exports) {

	/**
	 * A specialized version of `_.some` for arrays without support for iteratee
	 * shorthands.
	 *
	 * @private
	 * @param {Array} [array] The array to iterate over.
	 * @param {Function} predicate The function invoked per iteration.
	 * @returns {boolean} Returns `true` if any element passes the predicate check,
	 *  else `false`.
	 */
	function arraySome(array, predicate) {
	  var index = -1,
	      length = array == null ? 0 : array.length;

	  while (++index < length) {
	    if (predicate(array[index], index, array)) {
	      return true;
	    }
	  }
	  return false;
	}

	module.exports = arraySome;


/***/ },
/* 83 */
/***/ function(module, exports) {

	/**
	 * Checks if a `cache` value for `key` exists.
	 *
	 * @private
	 * @param {Object} cache The cache to query.
	 * @param {string} key The key of the entry to check.
	 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
	 */
	function cacheHas(cache, key) {
	  return cache.has(key);
	}

	module.exports = cacheHas;


/***/ },
/* 84 */
/***/ function(module, exports, __webpack_require__) {

	var Symbol = __webpack_require__(13),
	    Uint8Array = __webpack_require__(85),
	    eq = __webpack_require__(45),
	    equalArrays = __webpack_require__(78),
	    mapToArray = __webpack_require__(86),
	    setToArray = __webpack_require__(87);

	/** Used to compose bitmasks for value comparisons. */
	var COMPARE_PARTIAL_FLAG = 1,
	    COMPARE_UNORDERED_FLAG = 2;

	/** `Object#toString` result references. */
	var boolTag = '[object Boolean]',
	    dateTag = '[object Date]',
	    errorTag = '[object Error]',
	    mapTag = '[object Map]',
	    numberTag = '[object Number]',
	    regexpTag = '[object RegExp]',
	    setTag = '[object Set]',
	    stringTag = '[object String]',
	    symbolTag = '[object Symbol]';

	var arrayBufferTag = '[object ArrayBuffer]',
	    dataViewTag = '[object DataView]';

	/** Used to convert symbols to primitives and strings. */
	var symbolProto = Symbol ? Symbol.prototype : undefined,
	    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

	/**
	 * A specialized version of `baseIsEqualDeep` for comparing objects of
	 * the same `toStringTag`.
	 *
	 * **Note:** This function only supports comparing values with tags of
	 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
	 *
	 * @private
	 * @param {Object} object The object to compare.
	 * @param {Object} other The other object to compare.
	 * @param {string} tag The `toStringTag` of the objects to compare.
	 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
	 * @param {Function} customizer The function to customize comparisons.
	 * @param {Function} equalFunc The function to determine equivalents of values.
	 * @param {Object} stack Tracks traversed `object` and `other` objects.
	 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
	 */
	function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
	  switch (tag) {
	    case dataViewTag:
	      if ((object.byteLength != other.byteLength) ||
	          (object.byteOffset != other.byteOffset)) {
	        return false;
	      }
	      object = object.buffer;
	      other = other.buffer;

	    case arrayBufferTag:
	      if ((object.byteLength != other.byteLength) ||
	          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
	        return false;
	      }
	      return true;

	    case boolTag:
	    case dateTag:
	    case numberTag:
	      // Coerce booleans to `1` or `0` and dates to milliseconds.
	      // Invalid dates are coerced to `NaN`.
	      return eq(+object, +other);

	    case errorTag:
	      return object.name == other.name && object.message == other.message;

	    case regexpTag:
	    case stringTag:
	      // Coerce regexes to strings and treat strings, primitives and objects,
	      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
	      // for more details.
	      return object == (other + '');

	    case mapTag:
	      var convert = mapToArray;

	    case setTag:
	      var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
	      convert || (convert = setToArray);

	      if (object.size != other.size && !isPartial) {
	        return false;
	      }
	      // Assume cyclic values are equal.
	      var stacked = stack.get(object);
	      if (stacked) {
	        return stacked == other;
	      }
	      bitmask |= COMPARE_UNORDERED_FLAG;

	      // Recursively compare objects (susceptible to call stack limits).
	      stack.set(object, other);
	      var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
	      stack['delete'](object);
	      return result;

	    case symbolTag:
	      if (symbolValueOf) {
	        return symbolValueOf.call(object) == symbolValueOf.call(other);
	      }
	  }
	  return false;
	}

	module.exports = equalByTag;


/***/ },
/* 85 */
/***/ function(module, exports, __webpack_require__) {

	var root = __webpack_require__(14);

	/** Built-in value references. */
	var Uint8Array = root.Uint8Array;

	module.exports = Uint8Array;


/***/ },
/* 86 */
/***/ function(module, exports) {

	/**
	 * Converts `map` to its key-value pairs.
	 *
	 * @private
	 * @param {Object} map The map to convert.
	 * @returns {Array} Returns the key-value pairs.
	 */
	function mapToArray(map) {
	  var index = -1,
	      result = Array(map.size);

	  map.forEach(function(value, key) {
	    result[++index] = [key, value];
	  });
	  return result;
	}

	module.exports = mapToArray;


/***/ },
/* 87 */
/***/ function(module, exports) {

	/**
	 * Converts `set` to an array of its values.
	 *
	 * @private
	 * @param {Object} set The set to convert.
	 * @returns {Array} Returns the values.
	 */
	function setToArray(set) {
	  var index = -1,
	      result = Array(set.size);

	  set.forEach(function(value) {
	    result[++index] = value;
	  });
	  return result;
	}

	module.exports = setToArray;


/***/ },
/* 88 */
/***/ function(module, exports, __webpack_require__) {

	var getAllKeys = __webpack_require__(89);

	/** Used to compose bitmasks for value comparisons. */
	var COMPARE_PARTIAL_FLAG = 1;

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * A specialized version of `baseIsEqualDeep` for objects with support for
	 * partial deep comparisons.
	 *
	 * @private
	 * @param {Object} object The object to compare.
	 * @param {Object} other The other object to compare.
	 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
	 * @param {Function} customizer The function to customize comparisons.
	 * @param {Function} equalFunc The function to determine equivalents of values.
	 * @param {Object} stack Tracks traversed `object` and `other` objects.
	 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
	 */
	function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
	  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
	      objProps = getAllKeys(object),
	      objLength = objProps.length,
	      othProps = getAllKeys(other),
	      othLength = othProps.length;

	  if (objLength != othLength && !isPartial) {
	    return false;
	  }
	  var index = objLength;
	  while (index--) {
	    var key = objProps[index];
	    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
	      return false;
	    }
	  }
	  // Assume cyclic values are equal.
	  var stacked = stack.get(object);
	  if (stacked && stack.get(other)) {
	    return stacked == other;
	  }
	  var result = true;
	  stack.set(object, other);
	  stack.set(other, object);

	  var skipCtor = isPartial;
	  while (++index < objLength) {
	    key = objProps[index];
	    var objValue = object[key],
	        othValue = other[key];

	    if (customizer) {
	      var compared = isPartial
	        ? customizer(othValue, objValue, key, other, object, stack)
	        : customizer(objValue, othValue, key, object, other, stack);
	    }
	    // Recursively compare objects (susceptible to call stack limits).
	    if (!(compared === undefined
	          ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
	          : compared
	        )) {
	      result = false;
	      break;
	    }
	    skipCtor || (skipCtor = key == 'constructor');
	  }
	  if (result && !skipCtor) {
	    var objCtor = object.constructor,
	        othCtor = other.constructor;

	    // Non `Object` object instances with different constructors are not equal.
	    if (objCtor != othCtor &&
	        ('constructor' in object && 'constructor' in other) &&
	        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
	          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
	      result = false;
	    }
	  }
	  stack['delete'](object);
	  stack['delete'](other);
	  return result;
	}

	module.exports = equalObjects;


/***/ },
/* 89 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetAllKeys = __webpack_require__(90),
	    getSymbols = __webpack_require__(92),
	    keys = __webpack_require__(7);

	/**
	 * Creates an array of own enumerable property names and symbols of `object`.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of property names and symbols.
	 */
	function getAllKeys(object) {
	  return baseGetAllKeys(object, keys, getSymbols);
	}

	module.exports = getAllKeys;


/***/ },
/* 90 */
/***/ function(module, exports, __webpack_require__) {

	var arrayPush = __webpack_require__(91),
	    isArray = __webpack_require__(19);

	/**
	 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
	 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
	 * symbols of `object`.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @param {Function} keysFunc The function to get the keys of `object`.
	 * @param {Function} symbolsFunc The function to get the symbols of `object`.
	 * @returns {Array} Returns the array of property names and symbols.
	 */
	function baseGetAllKeys(object, keysFunc, symbolsFunc) {
	  var result = keysFunc(object);
	  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
	}

	module.exports = baseGetAllKeys;


/***/ },
/* 91 */
/***/ function(module, exports) {

	/**
	 * Appends the elements of `values` to `array`.
	 *
	 * @private
	 * @param {Array} array The array to modify.
	 * @param {Array} values The values to append.
	 * @returns {Array} Returns `array`.
	 */
	function arrayPush(array, values) {
	  var index = -1,
	      length = values.length,
	      offset = array.length;

	  while (++index < length) {
	    array[offset + index] = values[index];
	  }
	  return array;
	}

	module.exports = arrayPush;


/***/ },
/* 92 */
/***/ function(module, exports, __webpack_require__) {

	var arrayFilter = __webpack_require__(93),
	    stubArray = __webpack_require__(94);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Built-in value references. */
	var propertyIsEnumerable = objectProto.propertyIsEnumerable;

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeGetSymbols = Object.getOwnPropertySymbols;

	/**
	 * Creates an array of the own enumerable symbols of `object`.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of symbols.
	 */
	var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
	  if (object == null) {
	    return [];
	  }
	  object = Object(object);
	  return arrayFilter(nativeGetSymbols(object), function(symbol) {
	    return propertyIsEnumerable.call(object, symbol);
	  });
	};

	module.exports = getSymbols;


/***/ },
/* 93 */
/***/ function(module, exports) {

	/**
	 * A specialized version of `_.filter` for arrays without support for
	 * iteratee shorthands.
	 *
	 * @private
	 * @param {Array} [array] The array to iterate over.
	 * @param {Function} predicate The function invoked per iteration.
	 * @returns {Array} Returns the new filtered array.
	 */
	function arrayFilter(array, predicate) {
	  var index = -1,
	      length = array == null ? 0 : array.length,
	      resIndex = 0,
	      result = [];

	  while (++index < length) {
	    var value = array[index];
	    if (predicate(value, index, array)) {
	      result[resIndex++] = value;
	    }
	  }
	  return result;
	}

	module.exports = arrayFilter;


/***/ },
/* 94 */
/***/ function(module, exports) {

	/**
	 * This method returns a new empty array.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.13.0
	 * @category Util
	 * @returns {Array} Returns the new empty array.
	 * @example
	 *
	 * var arrays = _.times(2, _.stubArray);
	 *
	 * console.log(arrays);
	 * // => [[], []]
	 *
	 * console.log(arrays[0] === arrays[1]);
	 * // => false
	 */
	function stubArray() {
	  return [];
	}

	module.exports = stubArray;


/***/ },
/* 95 */
/***/ function(module, exports, __webpack_require__) {

	var DataView = __webpack_require__(96),
	    Map = __webpack_require__(54),
	    Promise = __webpack_require__(97),
	    Set = __webpack_require__(98),
	    WeakMap = __webpack_require__(99),
	    baseGetTag = __webpack_require__(12),
	    toSource = __webpack_require__(59);

	/** `Object#toString` result references. */
	var mapTag = '[object Map]',
	    objectTag = '[object Object]',
	    promiseTag = '[object Promise]',
	    setTag = '[object Set]',
	    weakMapTag = '[object WeakMap]';

	var dataViewTag = '[object DataView]';

	/** Used to detect maps, sets, and weakmaps. */
	var dataViewCtorString = toSource(DataView),
	    mapCtorString = toSource(Map),
	    promiseCtorString = toSource(Promise),
	    setCtorString = toSource(Set),
	    weakMapCtorString = toSource(WeakMap);

	/**
	 * Gets the `toStringTag` of `value`.
	 *
	 * @private
	 * @param {*} value The value to query.
	 * @returns {string} Returns the `toStringTag`.
	 */
	var getTag = baseGetTag;

	// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
	if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
	    (Map && getTag(new Map) != mapTag) ||
	    (Promise && getTag(Promise.resolve()) != promiseTag) ||
	    (Set && getTag(new Set) != setTag) ||
	    (WeakMap && getTag(new WeakMap) != weakMapTag)) {
	  getTag = function(value) {
	    var result = baseGetTag(value),
	        Ctor = result == objectTag ? value.constructor : undefined,
	        ctorString = Ctor ? toSource(Ctor) : '';

	    if (ctorString) {
	      switch (ctorString) {
	        case dataViewCtorString: return dataViewTag;
	        case mapCtorString: return mapTag;
	        case promiseCtorString: return promiseTag;
	        case setCtorString: return setTag;
	        case weakMapCtorString: return weakMapTag;
	      }
	    }
	    return result;
	  };
	}

	module.exports = getTag;


/***/ },
/* 96 */
/***/ function(module, exports, __webpack_require__) {

	var getNative = __webpack_require__(55),
	    root = __webpack_require__(14);

	/* Built-in method references that are verified to be native. */
	var DataView = getNative(root, 'DataView');

	module.exports = DataView;


/***/ },
/* 97 */
/***/ function(module, exports, __webpack_require__) {

	var getNative = __webpack_require__(55),
	    root = __webpack_require__(14);

	/* Built-in method references that are verified to be native. */
	var Promise = getNative(root, 'Promise');

	module.exports = Promise;


/***/ },
/* 98 */
/***/ function(module, exports, __webpack_require__) {

	var getNative = __webpack_require__(55),
	    root = __webpack_require__(14);

	/* Built-in method references that are verified to be native. */
	var Set = getNative(root, 'Set');

	module.exports = Set;


/***/ },
/* 99 */
/***/ function(module, exports, __webpack_require__) {

	var getNative = __webpack_require__(55),
	    root = __webpack_require__(14);

	/* Built-in method references that are verified to be native. */
	var WeakMap = getNative(root, 'WeakMap');

	module.exports = WeakMap;


/***/ },
/* 100 */
/***/ function(module, exports, __webpack_require__) {

	var isStrictComparable = __webpack_require__(101),
	    keys = __webpack_require__(7);

	/**
	 * Gets the property names, values, and compare flags of `object`.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the match data of `object`.
	 */
	function getMatchData(object) {
	  var result = keys(object),
	      length = result.length;

	  while (length--) {
	    var key = result[length],
	        value = object[key];

	    result[length] = [key, value, isStrictComparable(value)];
	  }
	  return result;
	}

	module.exports = getMatchData;


/***/ },
/* 101 */
/***/ function(module, exports, __webpack_require__) {

	var isObject = __webpack_require__(35);

	/**
	 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` if suitable for strict
	 *  equality comparisons, else `false`.
	 */
	function isStrictComparable(value) {
	  return value === value && !isObject(value);
	}

	module.exports = isStrictComparable;


/***/ },
/* 102 */
/***/ function(module, exports) {

	/**
	 * A specialized version of `matchesProperty` for source values suitable
	 * for strict equality comparisons, i.e. `===`.
	 *
	 * @private
	 * @param {string} key The key of the property to get.
	 * @param {*} srcValue The value to match.
	 * @returns {Function} Returns the new spec function.
	 */
	function matchesStrictComparable(key, srcValue) {
	  return function(object) {
	    if (object == null) {
	      return false;
	    }
	    return object[key] === srcValue &&
	      (srcValue !== undefined || (key in Object(object)));
	  };
	}

	module.exports = matchesStrictComparable;


/***/ },
/* 103 */
/***/ function(module, exports, __webpack_require__) {

	var baseIsEqual = __webpack_require__(76),
	    get = __webpack_require__(104),
	    hasIn = __webpack_require__(116),
	    isKey = __webpack_require__(107),
	    isStrictComparable = __webpack_require__(101),
	    matchesStrictComparable = __webpack_require__(102),
	    toKey = __webpack_require__(115);

	/** Used to compose bitmasks for value comparisons. */
	var COMPARE_PARTIAL_FLAG = 1,
	    COMPARE_UNORDERED_FLAG = 2;

	/**
	 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
	 *
	 * @private
	 * @param {string} path The path of the property to get.
	 * @param {*} srcValue The value to match.
	 * @returns {Function} Returns the new spec function.
	 */
	function baseMatchesProperty(path, srcValue) {
	  if (isKey(path) && isStrictComparable(srcValue)) {
	    return matchesStrictComparable(toKey(path), srcValue);
	  }
	  return function(object) {
	    var objValue = get(object, path);
	    return (objValue === undefined && objValue === srcValue)
	      ? hasIn(object, path)
	      : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
	  };
	}

	module.exports = baseMatchesProperty;


/***/ },
/* 104 */
/***/ function(module, exports, __webpack_require__) {

	var baseGet = __webpack_require__(105);

	/**
	 * Gets the value at `path` of `object`. If the resolved value is
	 * `undefined`, the `defaultValue` is returned in its place.
	 *
	 * @static
	 * @memberOf _
	 * @since 3.7.0
	 * @category Object
	 * @param {Object} object The object to query.
	 * @param {Array|string} path The path of the property to get.
	 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
	 * @returns {*} Returns the resolved value.
	 * @example
	 *
	 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
	 *
	 * _.get(object, 'a[0].b.c');
	 * // => 3
	 *
	 * _.get(object, ['a', '0', 'b', 'c']);
	 * // => 3
	 *
	 * _.get(object, 'a.b.c', 'default');
	 * // => 'default'
	 */
	function get(object, path, defaultValue) {
	  var result = object == null ? undefined : baseGet(object, path);
	  return result === undefined ? defaultValue : result;
	}

	module.exports = get;


/***/ },
/* 105 */
/***/ function(module, exports, __webpack_require__) {

	var castPath = __webpack_require__(106),
	    toKey = __webpack_require__(115);

	/**
	 * The base implementation of `_.get` without support for default values.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @param {Array|string} path The path of the property to get.
	 * @returns {*} Returns the resolved value.
	 */
	function baseGet(object, path) {
	  path = castPath(path, object);

	  var index = 0,
	      length = path.length;

	  while (object != null && index < length) {
	    object = object[toKey(path[index++])];
	  }
	  return (index && index == length) ? object : undefined;
	}

	module.exports = baseGet;


/***/ },
/* 106 */
/***/ function(module, exports, __webpack_require__) {

	var isArray = __webpack_require__(19),
	    isKey = __webpack_require__(107),
	    stringToPath = __webpack_require__(109),
	    toString = __webpack_require__(112);

	/**
	 * Casts `value` to a path array if it's not one.
	 *
	 * @private
	 * @param {*} value The value to inspect.
	 * @param {Object} [object] The object to query keys on.
	 * @returns {Array} Returns the cast property path array.
	 */
	function castPath(value, object) {
	  if (isArray(value)) {
	    return value;
	  }
	  return isKey(value, object) ? [value] : stringToPath(toString(value));
	}

	module.exports = castPath;


/***/ },
/* 107 */
/***/ function(module, exports, __webpack_require__) {

	var isArray = __webpack_require__(19),
	    isSymbol = __webpack_require__(108);

	/** Used to match property names within property paths. */
	var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
	    reIsPlainProp = /^\w*$/;

	/**
	 * Checks if `value` is a property name and not a property path.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @param {Object} [object] The object to query keys on.
	 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
	 */
	function isKey(value, object) {
	  if (isArray(value)) {
	    return false;
	  }
	  var type = typeof value;
	  if (type == 'number' || type == 'symbol' || type == 'boolean' ||
	      value == null || isSymbol(value)) {
	    return true;
	  }
	  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
	    (object != null && value in Object(object));
	}

	module.exports = isKey;


/***/ },
/* 108 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetTag = __webpack_require__(12),
	    isObjectLike = __webpack_require__(18);

	/** `Object#toString` result references. */
	var symbolTag = '[object Symbol]';

	/**
	 * Checks if `value` is classified as a `Symbol` primitive or object.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
	 * @example
	 *
	 * _.isSymbol(Symbol.iterator);
	 * // => true
	 *
	 * _.isSymbol('abc');
	 * // => false
	 */
	function isSymbol(value) {
	  return typeof value == 'symbol' ||
	    (isObjectLike(value) && baseGetTag(value) == symbolTag);
	}

	module.exports = isSymbol;


/***/ },
/* 109 */
/***/ function(module, exports, __webpack_require__) {

	var memoizeCapped = __webpack_require__(110);

	/** Used to match property names within property paths. */
	var reLeadingDot = /^\./,
	    rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

	/** Used to match backslashes in property paths. */
	var reEscapeChar = /\\(\\)?/g;

	/**
	 * Converts `string` to a property path array.
	 *
	 * @private
	 * @param {string} string The string to convert.
	 * @returns {Array} Returns the property path array.
	 */
	var stringToPath = memoizeCapped(function(string) {
	  var result = [];
	  if (reLeadingDot.test(string)) {
	    result.push('');
	  }
	  string.replace(rePropName, function(match, number, quote, string) {
	    result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
	  });
	  return result;
	});

	module.exports = stringToPath;


/***/ },
/* 110 */
/***/ function(module, exports, __webpack_require__) {

	var memoize = __webpack_require__(111);

	/** Used as the maximum memoize cache size. */
	var MAX_MEMOIZE_SIZE = 500;

	/**
	 * A specialized version of `_.memoize` which clears the memoized function's
	 * cache when it exceeds `MAX_MEMOIZE_SIZE`.
	 *
	 * @private
	 * @param {Function} func The function to have its output memoized.
	 * @returns {Function} Returns the new memoized function.
	 */
	function memoizeCapped(func) {
	  var result = memoize(func, function(key) {
	    if (cache.size === MAX_MEMOIZE_SIZE) {
	      cache.clear();
	    }
	    return key;
	  });

	  var cache = result.cache;
	  return result;
	}

	module.exports = memoizeCapped;


/***/ },
/* 111 */
/***/ function(module, exports, __webpack_require__) {

	var MapCache = __webpack_require__(61);

	/** Error message constants. */
	var FUNC_ERROR_TEXT = 'Expected a function';

	/**
	 * Creates a function that memoizes the result of `func`. If `resolver` is
	 * provided, it determines the cache key for storing the result based on the
	 * arguments provided to the memoized function. By default, the first argument
	 * provided to the memoized function is used as the map cache key. The `func`
	 * is invoked with the `this` binding of the memoized function.
	 *
	 * **Note:** The cache is exposed as the `cache` property on the memoized
	 * function. Its creation may be customized by replacing the `_.memoize.Cache`
	 * constructor with one whose instances implement the
	 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
	 * method interface of `clear`, `delete`, `get`, `has`, and `set`.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Function
	 * @param {Function} func The function to have its output memoized.
	 * @param {Function} [resolver] The function to resolve the cache key.
	 * @returns {Function} Returns the new memoized function.
	 * @example
	 *
	 * var object = { 'a': 1, 'b': 2 };
	 * var other = { 'c': 3, 'd': 4 };
	 *
	 * var values = _.memoize(_.values);
	 * values(object);
	 * // => [1, 2]
	 *
	 * values(other);
	 * // => [3, 4]
	 *
	 * object.a = 2;
	 * values(object);
	 * // => [1, 2]
	 *
	 * // Modify the result cache.
	 * values.cache.set(object, ['a', 'b']);
	 * values(object);
	 * // => ['a', 'b']
	 *
	 * // Replace `_.memoize.Cache`.
	 * _.memoize.Cache = WeakMap;
	 */
	function memoize(func, resolver) {
	  if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
	    throw new TypeError(FUNC_ERROR_TEXT);
	  }
	  var memoized = function() {
	    var args = arguments,
	        key = resolver ? resolver.apply(this, args) : args[0],
	        cache = memoized.cache;

	    if (cache.has(key)) {
	      return cache.get(key);
	    }
	    var result = func.apply(this, args);
	    memoized.cache = cache.set(key, result) || cache;
	    return result;
	  };
	  memoized.cache = new (memoize.Cache || MapCache);
	  return memoized;
	}

	// Expose `MapCache`.
	memoize.Cache = MapCache;

	module.exports = memoize;


/***/ },
/* 112 */
/***/ function(module, exports, __webpack_require__) {

	var baseToString = __webpack_require__(113);

	/**
	 * Converts `value` to a string. An empty string is returned for `null`
	 * and `undefined` values. The sign of `-0` is preserved.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to convert.
	 * @returns {string} Returns the converted string.
	 * @example
	 *
	 * _.toString(null);
	 * // => ''
	 *
	 * _.toString(-0);
	 * // => '-0'
	 *
	 * _.toString([1, 2, 3]);
	 * // => '1,2,3'
	 */
	function toString(value) {
	  return value == null ? '' : baseToString(value);
	}

	module.exports = toString;


/***/ },
/* 113 */
/***/ function(module, exports, __webpack_require__) {

	var Symbol = __webpack_require__(13),
	    arrayMap = __webpack_require__(114),
	    isArray = __webpack_require__(19),
	    isSymbol = __webpack_require__(108);

	/** Used as references for various `Number` constants. */
	var INFINITY = 1 / 0;

	/** Used to convert symbols to primitives and strings. */
	var symbolProto = Symbol ? Symbol.prototype : undefined,
	    symbolToString = symbolProto ? symbolProto.toString : undefined;

	/**
	 * The base implementation of `_.toString` which doesn't convert nullish
	 * values to empty strings.
	 *
	 * @private
	 * @param {*} value The value to process.
	 * @returns {string} Returns the string.
	 */
	function baseToString(value) {
	  // Exit early for strings to avoid a performance hit in some environments.
	  if (typeof value == 'string') {
	    return value;
	  }
	  if (isArray(value)) {
	    // Recursively convert values (susceptible to call stack limits).
	    return arrayMap(value, baseToString) + '';
	  }
	  if (isSymbol(value)) {
	    return symbolToString ? symbolToString.call(value) : '';
	  }
	  var result = (value + '');
	  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
	}

	module.exports = baseToString;


/***/ },
/* 114 */
/***/ function(module, exports) {

	/**
	 * A specialized version of `_.map` for arrays without support for iteratee
	 * shorthands.
	 *
	 * @private
	 * @param {Array} [array] The array to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @returns {Array} Returns the new mapped array.
	 */
	function arrayMap(array, iteratee) {
	  var index = -1,
	      length = array == null ? 0 : array.length,
	      result = Array(length);

	  while (++index < length) {
	    result[index] = iteratee(array[index], index, array);
	  }
	  return result;
	}

	module.exports = arrayMap;


/***/ },
/* 115 */
/***/ function(module, exports, __webpack_require__) {

	var isSymbol = __webpack_require__(108);

	/** Used as references for various `Number` constants. */
	var INFINITY = 1 / 0;

	/**
	 * Converts `value` to a string key if it's not a string or symbol.
	 *
	 * @private
	 * @param {*} value The value to inspect.
	 * @returns {string|symbol} Returns the key.
	 */
	function toKey(value) {
	  if (typeof value == 'string' || isSymbol(value)) {
	    return value;
	  }
	  var result = (value + '');
	  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
	}

	module.exports = toKey;


/***/ },
/* 116 */
/***/ function(module, exports, __webpack_require__) {

	var baseHasIn = __webpack_require__(117),
	    hasPath = __webpack_require__(118);

	/**
	 * Checks if `path` is a direct or inherited property of `object`.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Object
	 * @param {Object} object The object to query.
	 * @param {Array|string} path The path to check.
	 * @returns {boolean} Returns `true` if `path` exists, else `false`.
	 * @example
	 *
	 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
	 *
	 * _.hasIn(object, 'a');
	 * // => true
	 *
	 * _.hasIn(object, 'a.b');
	 * // => true
	 *
	 * _.hasIn(object, ['a', 'b']);
	 * // => true
	 *
	 * _.hasIn(object, 'b');
	 * // => false
	 */
	function hasIn(object, path) {
	  return object != null && hasPath(object, path, baseHasIn);
	}

	module.exports = hasIn;


/***/ },
/* 117 */
/***/ function(module, exports) {

	/**
	 * The base implementation of `_.hasIn` without support for deep paths.
	 *
	 * @private
	 * @param {Object} [object] The object to query.
	 * @param {Array|string} key The key to check.
	 * @returns {boolean} Returns `true` if `key` exists, else `false`.
	 */
	function baseHasIn(object, key) {
	  return object != null && key in Object(object);
	}

	module.exports = baseHasIn;


/***/ },
/* 118 */
/***/ function(module, exports, __webpack_require__) {

	var castPath = __webpack_require__(106),
	    isArguments = __webpack_require__(10),
	    isArray = __webpack_require__(19),
	    isIndex = __webpack_require__(23),
	    isLength = __webpack_require__(26),
	    toKey = __webpack_require__(115);

	/**
	 * Checks if `path` exists on `object`.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @param {Array|string} path The path to check.
	 * @param {Function} hasFunc The function to check properties.
	 * @returns {boolean} Returns `true` if `path` exists, else `false`.
	 */
	function hasPath(object, path, hasFunc) {
	  path = castPath(path, object);

	  var index = -1,
	      length = path.length,
	      result = false;

	  while (++index < length) {
	    var key = toKey(path[index]);
	    if (!(result = object != null && hasFunc(object, key))) {
	      break;
	    }
	    object = object[key];
	  }
	  if (result || ++index != length) {
	    return result;
	  }
	  length = object == null ? 0 : object.length;
	  return !!length && isLength(length) && isIndex(key, length) &&
	    (isArray(object) || isArguments(object));
	}

	module.exports = hasPath;


/***/ },
/* 119 */
/***/ function(module, exports) {

	/**
	 * This method returns the first argument it receives.
	 *
	 * @static
	 * @since 0.1.0
	 * @memberOf _
	 * @category Util
	 * @param {*} value Any value.
	 * @returns {*} Returns `value`.
	 * @example
	 *
	 * var object = { 'a': 1 };
	 *
	 * console.log(_.identity(object) === object);
	 * // => true
	 */
	function identity(value) {
	  return value;
	}

	module.exports = identity;


/***/ },
/* 120 */
/***/ function(module, exports, __webpack_require__) {

	var baseProperty = __webpack_require__(121),
	    basePropertyDeep = __webpack_require__(122),
	    isKey = __webpack_require__(107),
	    toKey = __webpack_require__(115);

	/**
	 * Creates a function that returns the value at `path` of a given object.
	 *
	 * @static
	 * @memberOf _
	 * @since 2.4.0
	 * @category Util
	 * @param {Array|string} path The path of the property to get.
	 * @returns {Function} Returns the new accessor function.
	 * @example
	 *
	 * var objects = [
	 *   { 'a': { 'b': 2 } },
	 *   { 'a': { 'b': 1 } }
	 * ];
	 *
	 * _.map(objects, _.property('a.b'));
	 * // => [2, 1]
	 *
	 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
	 * // => [1, 2]
	 */
	function property(path) {
	  return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
	}

	module.exports = property;


/***/ },
/* 121 */
/***/ function(module, exports) {

	/**
	 * The base implementation of `_.property` without support for deep paths.
	 *
	 * @private
	 * @param {string} key The key of the property to get.
	 * @returns {Function} Returns the new accessor function.
	 */
	function baseProperty(key) {
	  return function(object) {
	    return object == null ? undefined : object[key];
	  };
	}

	module.exports = baseProperty;


/***/ },
/* 122 */
/***/ function(module, exports, __webpack_require__) {

	var baseGet = __webpack_require__(105);

	/**
	 * A specialized version of `baseProperty` which supports deep paths.
	 *
	 * @private
	 * @param {Array|string} path The path of the property to get.
	 * @returns {Function} Returns the new accessor function.
	 */
	function basePropertyDeep(path) {
	  return function(object) {
	    return baseGet(object, path);
	  };
	}

	module.exports = basePropertyDeep;


/***/ },
/* 123 */
/***/ function(module, exports) {

	/**
	 * The base implementation of `_.reduce` and `_.reduceRight`, without support
	 * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
	 *
	 * @private
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @param {*} accumulator The initial value.
	 * @param {boolean} initAccum Specify using the first or last element of
	 *  `collection` as the initial value.
	 * @param {Function} eachFunc The function to iterate over `collection`.
	 * @returns {*} Returns the accumulated value.
	 */
	function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
	  eachFunc(collection, function(value, index, collection) {
	    accumulator = initAccum
	      ? (initAccum = false, value)
	      : iteratee(accumulator, value, index, collection);
	  });
	  return accumulator;
	}

	module.exports = baseReduce;


/***/ },
/* 124 */
/***/ function(module, exports, __webpack_require__) {

	var arrayFilter = __webpack_require__(93),
	    baseFilter = __webpack_require__(125),
	    baseIteratee = __webpack_require__(37),
	    isArray = __webpack_require__(19);

	/**
	 * Iterates over elements of `collection`, returning an array of all elements
	 * `predicate` returns truthy for. The predicate is invoked with three
	 * arguments: (value, index|key, collection).
	 *
	 * **Note:** Unlike `_.remove`, this method returns a new array.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Collection
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} [predicate=_.identity] The function invoked per iteration.
	 * @returns {Array} Returns the new filtered array.
	 * @see _.reject
	 * @example
	 *
	 * var users = [
	 *   { 'user': 'barney', 'age': 36, 'active': true },
	 *   { 'user': 'fred',   'age': 40, 'active': false }
	 * ];
	 *
	 * _.filter(users, function(o) { return !o.active; });
	 * // => objects for ['fred']
	 *
	 * // The `_.matches` iteratee shorthand.
	 * _.filter(users, { 'age': 36, 'active': true });
	 * // => objects for ['barney']
	 *
	 * // The `_.matchesProperty` iteratee shorthand.
	 * _.filter(users, ['active', false]);
	 * // => objects for ['fred']
	 *
	 * // The `_.property` iteratee shorthand.
	 * _.filter(users, 'active');
	 * // => objects for ['barney']
	 */
	function filter(collection, predicate) {
	  var func = isArray(collection) ? arrayFilter : baseFilter;
	  return func(collection, baseIteratee(predicate, 3));
	}

	module.exports = filter;


/***/ },
/* 125 */
/***/ function(module, exports, __webpack_require__) {

	var baseEach = __webpack_require__(3);

	/**
	 * The base implementation of `_.filter` without support for iteratee shorthands.
	 *
	 * @private
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} predicate The function invoked per iteration.
	 * @returns {Array} Returns the new filtered array.
	 */
	function baseFilter(collection, predicate) {
	  var result = [];
	  baseEach(collection, function(value, index, collection) {
	    if (predicate(value, index, collection)) {
	      result.push(value);
	    }
	  });
	  return result;
	}

	module.exports = baseFilter;


/***/ },
/* 126 */
/***/ function(module, exports, __webpack_require__) {

	var arrayMap = __webpack_require__(114),
	    baseIteratee = __webpack_require__(37),
	    baseMap = __webpack_require__(127),
	    isArray = __webpack_require__(19);

	/**
	 * Creates an array of values by running each element in `collection` thru
	 * `iteratee`. The iteratee is invoked with three arguments:
	 * (value, index|key, collection).
	 *
	 * Many lodash methods are guarded to work as iteratees for methods like
	 * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
	 *
	 * The guarded methods are:
	 * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
	 * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
	 * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
	 * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Collection
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	 * @returns {Array} Returns the new mapped array.
	 * @example
	 *
	 * function square(n) {
	 *   return n * n;
	 * }
	 *
	 * _.map([4, 8], square);
	 * // => [16, 64]
	 *
	 * _.map({ 'a': 4, 'b': 8 }, square);
	 * // => [16, 64] (iteration order is not guaranteed)
	 *
	 * var users = [
	 *   { 'user': 'barney' },
	 *   { 'user': 'fred' }
	 * ];
	 *
	 * // The `_.property` iteratee shorthand.
	 * _.map(users, 'user');
	 * // => ['barney', 'fred']
	 */
	function map(collection, iteratee) {
	  var func = isArray(collection) ? arrayMap : baseMap;
	  return func(collection, baseIteratee(iteratee, 3));
	}

	module.exports = map;


/***/ },
/* 127 */
/***/ function(module, exports, __webpack_require__) {

	var baseEach = __webpack_require__(3),
	    isArrayLike = __webpack_require__(33);

	/**
	 * The base implementation of `_.map` without support for iteratee shorthands.
	 *
	 * @private
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @returns {Array} Returns the new mapped array.
	 */
	function baseMap(collection, iteratee) {
	  var index = -1,
	      result = isArrayLike(collection) ? Array(collection.length) : [];

	  baseEach(collection, function(value, key, collection) {
	    result[++index] = iteratee(value, key, collection);
	  });
	  return result;
	}

	module.exports = baseMap;


/***/ },
/* 128 */
/***/ function(module, exports, __webpack_require__) {

	var arrayEach = __webpack_require__(129),
	    baseEach = __webpack_require__(3),
	    castFunction = __webpack_require__(130),
	    isArray = __webpack_require__(19);

	/**
	 * Iterates over elements of `collection` and invokes `iteratee` for each element.
	 * The iteratee is invoked with three arguments: (value, index|key, collection).
	 * Iteratee functions may exit iteration early by explicitly returning `false`.
	 *
	 * **Note:** As with other "Collections" methods, objects with a "length"
	 * property are iterated like arrays. To avoid this behavior use `_.forIn`
	 * or `_.forOwn` for object iteration.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @alias each
	 * @category Collection
	 * @param {Array|Object} collection The collection to iterate over.
	 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
	 * @returns {Array|Object} Returns `collection`.
	 * @see _.forEachRight
	 * @example
	 *
	 * _.forEach([1, 2], function(value) {
	 *   console.log(value);
	 * });
	 * // => Logs `1` then `2`.
	 *
	 * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
	 *   console.log(key);
	 * });
	 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
	 */
	function forEach(collection, iteratee) {
	  var func = isArray(collection) ? arrayEach : baseEach;
	  return func(collection, castFunction(iteratee));
	}

	module.exports = forEach;


/***/ },
/* 129 */
/***/ function(module, exports) {

	/**
	 * A specialized version of `_.forEach` for arrays without support for
	 * iteratee shorthands.
	 *
	 * @private
	 * @param {Array} [array] The array to iterate over.
	 * @param {Function} iteratee The function invoked per iteration.
	 * @returns {Array} Returns `array`.
	 */
	function arrayEach(array, iteratee) {
	  var index = -1,
	      length = array == null ? 0 : array.length;

	  while (++index < length) {
	    if (iteratee(array[index], index, array) === false) {
	      break;
	    }
	  }
	  return array;
	}

	module.exports = arrayEach;


/***/ },
/* 130 */
/***/ function(module, exports, __webpack_require__) {

	var identity = __webpack_require__(119);

	/**
	 * Casts `value` to `identity` if it's not a function.
	 *
	 * @private
	 * @param {*} value The value to inspect.
	 * @returns {Function} Returns cast function.
	 */
	function castFunction(value) {
	  return typeof value == 'function' ? value : identity;
	}

	module.exports = castFunction;


/***/ },
/* 131 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * The Helicase enzyme in real life breaks the double helix and separates the DNA strands.
	 * This module picks the user properties collection and the features collection and break them apart into two strands of
	 * names.
	 */

	var chemicalReactions = __webpack_require__(132);

	module.exports = {
	    /**
	     * Returns an object containing two strands: one containing the user properties names and the other containing
	     * the features names.
	     *
	     * @param userProperties a dictionary with user properties
	     * @param feature a dictionary with features instructions
	     * @returns An object that contains user property names and features names
	     */
	    breakProperties: function (userProperties, feature) {
	        return chemicalReactions.separateProperties(userProperties, feature);
	    }
	};


/***/ },
/* 132 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * This module contains multiple chemical reactions for use freely.
	 */
	var keys = __webpack_require__(7);

	module.exports = {
	    separateProperties: function (userProperties, feature) {
	        return {
	            userPropertyNames: keys(userProperties),
	            featurePropertyNames: keys(feature)
	        };
	    }
	};


/***/ },
/* 133 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * The Primase enzyme in real life prepares the strand for the replication, this is called the primer.
	 * This module takes the user properties and feature properties strands, analyses it and returns a primer object
	 * containing instructions regarding the features to activate or deactivate.
	 */
	var get = __webpack_require__(104);
	var pick = __webpack_require__(134);
	var merge = __webpack_require__(151);
	var has = __webpack_require__(172);
	var isUndefined = __webpack_require__(174);
	var includes = __webpack_require__(175);

	var chemicalReactions = __webpack_require__(132);
	var matchReading = __webpack_require__(186);

	function getFeatureProperties(feature) {
	    return pick(feature, ['toggle', 'throttle', 'buckets']);
	}

	function mergeProperties(primer, feature) {
	    var properties = getFeatureProperties(feature);
	    merge(primer, properties);
	}

	function isFeatureDisabled(primer, root) {
	    var toggle = get(primer, 'toggle');
	    return root && toggle === false;
	}

	function containsFeatureProperties(obj) {
	    return has(obj, 'toggle') || has(obj, 'throttle') || has(obj, 'buckets');
	}

	function pickMatchedProperties(childProperties, parentProperties) {
	    return !isUndefined(childProperties) ? childProperties : parentProperties;
	}

	function getPropertiesNode(userProperties, featurePropertyName, feature) {
	    // Explode the current node to check if there are properties
	    var featureProperty = feature[featurePropertyName];

	    var userPropertyValue = userProperties[featurePropertyName];
	    var properties = matchReading.getMatchedProperties(userPropertyValue, featureProperty);

	    return pickMatchedProperties(properties, featureProperty);
	}

	function bindPrimer(primerInstructions, childPrimer) {
	    merge(primerInstructions, childPrimer);
	}

	module.exports = {
	    /**
	     * Returns a primer collection containing instructions to toggle on or off a feature,
	     * matched against the user properties.
	     *
	     * @param userProperties The user properties to match the features
	     * @param feature The feature being processed
	     * @param propertyStrands An object with the strands containing user and features properties names
	     * @param root A flag to indicate if the features tree is being processed in the root
	     * @returns A collection of primer instructions matched against the user properties
	     */
	    preparePrimer: function(userProperties, feature, propertyStrands, root) {
	        var self = this;
	        var primerInstructions = {};

	        var userPropertyNames = propertyStrands.userPropertyNames;
	        var featurePropertyNames = propertyStrands.featurePropertyNames;

	        // If are feature properties on the current node, it merges with the final result
	        if (containsFeatureProperties(feature)) {
	            mergeProperties(primerInstructions, feature);
	        }

	        if (!isFeatureDisabled(primerInstructions, root)) {
	            featurePropertyNames.forEach(function (featurePropertyName) {
	                if (includes(userPropertyNames, featurePropertyName)) {
	                    var propertiesNode = getPropertiesNode(userProperties, featurePropertyName, feature);
	                    // Process the child node
	                    var childStrands = chemicalReactions.separateProperties(userProperties, propertiesNode);
	                    var childPrimer = self.preparePrimer(userProperties, propertiesNode, childStrands);

	                    bindPrimer(primerInstructions, childPrimer);
	                }
	            });
	        }

	        return primerInstructions;
	    }
	};


/***/ },
/* 134 */
/***/ function(module, exports, __webpack_require__) {

	var basePick = __webpack_require__(135),
	    flatRest = __webpack_require__(141);

	/**
	 * Creates an object composed of the picked `object` properties.
	 *
	 * @static
	 * @since 0.1.0
	 * @memberOf _
	 * @category Object
	 * @param {Object} object The source object.
	 * @param {...(string|string[])} [paths] The property paths to pick.
	 * @returns {Object} Returns the new object.
	 * @example
	 *
	 * var object = { 'a': 1, 'b': '2', 'c': 3 };
	 *
	 * _.pick(object, ['a', 'c']);
	 * // => { 'a': 1, 'c': 3 }
	 */
	var pick = flatRest(function(object, paths) {
	  return object == null ? {} : basePick(object, paths);
	});

	module.exports = pick;


/***/ },
/* 135 */
/***/ function(module, exports, __webpack_require__) {

	var basePickBy = __webpack_require__(136),
	    hasIn = __webpack_require__(116);

	/**
	 * The base implementation of `_.pick` without support for individual
	 * property identifiers.
	 *
	 * @private
	 * @param {Object} object The source object.
	 * @param {string[]} paths The property paths to pick.
	 * @returns {Object} Returns the new object.
	 */
	function basePick(object, paths) {
	  return basePickBy(object, paths, function(value, path) {
	    return hasIn(object, path);
	  });
	}

	module.exports = basePick;


/***/ },
/* 136 */
/***/ function(module, exports, __webpack_require__) {

	var baseGet = __webpack_require__(105),
	    baseSet = __webpack_require__(137),
	    castPath = __webpack_require__(106);

	/**
	 * The base implementation of  `_.pickBy` without support for iteratee shorthands.
	 *
	 * @private
	 * @param {Object} object The source object.
	 * @param {string[]} paths The property paths to pick.
	 * @param {Function} predicate The function invoked per property.
	 * @returns {Object} Returns the new object.
	 */
	function basePickBy(object, paths, predicate) {
	  var index = -1,
	      length = paths.length,
	      result = {};

	  while (++index < length) {
	    var path = paths[index],
	        value = baseGet(object, path);

	    if (predicate(value, path)) {
	      baseSet(result, castPath(path, object), value);
	    }
	  }
	  return result;
	}

	module.exports = basePickBy;


/***/ },
/* 137 */
/***/ function(module, exports, __webpack_require__) {

	var assignValue = __webpack_require__(138),
	    castPath = __webpack_require__(106),
	    isIndex = __webpack_require__(23),
	    isObject = __webpack_require__(35),
	    toKey = __webpack_require__(115);

	/**
	 * The base implementation of `_.set`.
	 *
	 * @private
	 * @param {Object} object The object to modify.
	 * @param {Array|string} path The path of the property to set.
	 * @param {*} value The value to set.
	 * @param {Function} [customizer] The function to customize path creation.
	 * @returns {Object} Returns `object`.
	 */
	function baseSet(object, path, value, customizer) {
	  if (!isObject(object)) {
	    return object;
	  }
	  path = castPath(path, object);

	  var index = -1,
	      length = path.length,
	      lastIndex = length - 1,
	      nested = object;

	  while (nested != null && ++index < length) {
	    var key = toKey(path[index]),
	        newValue = value;

	    if (index != lastIndex) {
	      var objValue = nested[key];
	      newValue = customizer ? customizer(objValue, key, nested) : undefined;
	      if (newValue === undefined) {
	        newValue = isObject(objValue)
	          ? objValue
	          : (isIndex(path[index + 1]) ? [] : {});
	      }
	    }
	    assignValue(nested, key, newValue);
	    nested = nested[key];
	  }
	  return object;
	}

	module.exports = baseSet;


/***/ },
/* 138 */
/***/ function(module, exports, __webpack_require__) {

	var baseAssignValue = __webpack_require__(139),
	    eq = __webpack_require__(45);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * Assigns `value` to `key` of `object` if the existing value is not equivalent
	 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
	 * for equality comparisons.
	 *
	 * @private
	 * @param {Object} object The object to modify.
	 * @param {string} key The key of the property to assign.
	 * @param {*} value The value to assign.
	 */
	function assignValue(object, key, value) {
	  var objValue = object[key];
	  if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
	      (value === undefined && !(key in object))) {
	    baseAssignValue(object, key, value);
	  }
	}

	module.exports = assignValue;


/***/ },
/* 139 */
/***/ function(module, exports, __webpack_require__) {

	var defineProperty = __webpack_require__(140);

	/**
	 * The base implementation of `assignValue` and `assignMergeValue` without
	 * value checks.
	 *
	 * @private
	 * @param {Object} object The object to modify.
	 * @param {string} key The key of the property to assign.
	 * @param {*} value The value to assign.
	 */
	function baseAssignValue(object, key, value) {
	  if (key == '__proto__' && defineProperty) {
	    defineProperty(object, key, {
	      'configurable': true,
	      'enumerable': true,
	      'value': value,
	      'writable': true
	    });
	  } else {
	    object[key] = value;
	  }
	}

	module.exports = baseAssignValue;


/***/ },
/* 140 */
/***/ function(module, exports, __webpack_require__) {

	var getNative = __webpack_require__(55);

	var defineProperty = (function() {
	  try {
	    var func = getNative(Object, 'defineProperty');
	    func({}, '', {});
	    return func;
	  } catch (e) {}
	}());

	module.exports = defineProperty;


/***/ },
/* 141 */
/***/ function(module, exports, __webpack_require__) {

	var flatten = __webpack_require__(142),
	    overRest = __webpack_require__(145),
	    setToString = __webpack_require__(147);

	/**
	 * A specialized version of `baseRest` which flattens the rest array.
	 *
	 * @private
	 * @param {Function} func The function to apply a rest parameter to.
	 * @returns {Function} Returns the new function.
	 */
	function flatRest(func) {
	  return setToString(overRest(func, undefined, flatten), func + '');
	}

	module.exports = flatRest;


/***/ },
/* 142 */
/***/ function(module, exports, __webpack_require__) {

	var baseFlatten = __webpack_require__(143);

	/**
	 * Flattens `array` a single level deep.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Array
	 * @param {Array} array The array to flatten.
	 * @returns {Array} Returns the new flattened array.
	 * @example
	 *
	 * _.flatten([1, [2, [3, [4]], 5]]);
	 * // => [1, 2, [3, [4]], 5]
	 */
	function flatten(array) {
	  var length = array == null ? 0 : array.length;
	  return length ? baseFlatten(array, 1) : [];
	}

	module.exports = flatten;


/***/ },
/* 143 */
/***/ function(module, exports, __webpack_require__) {

	var arrayPush = __webpack_require__(91),
	    isFlattenable = __webpack_require__(144);

	/**
	 * The base implementation of `_.flatten` with support for restricting flattening.
	 *
	 * @private
	 * @param {Array} array The array to flatten.
	 * @param {number} depth The maximum recursion depth.
	 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
	 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
	 * @param {Array} [result=[]] The initial result value.
	 * @returns {Array} Returns the new flattened array.
	 */
	function baseFlatten(array, depth, predicate, isStrict, result) {
	  var index = -1,
	      length = array.length;

	  predicate || (predicate = isFlattenable);
	  result || (result = []);

	  while (++index < length) {
	    var value = array[index];
	    if (depth > 0 && predicate(value)) {
	      if (depth > 1) {
	        // Recursively flatten arrays (susceptible to call stack limits).
	        baseFlatten(value, depth - 1, predicate, isStrict, result);
	      } else {
	        arrayPush(result, value);
	      }
	    } else if (!isStrict) {
	      result[result.length] = value;
	    }
	  }
	  return result;
	}

	module.exports = baseFlatten;


/***/ },
/* 144 */
/***/ function(module, exports, __webpack_require__) {

	var Symbol = __webpack_require__(13),
	    isArguments = __webpack_require__(10),
	    isArray = __webpack_require__(19);

	/** Built-in value references. */
	var spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;

	/**
	 * Checks if `value` is a flattenable `arguments` object or array.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
	 */
	function isFlattenable(value) {
	  return isArray(value) || isArguments(value) ||
	    !!(spreadableSymbol && value && value[spreadableSymbol]);
	}

	module.exports = isFlattenable;


/***/ },
/* 145 */
/***/ function(module, exports, __webpack_require__) {

	var apply = __webpack_require__(146);

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeMax = Math.max;

	/**
	 * A specialized version of `baseRest` which transforms the rest array.
	 *
	 * @private
	 * @param {Function} func The function to apply a rest parameter to.
	 * @param {number} [start=func.length-1] The start position of the rest parameter.
	 * @param {Function} transform The rest array transform.
	 * @returns {Function} Returns the new function.
	 */
	function overRest(func, start, transform) {
	  start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
	  return function() {
	    var args = arguments,
	        index = -1,
	        length = nativeMax(args.length - start, 0),
	        array = Array(length);

	    while (++index < length) {
	      array[index] = args[start + index];
	    }
	    index = -1;
	    var otherArgs = Array(start + 1);
	    while (++index < start) {
	      otherArgs[index] = args[index];
	    }
	    otherArgs[start] = transform(array);
	    return apply(func, this, otherArgs);
	  };
	}

	module.exports = overRest;


/***/ },
/* 146 */
/***/ function(module, exports) {

	/**
	 * A faster alternative to `Function#apply`, this function invokes `func`
	 * with the `this` binding of `thisArg` and the arguments of `args`.
	 *
	 * @private
	 * @param {Function} func The function to invoke.
	 * @param {*} thisArg The `this` binding of `func`.
	 * @param {Array} args The arguments to invoke `func` with.
	 * @returns {*} Returns the result of `func`.
	 */
	function apply(func, thisArg, args) {
	  switch (args.length) {
	    case 0: return func.call(thisArg);
	    case 1: return func.call(thisArg, args[0]);
	    case 2: return func.call(thisArg, args[0], args[1]);
	    case 3: return func.call(thisArg, args[0], args[1], args[2]);
	  }
	  return func.apply(thisArg, args);
	}

	module.exports = apply;


/***/ },
/* 147 */
/***/ function(module, exports, __webpack_require__) {

	var baseSetToString = __webpack_require__(148),
	    shortOut = __webpack_require__(150);

	/**
	 * Sets the `toString` method of `func` to return `string`.
	 *
	 * @private
	 * @param {Function} func The function to modify.
	 * @param {Function} string The `toString` result.
	 * @returns {Function} Returns `func`.
	 */
	var setToString = shortOut(baseSetToString);

	module.exports = setToString;


/***/ },
/* 148 */
/***/ function(module, exports, __webpack_require__) {

	var constant = __webpack_require__(149),
	    defineProperty = __webpack_require__(140),
	    identity = __webpack_require__(119);

	/**
	 * The base implementation of `setToString` without support for hot loop shorting.
	 *
	 * @private
	 * @param {Function} func The function to modify.
	 * @param {Function} string The `toString` result.
	 * @returns {Function} Returns `func`.
	 */
	var baseSetToString = !defineProperty ? identity : function(func, string) {
	  return defineProperty(func, 'toString', {
	    'configurable': true,
	    'enumerable': false,
	    'value': constant(string),
	    'writable': true
	  });
	};

	module.exports = baseSetToString;


/***/ },
/* 149 */
/***/ function(module, exports) {

	/**
	 * Creates a function that returns `value`.
	 *
	 * @static
	 * @memberOf _
	 * @since 2.4.0
	 * @category Util
	 * @param {*} value The value to return from the new function.
	 * @returns {Function} Returns the new constant function.
	 * @example
	 *
	 * var objects = _.times(2, _.constant({ 'a': 1 }));
	 *
	 * console.log(objects);
	 * // => [{ 'a': 1 }, { 'a': 1 }]
	 *
	 * console.log(objects[0] === objects[1]);
	 * // => true
	 */
	function constant(value) {
	  return function() {
	    return value;
	  };
	}

	module.exports = constant;


/***/ },
/* 150 */
/***/ function(module, exports) {

	/** Used to detect hot functions by number of calls within a span of milliseconds. */
	var HOT_COUNT = 800,
	    HOT_SPAN = 16;

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeNow = Date.now;

	/**
	 * Creates a function that'll short out and invoke `identity` instead
	 * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
	 * milliseconds.
	 *
	 * @private
	 * @param {Function} func The function to restrict.
	 * @returns {Function} Returns the new shortable function.
	 */
	function shortOut(func) {
	  var count = 0,
	      lastCalled = 0;

	  return function() {
	    var stamp = nativeNow(),
	        remaining = HOT_SPAN - (stamp - lastCalled);

	    lastCalled = stamp;
	    if (remaining > 0) {
	      if (++count >= HOT_COUNT) {
	        return arguments[0];
	      }
	    } else {
	      count = 0;
	    }
	    return func.apply(undefined, arguments);
	  };
	}

	module.exports = shortOut;


/***/ },
/* 151 */
/***/ function(module, exports, __webpack_require__) {

	var baseMerge = __webpack_require__(152),
	    createAssigner = __webpack_require__(169);

	/**
	 * This method is like `_.assign` except that it recursively merges own and
	 * inherited enumerable string keyed properties of source objects into the
	 * destination object. Source properties that resolve to `undefined` are
	 * skipped if a destination value exists. Array and plain object properties
	 * are merged recursively. Other objects and value types are overridden by
	 * assignment. Source objects are applied from left to right. Subsequent
	 * sources overwrite property assignments of previous sources.
	 *
	 * **Note:** This method mutates `object`.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.5.0
	 * @category Object
	 * @param {Object} object The destination object.
	 * @param {...Object} [sources] The source objects.
	 * @returns {Object} Returns `object`.
	 * @example
	 *
	 * var object = {
	 *   'a': [{ 'b': 2 }, { 'd': 4 }]
	 * };
	 *
	 * var other = {
	 *   'a': [{ 'c': 3 }, { 'e': 5 }]
	 * };
	 *
	 * _.merge(object, other);
	 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
	 */
	var merge = createAssigner(function(object, source, srcIndex) {
	  baseMerge(object, source, srcIndex);
	});

	module.exports = merge;


/***/ },
/* 152 */
/***/ function(module, exports, __webpack_require__) {

	var Stack = __webpack_require__(40),
	    assignMergeValue = __webpack_require__(153),
	    baseFor = __webpack_require__(5),
	    baseMergeDeep = __webpack_require__(154),
	    isObject = __webpack_require__(35),
	    keysIn = __webpack_require__(166);

	/**
	 * The base implementation of `_.merge` without support for multiple sources.
	 *
	 * @private
	 * @param {Object} object The destination object.
	 * @param {Object} source The source object.
	 * @param {number} srcIndex The index of `source`.
	 * @param {Function} [customizer] The function to customize merged values.
	 * @param {Object} [stack] Tracks traversed source values and their merged
	 *  counterparts.
	 */
	function baseMerge(object, source, srcIndex, customizer, stack) {
	  if (object === source) {
	    return;
	  }
	  baseFor(source, function(srcValue, key) {
	    if (isObject(srcValue)) {
	      stack || (stack = new Stack);
	      baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
	    }
	    else {
	      var newValue = customizer
	        ? customizer(object[key], srcValue, (key + ''), object, source, stack)
	        : undefined;

	      if (newValue === undefined) {
	        newValue = srcValue;
	      }
	      assignMergeValue(object, key, newValue);
	    }
	  }, keysIn);
	}

	module.exports = baseMerge;


/***/ },
/* 153 */
/***/ function(module, exports, __webpack_require__) {

	var baseAssignValue = __webpack_require__(139),
	    eq = __webpack_require__(45);

	/**
	 * This function is like `assignValue` except that it doesn't assign
	 * `undefined` values.
	 *
	 * @private
	 * @param {Object} object The object to modify.
	 * @param {string} key The key of the property to assign.
	 * @param {*} value The value to assign.
	 */
	function assignMergeValue(object, key, value) {
	  if ((value !== undefined && !eq(object[key], value)) ||
	      (value === undefined && !(key in object))) {
	    baseAssignValue(object, key, value);
	  }
	}

	module.exports = assignMergeValue;


/***/ },
/* 154 */
/***/ function(module, exports, __webpack_require__) {

	var assignMergeValue = __webpack_require__(153),
	    cloneBuffer = __webpack_require__(155),
	    cloneTypedArray = __webpack_require__(156),
	    copyArray = __webpack_require__(158),
	    initCloneObject = __webpack_require__(159),
	    isArguments = __webpack_require__(10),
	    isArray = __webpack_require__(19),
	    isArrayLikeObject = __webpack_require__(162),
	    isBuffer = __webpack_require__(20),
	    isFunction = __webpack_require__(34),
	    isObject = __webpack_require__(35),
	    isPlainObject = __webpack_require__(163),
	    isTypedArray = __webpack_require__(24),
	    toPlainObject = __webpack_require__(164);

	/**
	 * A specialized version of `baseMerge` for arrays and objects which performs
	 * deep merges and tracks traversed objects enabling objects with circular
	 * references to be merged.
	 *
	 * @private
	 * @param {Object} object The destination object.
	 * @param {Object} source The source object.
	 * @param {string} key The key of the value to merge.
	 * @param {number} srcIndex The index of `source`.
	 * @param {Function} mergeFunc The function to merge values.
	 * @param {Function} [customizer] The function to customize assigned values.
	 * @param {Object} [stack] Tracks traversed source values and their merged
	 *  counterparts.
	 */
	function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
	  var objValue = object[key],
	      srcValue = source[key],
	      stacked = stack.get(srcValue);

	  if (stacked) {
	    assignMergeValue(object, key, stacked);
	    return;
	  }
	  var newValue = customizer
	    ? customizer(objValue, srcValue, (key + ''), object, source, stack)
	    : undefined;

	  var isCommon = newValue === undefined;

	  if (isCommon) {
	    var isArr = isArray(srcValue),
	        isBuff = !isArr && isBuffer(srcValue),
	        isTyped = !isArr && !isBuff && isTypedArray(srcValue);

	    newValue = srcValue;
	    if (isArr || isBuff || isTyped) {
	      if (isArray(objValue)) {
	        newValue = objValue;
	      }
	      else if (isArrayLikeObject(objValue)) {
	        newValue = copyArray(objValue);
	      }
	      else if (isBuff) {
	        isCommon = false;
	        newValue = cloneBuffer(srcValue, true);
	      }
	      else if (isTyped) {
	        isCommon = false;
	        newValue = cloneTypedArray(srcValue, true);
	      }
	      else {
	        newValue = [];
	      }
	    }
	    else if (isPlainObject(srcValue) || isArguments(srcValue)) {
	      newValue = objValue;
	      if (isArguments(objValue)) {
	        newValue = toPlainObject(objValue);
	      }
	      else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
	        newValue = initCloneObject(srcValue);
	      }
	    }
	    else {
	      isCommon = false;
	    }
	  }
	  if (isCommon) {
	    // Recursively merge objects and arrays (susceptible to call stack limits).
	    stack.set(srcValue, newValue);
	    mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
	    stack['delete'](srcValue);
	  }
	  assignMergeValue(object, key, newValue);
	}

	module.exports = baseMergeDeep;


/***/ },
/* 155 */
/***/ function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(14);

	/** Detect free variable `exports`. */
	var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

	/** Detect free variable `module`. */
	var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

	/** Detect the popular CommonJS extension `module.exports`. */
	var moduleExports = freeModule && freeModule.exports === freeExports;

	/** Built-in value references. */
	var Buffer = moduleExports ? root.Buffer : undefined,
	    allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;

	/**
	 * Creates a clone of  `buffer`.
	 *
	 * @private
	 * @param {Buffer} buffer The buffer to clone.
	 * @param {boolean} [isDeep] Specify a deep clone.
	 * @returns {Buffer} Returns the cloned buffer.
	 */
	function cloneBuffer(buffer, isDeep) {
	  if (isDeep) {
	    return buffer.slice();
	  }
	  var length = buffer.length,
	      result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);

	  buffer.copy(result);
	  return result;
	}

	module.exports = cloneBuffer;

	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(21)(module)))

/***/ },
/* 156 */
/***/ function(module, exports, __webpack_require__) {

	var cloneArrayBuffer = __webpack_require__(157);

	/**
	 * Creates a clone of `typedArray`.
	 *
	 * @private
	 * @param {Object} typedArray The typed array to clone.
	 * @param {boolean} [isDeep] Specify a deep clone.
	 * @returns {Object} Returns the cloned typed array.
	 */
	function cloneTypedArray(typedArray, isDeep) {
	  var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
	  return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
	}

	module.exports = cloneTypedArray;


/***/ },
/* 157 */
/***/ function(module, exports, __webpack_require__) {

	var Uint8Array = __webpack_require__(85);

	/**
	 * Creates a clone of `arrayBuffer`.
	 *
	 * @private
	 * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
	 * @returns {ArrayBuffer} Returns the cloned array buffer.
	 */
	function cloneArrayBuffer(arrayBuffer) {
	  var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
	  new Uint8Array(result).set(new Uint8Array(arrayBuffer));
	  return result;
	}

	module.exports = cloneArrayBuffer;


/***/ },
/* 158 */
/***/ function(module, exports) {

	/**
	 * Copies the values of `source` to `array`.
	 *
	 * @private
	 * @param {Array} source The array to copy values from.
	 * @param {Array} [array=[]] The array to copy values to.
	 * @returns {Array} Returns `array`.
	 */
	function copyArray(source, array) {
	  var index = -1,
	      length = source.length;

	  array || (array = Array(length));
	  while (++index < length) {
	    array[index] = source[index];
	  }
	  return array;
	}

	module.exports = copyArray;


/***/ },
/* 159 */
/***/ function(module, exports, __webpack_require__) {

	var baseCreate = __webpack_require__(160),
	    getPrototype = __webpack_require__(161),
	    isPrototype = __webpack_require__(30);

	/**
	 * Initializes an object clone.
	 *
	 * @private
	 * @param {Object} object The object to clone.
	 * @returns {Object} Returns the initialized clone.
	 */
	function initCloneObject(object) {
	  return (typeof object.constructor == 'function' && !isPrototype(object))
	    ? baseCreate(getPrototype(object))
	    : {};
	}

	module.exports = initCloneObject;


/***/ },
/* 160 */
/***/ function(module, exports, __webpack_require__) {

	var isObject = __webpack_require__(35);

	/** Built-in value references. */
	var objectCreate = Object.create;

	/**
	 * The base implementation of `_.create` without support for assigning
	 * properties to the created object.
	 *
	 * @private
	 * @param {Object} proto The object to inherit from.
	 * @returns {Object} Returns the new object.
	 */
	var baseCreate = (function() {
	  function object() {}
	  return function(proto) {
	    if (!isObject(proto)) {
	      return {};
	    }
	    if (objectCreate) {
	      return objectCreate(proto);
	    }
	    object.prototype = proto;
	    var result = new object;
	    object.prototype = undefined;
	    return result;
	  };
	}());

	module.exports = baseCreate;


/***/ },
/* 161 */
/***/ function(module, exports, __webpack_require__) {

	var overArg = __webpack_require__(32);

	/** Built-in value references. */
	var getPrototype = overArg(Object.getPrototypeOf, Object);

	module.exports = getPrototype;


/***/ },
/* 162 */
/***/ function(module, exports, __webpack_require__) {

	var isArrayLike = __webpack_require__(33),
	    isObjectLike = __webpack_require__(18);

	/**
	 * This method is like `_.isArrayLike` except that it also checks if `value`
	 * is an object.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is an array-like object,
	 *  else `false`.
	 * @example
	 *
	 * _.isArrayLikeObject([1, 2, 3]);
	 * // => true
	 *
	 * _.isArrayLikeObject(document.body.children);
	 * // => true
	 *
	 * _.isArrayLikeObject('abc');
	 * // => false
	 *
	 * _.isArrayLikeObject(_.noop);
	 * // => false
	 */
	function isArrayLikeObject(value) {
	  return isObjectLike(value) && isArrayLike(value);
	}

	module.exports = isArrayLikeObject;


/***/ },
/* 163 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetTag = __webpack_require__(12),
	    getPrototype = __webpack_require__(161),
	    isObjectLike = __webpack_require__(18);

	/** `Object#toString` result references. */
	var objectTag = '[object Object]';

	/** Used for built-in method references. */
	var funcProto = Function.prototype,
	    objectProto = Object.prototype;

	/** Used to resolve the decompiled source of functions. */
	var funcToString = funcProto.toString;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/** Used to infer the `Object` constructor. */
	var objectCtorString = funcToString.call(Object);

	/**
	 * Checks if `value` is a plain object, that is, an object created by the
	 * `Object` constructor or one with a `[[Prototype]]` of `null`.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.8.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
	 * @example
	 *
	 * function Foo() {
	 *   this.a = 1;
	 * }
	 *
	 * _.isPlainObject(new Foo);
	 * // => false
	 *
	 * _.isPlainObject([1, 2, 3]);
	 * // => false
	 *
	 * _.isPlainObject({ 'x': 0, 'y': 0 });
	 * // => true
	 *
	 * _.isPlainObject(Object.create(null));
	 * // => true
	 */
	function isPlainObject(value) {
	  if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
	    return false;
	  }
	  var proto = getPrototype(value);
	  if (proto === null) {
	    return true;
	  }
	  var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
	  return typeof Ctor == 'function' && Ctor instanceof Ctor &&
	    funcToString.call(Ctor) == objectCtorString;
	}

	module.exports = isPlainObject;


/***/ },
/* 164 */
/***/ function(module, exports, __webpack_require__) {

	var copyObject = __webpack_require__(165),
	    keysIn = __webpack_require__(166);

	/**
	 * Converts `value` to a plain object flattening inherited enumerable string
	 * keyed properties of `value` to own properties of the plain object.
	 *
	 * @static
	 * @memberOf _
	 * @since 3.0.0
	 * @category Lang
	 * @param {*} value The value to convert.
	 * @returns {Object} Returns the converted plain object.
	 * @example
	 *
	 * function Foo() {
	 *   this.b = 2;
	 * }
	 *
	 * Foo.prototype.c = 3;
	 *
	 * _.assign({ 'a': 1 }, new Foo);
	 * // => { 'a': 1, 'b': 2 }
	 *
	 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
	 * // => { 'a': 1, 'b': 2, 'c': 3 }
	 */
	function toPlainObject(value) {
	  return copyObject(value, keysIn(value));
	}

	module.exports = toPlainObject;


/***/ },
/* 165 */
/***/ function(module, exports, __webpack_require__) {

	var assignValue = __webpack_require__(138),
	    baseAssignValue = __webpack_require__(139);

	/**
	 * Copies properties of `source` to `object`.
	 *
	 * @private
	 * @param {Object} source The object to copy properties from.
	 * @param {Array} props The property identifiers to copy.
	 * @param {Object} [object={}] The object to copy properties to.
	 * @param {Function} [customizer] The function to customize copied values.
	 * @returns {Object} Returns `object`.
	 */
	function copyObject(source, props, object, customizer) {
	  var isNew = !object;
	  object || (object = {});

	  var index = -1,
	      length = props.length;

	  while (++index < length) {
	    var key = props[index];

	    var newValue = customizer
	      ? customizer(object[key], source[key], key, object, source)
	      : undefined;

	    if (newValue === undefined) {
	      newValue = source[key];
	    }
	    if (isNew) {
	      baseAssignValue(object, key, newValue);
	    } else {
	      assignValue(object, key, newValue);
	    }
	  }
	  return object;
	}

	module.exports = copyObject;


/***/ },
/* 166 */
/***/ function(module, exports, __webpack_require__) {

	var arrayLikeKeys = __webpack_require__(8),
	    baseKeysIn = __webpack_require__(167),
	    isArrayLike = __webpack_require__(33);

	/**
	 * Creates an array of the own and inherited enumerable property names of `object`.
	 *
	 * **Note:** Non-object values are coerced to objects.
	 *
	 * @static
	 * @memberOf _
	 * @since 3.0.0
	 * @category Object
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of property names.
	 * @example
	 *
	 * function Foo() {
	 *   this.a = 1;
	 *   this.b = 2;
	 * }
	 *
	 * Foo.prototype.c = 3;
	 *
	 * _.keysIn(new Foo);
	 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
	 */
	function keysIn(object) {
	  return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
	}

	module.exports = keysIn;


/***/ },
/* 167 */
/***/ function(module, exports, __webpack_require__) {

	var isObject = __webpack_require__(35),
	    isPrototype = __webpack_require__(30),
	    nativeKeysIn = __webpack_require__(168);

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of property names.
	 */
	function baseKeysIn(object) {
	  if (!isObject(object)) {
	    return nativeKeysIn(object);
	  }
	  var isProto = isPrototype(object),
	      result = [];

	  for (var key in object) {
	    if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
	      result.push(key);
	    }
	  }
	  return result;
	}

	module.exports = baseKeysIn;


/***/ },
/* 168 */
/***/ function(module, exports) {

	/**
	 * This function is like
	 * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
	 * except that it includes inherited enumerable properties.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of property names.
	 */
	function nativeKeysIn(object) {
	  var result = [];
	  if (object != null) {
	    for (var key in Object(object)) {
	      result.push(key);
	    }
	  }
	  return result;
	}

	module.exports = nativeKeysIn;


/***/ },
/* 169 */
/***/ function(module, exports, __webpack_require__) {

	var baseRest = __webpack_require__(170),
	    isIterateeCall = __webpack_require__(171);

	/**
	 * Creates a function like `_.assign`.
	 *
	 * @private
	 * @param {Function} assigner The function to assign values.
	 * @returns {Function} Returns the new assigner function.
	 */
	function createAssigner(assigner) {
	  return baseRest(function(object, sources) {
	    var index = -1,
	        length = sources.length,
	        customizer = length > 1 ? sources[length - 1] : undefined,
	        guard = length > 2 ? sources[2] : undefined;

	    customizer = (assigner.length > 3 && typeof customizer == 'function')
	      ? (length--, customizer)
	      : undefined;

	    if (guard && isIterateeCall(sources[0], sources[1], guard)) {
	      customizer = length < 3 ? undefined : customizer;
	      length = 1;
	    }
	    object = Object(object);
	    while (++index < length) {
	      var source = sources[index];
	      if (source) {
	        assigner(object, source, index, customizer);
	      }
	    }
	    return object;
	  });
	}

	module.exports = createAssigner;


/***/ },
/* 170 */
/***/ function(module, exports, __webpack_require__) {

	var identity = __webpack_require__(119),
	    overRest = __webpack_require__(145),
	    setToString = __webpack_require__(147);

	/**
	 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
	 *
	 * @private
	 * @param {Function} func The function to apply a rest parameter to.
	 * @param {number} [start=func.length-1] The start position of the rest parameter.
	 * @returns {Function} Returns the new function.
	 */
	function baseRest(func, start) {
	  return setToString(overRest(func, start, identity), func + '');
	}

	module.exports = baseRest;


/***/ },
/* 171 */
/***/ function(module, exports, __webpack_require__) {

	var eq = __webpack_require__(45),
	    isArrayLike = __webpack_require__(33),
	    isIndex = __webpack_require__(23),
	    isObject = __webpack_require__(35);

	/**
	 * Checks if the given arguments are from an iteratee call.
	 *
	 * @private
	 * @param {*} value The potential iteratee value argument.
	 * @param {*} index The potential iteratee index or key argument.
	 * @param {*} object The potential iteratee object argument.
	 * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
	 *  else `false`.
	 */
	function isIterateeCall(value, index, object) {
	  if (!isObject(object)) {
	    return false;
	  }
	  var type = typeof index;
	  if (type == 'number'
	        ? (isArrayLike(object) && isIndex(index, object.length))
	        : (type == 'string' && index in object)
	      ) {
	    return eq(object[index], value);
	  }
	  return false;
	}

	module.exports = isIterateeCall;


/***/ },
/* 172 */
/***/ function(module, exports, __webpack_require__) {

	var baseHas = __webpack_require__(173),
	    hasPath = __webpack_require__(118);

	/**
	 * Checks if `path` is a direct property of `object`.
	 *
	 * @static
	 * @since 0.1.0
	 * @memberOf _
	 * @category Object
	 * @param {Object} object The object to query.
	 * @param {Array|string} path The path to check.
	 * @returns {boolean} Returns `true` if `path` exists, else `false`.
	 * @example
	 *
	 * var object = { 'a': { 'b': 2 } };
	 * var other = _.create({ 'a': _.create({ 'b': 2 }) });
	 *
	 * _.has(object, 'a');
	 * // => true
	 *
	 * _.has(object, 'a.b');
	 * // => true
	 *
	 * _.has(object, ['a', 'b']);
	 * // => true
	 *
	 * _.has(other, 'a');
	 * // => false
	 */
	function has(object, path) {
	  return object != null && hasPath(object, path, baseHas);
	}

	module.exports = has;


/***/ },
/* 173 */
/***/ function(module, exports) {

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * The base implementation of `_.has` without support for deep paths.
	 *
	 * @private
	 * @param {Object} [object] The object to query.
	 * @param {Array|string} key The key to check.
	 * @returns {boolean} Returns `true` if `key` exists, else `false`.
	 */
	function baseHas(object, key) {
	  return object != null && hasOwnProperty.call(object, key);
	}

	module.exports = baseHas;


/***/ },
/* 174 */
/***/ function(module, exports) {

	/**
	 * Checks if `value` is `undefined`.
	 *
	 * @static
	 * @since 0.1.0
	 * @memberOf _
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
	 * @example
	 *
	 * _.isUndefined(void 0);
	 * // => true
	 *
	 * _.isUndefined(null);
	 * // => false
	 */
	function isUndefined(value) {
	  return value === undefined;
	}

	module.exports = isUndefined;


/***/ },
/* 175 */
/***/ function(module, exports, __webpack_require__) {

	var baseIndexOf = __webpack_require__(176),
	    isArrayLike = __webpack_require__(33),
	    isString = __webpack_require__(180),
	    toInteger = __webpack_require__(181),
	    values = __webpack_require__(184);

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeMax = Math.max;

	/**
	 * Checks if `value` is in `collection`. If `collection` is a string, it's
	 * checked for a substring of `value`, otherwise
	 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
	 * is used for equality comparisons. If `fromIndex` is negative, it's used as
	 * the offset from the end of `collection`.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Collection
	 * @param {Array|Object|string} collection The collection to inspect.
	 * @param {*} value The value to search for.
	 * @param {number} [fromIndex=0] The index to search from.
	 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
	 * @returns {boolean} Returns `true` if `value` is found, else `false`.
	 * @example
	 *
	 * _.includes([1, 2, 3], 1);
	 * // => true
	 *
	 * _.includes([1, 2, 3], 1, 2);
	 * // => false
	 *
	 * _.includes({ 'a': 1, 'b': 2 }, 1);
	 * // => true
	 *
	 * _.includes('abcd', 'bc');
	 * // => true
	 */
	function includes(collection, value, fromIndex, guard) {
	  collection = isArrayLike(collection) ? collection : values(collection);
	  fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;

	  var length = collection.length;
	  if (fromIndex < 0) {
	    fromIndex = nativeMax(length + fromIndex, 0);
	  }
	  return isString(collection)
	    ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
	    : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
	}

	module.exports = includes;


/***/ },
/* 176 */
/***/ function(module, exports, __webpack_require__) {

	var baseFindIndex = __webpack_require__(177),
	    baseIsNaN = __webpack_require__(178),
	    strictIndexOf = __webpack_require__(179);

	/**
	 * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
	 *
	 * @private
	 * @param {Array} array The array to inspect.
	 * @param {*} value The value to search for.
	 * @param {number} fromIndex The index to search from.
	 * @returns {number} Returns the index of the matched value, else `-1`.
	 */
	function baseIndexOf(array, value, fromIndex) {
	  return value === value
	    ? strictIndexOf(array, value, fromIndex)
	    : baseFindIndex(array, baseIsNaN, fromIndex);
	}

	module.exports = baseIndexOf;


/***/ },
/* 177 */
/***/ function(module, exports) {

	/**
	 * The base implementation of `_.findIndex` and `_.findLastIndex` without
	 * support for iteratee shorthands.
	 *
	 * @private
	 * @param {Array} array The array to inspect.
	 * @param {Function} predicate The function invoked per iteration.
	 * @param {number} fromIndex The index to search from.
	 * @param {boolean} [fromRight] Specify iterating from right to left.
	 * @returns {number} Returns the index of the matched value, else `-1`.
	 */
	function baseFindIndex(array, predicate, fromIndex, fromRight) {
	  var length = array.length,
	      index = fromIndex + (fromRight ? 1 : -1);

	  while ((fromRight ? index-- : ++index < length)) {
	    if (predicate(array[index], index, array)) {
	      return index;
	    }
	  }
	  return -1;
	}

	module.exports = baseFindIndex;


/***/ },
/* 178 */
/***/ function(module, exports) {

	/**
	 * The base implementation of `_.isNaN` without support for number objects.
	 *
	 * @private
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
	 */
	function baseIsNaN(value) {
	  return value !== value;
	}

	module.exports = baseIsNaN;


/***/ },
/* 179 */
/***/ function(module, exports) {

	/**
	 * A specialized version of `_.indexOf` which performs strict equality
	 * comparisons of values, i.e. `===`.
	 *
	 * @private
	 * @param {Array} array The array to inspect.
	 * @param {*} value The value to search for.
	 * @param {number} fromIndex The index to search from.
	 * @returns {number} Returns the index of the matched value, else `-1`.
	 */
	function strictIndexOf(array, value, fromIndex) {
	  var index = fromIndex - 1,
	      length = array.length;

	  while (++index < length) {
	    if (array[index] === value) {
	      return index;
	    }
	  }
	  return -1;
	}

	module.exports = strictIndexOf;


/***/ },
/* 180 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetTag = __webpack_require__(12),
	    isArray = __webpack_require__(19),
	    isObjectLike = __webpack_require__(18);

	/** `Object#toString` result references. */
	var stringTag = '[object String]';

	/**
	 * Checks if `value` is classified as a `String` primitive or object.
	 *
	 * @static
	 * @since 0.1.0
	 * @memberOf _
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a string, else `false`.
	 * @example
	 *
	 * _.isString('abc');
	 * // => true
	 *
	 * _.isString(1);
	 * // => false
	 */
	function isString(value) {
	  return typeof value == 'string' ||
	    (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
	}

	module.exports = isString;


/***/ },
/* 181 */
/***/ function(module, exports, __webpack_require__) {

	var toFinite = __webpack_require__(182);

	/**
	 * Converts `value` to an integer.
	 *
	 * **Note:** This method is loosely based on
	 * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to convert.
	 * @returns {number} Returns the converted integer.
	 * @example
	 *
	 * _.toInteger(3.2);
	 * // => 3
	 *
	 * _.toInteger(Number.MIN_VALUE);
	 * // => 0
	 *
	 * _.toInteger(Infinity);
	 * // => 1.7976931348623157e+308
	 *
	 * _.toInteger('3.2');
	 * // => 3
	 */
	function toInteger(value) {
	  var result = toFinite(value),
	      remainder = result % 1;

	  return result === result ? (remainder ? result - remainder : result) : 0;
	}

	module.exports = toInteger;


/***/ },
/* 182 */
/***/ function(module, exports, __webpack_require__) {

	var toNumber = __webpack_require__(183);

	/** Used as references for various `Number` constants. */
	var INFINITY = 1 / 0,
	    MAX_INTEGER = 1.7976931348623157e+308;

	/**
	 * Converts `value` to a finite number.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.12.0
	 * @category Lang
	 * @param {*} value The value to convert.
	 * @returns {number} Returns the converted number.
	 * @example
	 *
	 * _.toFinite(3.2);
	 * // => 3.2
	 *
	 * _.toFinite(Number.MIN_VALUE);
	 * // => 5e-324
	 *
	 * _.toFinite(Infinity);
	 * // => 1.7976931348623157e+308
	 *
	 * _.toFinite('3.2');
	 * // => 3.2
	 */
	function toFinite(value) {
	  if (!value) {
	    return value === 0 ? value : 0;
	  }
	  value = toNumber(value);
	  if (value === INFINITY || value === -INFINITY) {
	    var sign = (value < 0 ? -1 : 1);
	    return sign * MAX_INTEGER;
	  }
	  return value === value ? value : 0;
	}

	module.exports = toFinite;


/***/ },
/* 183 */
/***/ function(module, exports, __webpack_require__) {

	var isObject = __webpack_require__(35),
	    isSymbol = __webpack_require__(108);

	/** Used as references for various `Number` constants. */
	var NAN = 0 / 0;

	/** Used to match leading and trailing whitespace. */
	var reTrim = /^\s+|\s+$/g;

	/** Used to detect bad signed hexadecimal string values. */
	var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

	/** Used to detect binary string values. */
	var reIsBinary = /^0b[01]+$/i;

	/** Used to detect octal string values. */
	var reIsOctal = /^0o[0-7]+$/i;

	/** Built-in method references without a dependency on `root`. */
	var freeParseInt = parseInt;

	/**
	 * Converts `value` to a number.
	 *
	 * @static
	 * @memberOf _
	 * @since 4.0.0
	 * @category Lang
	 * @param {*} value The value to process.
	 * @returns {number} Returns the number.
	 * @example
	 *
	 * _.toNumber(3.2);
	 * // => 3.2
	 *
	 * _.toNumber(Number.MIN_VALUE);
	 * // => 5e-324
	 *
	 * _.toNumber(Infinity);
	 * // => Infinity
	 *
	 * _.toNumber('3.2');
	 * // => 3.2
	 */
	function toNumber(value) {
	  if (typeof value == 'number') {
	    return value;
	  }
	  if (isSymbol(value)) {
	    return NAN;
	  }
	  if (isObject(value)) {
	    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
	    value = isObject(other) ? (other + '') : other;
	  }
	  if (typeof value != 'string') {
	    return value === 0 ? value : +value;
	  }
	  value = value.replace(reTrim, '');
	  var isBinary = reIsBinary.test(value);
	  return (isBinary || reIsOctal.test(value))
	    ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
	    : (reIsBadHex.test(value) ? NAN : +value);
	}

	module.exports = toNumber;


/***/ },
/* 184 */
/***/ function(module, exports, __webpack_require__) {

	var baseValues = __webpack_require__(185),
	    keys = __webpack_require__(7);

	/**
	 * Creates an array of the own enumerable string keyed property values of `object`.
	 *
	 * **Note:** Non-object values are coerced to objects.
	 *
	 * @static
	 * @since 0.1.0
	 * @memberOf _
	 * @category Object
	 * @param {Object} object The object to query.
	 * @returns {Array} Returns the array of property values.
	 * @example
	 *
	 * function Foo() {
	 *   this.a = 1;
	 *   this.b = 2;
	 * }
	 *
	 * Foo.prototype.c = 3;
	 *
	 * _.values(new Foo);
	 * // => [1, 2] (iteration order is not guaranteed)
	 *
	 * _.values('hi');
	 * // => ['h', 'i']
	 */
	function values(object) {
	  return object == null ? [] : baseValues(object, keys(object));
	}

	module.exports = values;


/***/ },
/* 185 */
/***/ function(module, exports, __webpack_require__) {

	var arrayMap = __webpack_require__(114);

	/**
	 * The base implementation of `_.values` and `_.valuesIn` which creates an
	 * array of `object` property values corresponding to the property names
	 * of `props`.
	 *
	 * @private
	 * @param {Object} object The object to query.
	 * @param {Array} props The property names to get values for.
	 * @returns {Object} Returns the array of property values.
	 */
	function baseValues(object, props) {
	  return arrayMap(props, function(key) {
	    return object[key];
	  });
	}

	module.exports = baseValues;


/***/ },
/* 186 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * This module match-reads feature properties against user properties.
	 */

	var findLast = __webpack_require__(187);
	var regexMatcher = __webpack_require__(190);
	var numericMatcher = __webpack_require__(191);

	var defaultMatcher = {
	    matchesPropertyValue: function(userPropertyValue, propertyKey) {
	        return userPropertyValue === propertyKey;
	    }
	};

	function pickMatcher(userPropertyValue, propertyKey) {
	    if (regexMatcher.isRegex(propertyKey)) {
	        return regexMatcher;
	    } else if (numericMatcher.isNumber(userPropertyValue) &&
	        numericMatcher.isNumericQuantifier(propertyKey)) {
	        return numericMatcher;
	    } else {
	        return defaultMatcher;
	    }
	}

	module.exports = {
	    getMatchedProperties: function(userPropertyValue, featureProperty) {
	        return findLast(featureProperty, function (propertyValue, propertyKey) {
	            var matcher = pickMatcher(userPropertyValue, propertyKey);
	            return matcher.matchesPropertyValue(userPropertyValue, propertyKey);
	        });
	    }
	};


/***/ },
/* 187 */
/***/ function(module, exports, __webpack_require__) {

	var createFind = __webpack_require__(188),
	    findLastIndex = __webpack_require__(189);

	/**
	 * This method is like `_.find` except that it iterates over elements of
	 * `collection` from right to left.
	 *
	 * @static
	 * @memberOf _
	 * @since 2.0.0
	 * @category Collection
	 * @param {Array|Object} collection The collection to inspect.
	 * @param {Function} [predicate=_.identity] The function invoked per iteration.
	 * @param {number} [fromIndex=collection.length-1] The index to search from.
	 * @returns {*} Returns the matched element, else `undefined`.
	 * @example
	 *
	 * _.findLast([1, 2, 3, 4], function(n) {
	 *   return n % 2 == 1;
	 * });
	 * // => 3
	 */
	var findLast = createFind(findLastIndex);

	module.exports = findLast;


/***/ },
/* 188 */
/***/ function(module, exports, __webpack_require__) {

	var baseIteratee = __webpack_require__(37),
	    isArrayLike = __webpack_require__(33),
	    keys = __webpack_require__(7);

	/**
	 * Creates a `_.find` or `_.findLast` function.
	 *
	 * @private
	 * @param {Function} findIndexFunc The function to find the collection index.
	 * @returns {Function} Returns the new find function.
	 */
	function createFind(findIndexFunc) {
	  return function(collection, predicate, fromIndex) {
	    var iterable = Object(collection);
	    if (!isArrayLike(collection)) {
	      var iteratee = baseIteratee(predicate, 3);
	      collection = keys(collection);
	      predicate = function(key) { return iteratee(iterable[key], key, iterable); };
	    }
	    var index = findIndexFunc(collection, predicate, fromIndex);
	    return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
	  };
	}

	module.exports = createFind;


/***/ },
/* 189 */
/***/ function(module, exports, __webpack_require__) {

	var baseFindIndex = __webpack_require__(177),
	    baseIteratee = __webpack_require__(37),
	    toInteger = __webpack_require__(181);

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeMax = Math.max,
	    nativeMin = Math.min;

	/**
	 * This method is like `_.findIndex` except that it iterates over elements
	 * of `collection` from right to left.
	 *
	 * @static
	 * @memberOf _
	 * @since 2.0.0
	 * @category Array
	 * @param {Array} array The array to inspect.
	 * @param {Function} [predicate=_.identity] The function invoked per iteration.
	 * @param {number} [fromIndex=array.length-1] The index to search from.
	 * @returns {number} Returns the index of the found element, else `-1`.
	 * @example
	 *
	 * var users = [
	 *   { 'user': 'barney',  'active': true },
	 *   { 'user': 'fred',    'active': false },
	 *   { 'user': 'pebbles', 'active': false }
	 * ];
	 *
	 * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
	 * // => 2
	 *
	 * // The `_.matches` iteratee shorthand.
	 * _.findLastIndex(users, { 'user': 'barney', 'active': true });
	 * // => 0
	 *
	 * // The `_.matchesProperty` iteratee shorthand.
	 * _.findLastIndex(users, ['active', false]);
	 * // => 2
	 *
	 * // The `_.property` iteratee shorthand.
	 * _.findLastIndex(users, 'active');
	 * // => 0
	 */
	function findLastIndex(array, predicate, fromIndex) {
	  var length = array == null ? 0 : array.length;
	  if (!length) {
	    return -1;
	  }
	  var index = length - 1;
	  if (fromIndex !== undefined) {
	    index = toInteger(fromIndex);
	    index = fromIndex < 0
	      ? nativeMax(length + index, 0)
	      : nativeMin(index, length - 1);
	  }
	  return baseFindIndex(array, baseIteratee(predicate, 3), index, true);
	}

	module.exports = findLastIndex;


/***/ },
/* 190 */
/***/ function(module, exports) {

	'use strict';

	var regexDelimiters = /^\/.+\/$/;

	function sanitizeRegexStr(regexStr) {
	    return regexStr.substring(1, regexStr.length - 1);
	}

	module.exports = {
	    isRegex: function (value) {
	        return regexDelimiters.test(value);
	    },

	    matchesPropertyValue: function(propertyValue, regexStr) {
	        var sanitisedRegex = sanitizeRegexStr(regexStr);
	        var regex = new RegExp('^' + sanitisedRegex + '$');
	        return regex.test(propertyValue);
	    }
	};


/***/ },
/* 191 */
/***/ function(module, exports) {

	'use strict';

	var numberRegex = /-?\d+(\.\d{1,2})?/;
	var operatorRegex = /[><]=?/;

	var numericQuantifierRegex = new RegExp(operatorRegex.source + numberRegex.source);
	var validExpressionRegex = new RegExp(numberRegex.source + operatorRegex.source + numberRegex.source);

	function isExpressionValid(expression) {
	    return validExpressionRegex.test(expression);
	}

	module.exports = {

	    isNumber: function (value) {
	        return numberRegex.test(value);
	    },

	    isNumericQuantifier: function (value) {
	        return numericQuantifierRegex.test(value);
	    },

	    matchesPropertyValue: function(propertyValue, numericQuantifierStr) {
	        var expression = propertyValue + numericQuantifierStr;

	        if (!isExpressionValid(expression)) {
	            // Just to catch eventual issues with eval
	            return false;
	        }

	        /*jshint -W061*/
	        return eval(expression);
	    }
	};


/***/ },
/* 192 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * The Polymerase enzyme in real life assembles a new DNA strand on top of the existing one. During the process, it
	 * check for replication errors doing proof-reading on the fly. But sometimes a random mutation occur... that's life
	 * trying to evolve.
	 * This module takes the primer feature instructions, does proof-reading over them to make sure no errors
	 * are found and then it assembles a collection of resolved feature toggles.
	 *
	 * In the process, even if the instructions are considered valid, random mutations occur. Those are caused by the
	 * Bucket and Throttle mutators. That's your application trying to evolve.
	 */
	var merge = __webpack_require__(151);

	var bucketMutator = __webpack_require__(193);
	var throttleMutator = __webpack_require__(195);
	var genePairing = __webpack_require__(196);
	var proofReader = __webpack_require__(199);

	function addToFeatures(features, featureName, toggle) {
	    return features.push(merge({ name: featureName }, toggle));
	}

	function processFeatureInstructions(featureProperties, gene) {
	    var toggle = {
	        type: 'toggle',
	        toggle: false
	    };

	    if (featureProperties.toggle !== false) {
	        if (throttleMutator.isThrottleValid(featureProperties.throttle)) {
	            toggle.toggle = throttleMutator.mutate(featureProperties.throttle, gene);
	            toggle.type = 'throttle';
	        } else if (featureProperties.toggle === true) {
	            toggle.toggle = true;
	        }
	    }

	    return toggle;
	}

	function containsBuckets(toggle, featureInstructions) {
	    return toggle.toggle && bucketMutator.containsMultivariant(featureInstructions);
	}

	function addBucketToFeatures(features, featureName, featureInstructions, toggle, gene) {
	    var bucketName = bucketMutator.mutate(featureInstructions, gene);

	    var bucketToggle = {
	        toggle : toggle.toggle,
	        type : 'bucket'
	    };

	    addToFeatures(features, featureName + "." + bucketName, bucketToggle);
	}

	module.exports = {
	    /**
	     * Returns a resolved feature toggle, with the information indicating whether it's active or not. If the
	     * feature mutates to a bucket, it also can contain the corresponding feature toggle.
	     *
	     * @param featureName The feature name being processed
	     * @param primerInstructions The primer instructions to process
	     * @returns A resolved feature toggle, which may mutate to a bucket feature toggle
	     * @param ancestorGenes An object containing 'genes' to inherit, this only applies to throttles and buckets
	     */
	    assembleFeatures: function(featureName, primerInstructions, ancestorGenes) {
	        var features = [];

	        if (proofReader.areInstructionsValid(primerInstructions)) {

	            // Get the ancestor gene based on name to be able to copy it to the descendant
	            var gene = genePairing.pairGene(ancestorGenes, featureName);

	            var toggle = processFeatureInstructions(primerInstructions, gene);
	            addToFeatures(features, featureName, toggle);

	            if (containsBuckets(toggle, primerInstructions)) {
	                addBucketToFeatures(features, featureName, primerInstructions, toggle, gene);
	            }
	        } else {
	            addToFeatures(features, featureName, { toggle: false, type: 'toggle' });
	        }
	        return features;
	    }
	};


/***/ },
/* 193 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * The Bucket mutator manipulates the features by introducing small random mutations by picking a random
	 * bucket from the list, allowing multivariance testing.
	 */
	var isArray = __webpack_require__(19);
	var isEmpty = __webpack_require__(194);
	var includes = __webpack_require__(175);

	function pickOneElement(array) {
	    if (!isArray(array)) {
	        throw 'Not an array!';
	    }

	    var index = Math.floor(Math.random() * (array.length));
	    return array[index];
	}

	function isBucketGene(gene) {
	    return !isEmpty(gene) && gene.type === 'bucket';
	}

	function containsGene(featureProperties, gene) {
	    return includes(featureProperties.buckets, gene.toggle);
	}

	module.exports = {
	    mutate: function(featureProperties, gene) {
	        if (isBucketGene(gene) && containsGene(featureProperties, gene)) {
	            return gene.toggle;
	        } else {
	            return pickOneElement(featureProperties.buckets);
	        }
	    },

	    containsMultivariant: function(featureProperties) {
	        return this.isBucketListValid(featureProperties.buckets);
	    },

	    isBucketListValid: function(bucketList) {
	        return isArray(bucketList) && bucketList.length >= 0;
	    }
	};


/***/ },
/* 194 */
/***/ function(module, exports, __webpack_require__) {

	var baseKeys = __webpack_require__(29),
	    getTag = __webpack_require__(95),
	    isArguments = __webpack_require__(10),
	    isArray = __webpack_require__(19),
	    isArrayLike = __webpack_require__(33),
	    isBuffer = __webpack_require__(20),
	    isPrototype = __webpack_require__(30),
	    isTypedArray = __webpack_require__(24);

	/** `Object#toString` result references. */
	var mapTag = '[object Map]',
	    setTag = '[object Set]';

	/** Used for built-in method references. */
	var objectProto = Object.prototype;

	/** Used to check objects for own properties. */
	var hasOwnProperty = objectProto.hasOwnProperty;

	/**
	 * Checks if `value` is an empty object, collection, map, or set.
	 *
	 * Objects are considered empty if they have no own enumerable string keyed
	 * properties.
	 *
	 * Array-like values such as `arguments` objects, arrays, buffers, strings, or
	 * jQuery-like collections are considered empty if they have a `length` of `0`.
	 * Similarly, maps and sets are considered empty if they have a `size` of `0`.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is empty, else `false`.
	 * @example
	 *
	 * _.isEmpty(null);
	 * // => true
	 *
	 * _.isEmpty(true);
	 * // => true
	 *
	 * _.isEmpty(1);
	 * // => true
	 *
	 * _.isEmpty([1, 2, 3]);
	 * // => false
	 *
	 * _.isEmpty({ 'a': 1 });
	 * // => false
	 */
	function isEmpty(value) {
	  if (value == null) {
	    return true;
	  }
	  if (isArrayLike(value) &&
	      (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
	        isBuffer(value) || isTypedArray(value) || isArguments(value))) {
	    return !value.length;
	  }
	  var tag = getTag(value);
	  if (tag == mapTag || tag == setTag) {
	    return !value.size;
	  }
	  if (isPrototype(value)) {
	    return !baseKeys(value).length;
	  }
	  for (var key in value) {
	    if (hasOwnProperty.call(value, key)) {
	      return false;
	    }
	  }
	  return true;
	}

	module.exports = isEmpty;


/***/ },
/* 195 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * The Throttle mutator manipulates the features by introducing small random mutations by randomly activate
	 * or deactivate feture toggles.
	 */
	var isUndefined = __webpack_require__(174);
	var isString = __webpack_require__(180);
	var isPlainObject = __webpack_require__(163);
	var isEmpty = __webpack_require__(194);

	function isPercentage(value) {
	    return !isUndefined(value) && isString(value) && value.match(/[0-100]%/);
	}

	function isThrottleNode(throttle) {
	    return isPlainObject(throttle) && isString(throttle['value']) && isPercentage(throttle['value']);
	}

	function extractPercentage(throttle) {
	    var percentage;
	    if (isThrottleNode(throttle)) {
	        percentage = throttle['value'];
	    } else {
	        percentage = throttle;
	    }
	    return percentage;
	}

	function getPercentageDecimal(throttle) {
	    var percentage = extractPercentage(throttle);
	    var value = percentage.substr(0, percentage.length - 2);
	    return value / 10;
	}

	function isThrottleValid(throttle) {
	    return isThrottleNode(throttle) || isPercentage(throttle);
	}

	function isThrottleGene(gene) {
	    return !isEmpty(gene) && gene.type === 'throttle';
	}

	function shouldMutate(throttle) {
	    return !isUndefined(throttle['mutate']) && throttle['mutate'] === 'force';
	}

	module.exports = {
	    mutate: function (throttle, gene) {
	        if (!shouldMutate(throttle) && isThrottleGene(gene)) {
	            return gene.toggle;
	        } else {
	            var percentage = getPercentageDecimal(throttle);
	            return Math.random() < percentage;
	        }
	    },

	    isThrottleValid: function (throttle) {
	        return isThrottleValid(throttle);
	    }
	};


/***/ },
/* 196 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	var filter = __webpack_require__(124);
	var find = __webpack_require__(197);
	var keys = __webpack_require__(7);
	var isString = __webpack_require__(180);

	function findWithPartialName(featureNames, partialName) {
	    return filter(featureNames, function (featureName) {
	        return featureName.indexOf(partialName) === 0;
	    });
	}

	function hasPartialName(featureNames, partialName) {
	    return findWithPartialName(featureNames, partialName).length > 0;
	}

	function containTogglesPair(genes, featureName) {
	    return hasPartialName(keys(genes.toggles), featureName);
	}

	function containBucketsPair(genes, featureName) {
	    return hasPartialName(genes.buckets, featureName);
	}

	function containThrottlesPair(genes, featureName) {
	    return hasPartialName(genes.throttles, featureName);
	}

	function getBucketNameFromFeatureName(featureName) {
	    var dotIndex = featureName.indexOf('.');
	    return dotIndex >= 0 ? featureName.substring(dotIndex + 1) : '';
	}

	function getMatchingBucket(genes, featureName) {
	    var matchedFeatures = findWithPartialName(genes.buckets, featureName);
	    var matched = find(matchedFeatures, function (matchedBucket) {
	            return genes.toggles[matchedBucket];
	        });
	    return isString(matched) ? getBucketNameFromFeatureName(matched) : '';
	}

	module.exports = {
	    pairGene: function (genes, featureName) {
	        var gene = {};
	        if (containTogglesPair(genes, featureName)) {
	            var type = 'toggle';
	            var name = genes.toggles[featureName];
	            if (containBucketsPair(genes, featureName)) {
	                type = 'bucket';
	                name = getMatchingBucket(genes, featureName);
	            } else if (containThrottlesPair(genes, featureName)) {
	                type = 'throttle';
	            }

	            gene['toggle'] = name;
	            gene['type'] = type;
	        }
	        return gene;
	    }
	};


/***/ },
/* 197 */
/***/ function(module, exports, __webpack_require__) {

	var createFind = __webpack_require__(188),
	    findIndex = __webpack_require__(198);

	/**
	 * Iterates over elements of `collection`, returning the first element
	 * `predicate` returns truthy for. The predicate is invoked with three
	 * arguments: (value, index|key, collection).
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Collection
	 * @param {Array|Object} collection The collection to inspect.
	 * @param {Function} [predicate=_.identity] The function invoked per iteration.
	 * @param {number} [fromIndex=0] The index to search from.
	 * @returns {*} Returns the matched element, else `undefined`.
	 * @example
	 *
	 * var users = [
	 *   { 'user': 'barney',  'age': 36, 'active': true },
	 *   { 'user': 'fred',    'age': 40, 'active': false },
	 *   { 'user': 'pebbles', 'age': 1,  'active': true }
	 * ];
	 *
	 * _.find(users, function(o) { return o.age < 40; });
	 * // => object for 'barney'
	 *
	 * // The `_.matches` iteratee shorthand.
	 * _.find(users, { 'age': 1, 'active': true });
	 * // => object for 'pebbles'
	 *
	 * // The `_.matchesProperty` iteratee shorthand.
	 * _.find(users, ['active', false]);
	 * // => object for 'fred'
	 *
	 * // The `_.property` iteratee shorthand.
	 * _.find(users, 'active');
	 * // => object for 'barney'
	 */
	var find = createFind(findIndex);

	module.exports = find;


/***/ },
/* 198 */
/***/ function(module, exports, __webpack_require__) {

	var baseFindIndex = __webpack_require__(177),
	    baseIteratee = __webpack_require__(37),
	    toInteger = __webpack_require__(181);

	/* Built-in method references for those with the same name as other `lodash` methods. */
	var nativeMax = Math.max;

	/**
	 * This method is like `_.find` except that it returns the index of the first
	 * element `predicate` returns truthy for instead of the element itself.
	 *
	 * @static
	 * @memberOf _
	 * @since 1.1.0
	 * @category Array
	 * @param {Array} array The array to inspect.
	 * @param {Function} [predicate=_.identity] The function invoked per iteration.
	 * @param {number} [fromIndex=0] The index to search from.
	 * @returns {number} Returns the index of the found element, else `-1`.
	 * @example
	 *
	 * var users = [
	 *   { 'user': 'barney',  'active': false },
	 *   { 'user': 'fred',    'active': false },
	 *   { 'user': 'pebbles', 'active': true }
	 * ];
	 *
	 * _.findIndex(users, function(o) { return o.user == 'barney'; });
	 * // => 0
	 *
	 * // The `_.matches` iteratee shorthand.
	 * _.findIndex(users, { 'user': 'fred', 'active': false });
	 * // => 1
	 *
	 * // The `_.matchesProperty` iteratee shorthand.
	 * _.findIndex(users, ['active', false]);
	 * // => 0
	 *
	 * // The `_.property` iteratee shorthand.
	 * _.findIndex(users, 'active');
	 * // => 2
	 */
	function findIndex(array, predicate, fromIndex) {
	  var length = array == null ? 0 : array.length;
	  if (!length) {
	    return -1;
	  }
	  var index = fromIndex == null ? 0 : toInteger(fromIndex);
	  if (index < 0) {
	    index = nativeMax(length + index, 0);
	  }
	  return baseFindIndex(array, baseIteratee(predicate, 3), index);
	}

	module.exports = findIndex;


/***/ },
/* 199 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	/**
	 * This module checks for errors and proof-reads the molecules.
	 */
	var get = __webpack_require__(104);
	var isUndefined = __webpack_require__(174);
	var isBoolean = __webpack_require__(200);
	var isNull = __webpack_require__(201);
	var isArray = __webpack_require__(19);
	var isObject = __webpack_require__(35);

	var bucketMutator = __webpack_require__(193);
	var throttleMutator = __webpack_require__(195);

	module.exports = {
	    areInstructionsValid: function (featureInstructions) {
	        var toggle = get(featureInstructions, 'toggle');
	        var throttle = get(featureInstructions, 'throttle');
	        var buckets = get(featureInstructions, 'buckets');

	        return this.isToggleValid(toggle) && this.isThrottleValid(throttle) && this.areBucketsValid(buckets);
	    },

	    isToggleValid: function (toggle) {
	        return isUndefined(toggle) || isBoolean(toggle);
	    },

	    isThrottleValid: function(throttle) {
	        return isUndefined(throttle) || throttleMutator.isThrottleValid(throttle);
	    },

	    areBucketsValid: function(buckets) {
	        return isUndefined(buckets) || bucketMutator.isBucketListValid(buckets);
	    },

	    checkFeatureInstructions: function (featureInstructions) {
	        var valid = isUndefined(featureInstructions) || isNull(featureInstructions) || !isArray(featureInstructions) && isObject(featureInstructions);

	        if (!valid) {
	            throw new Error('Invalid feature instructions!');
	        }
	    }
	};


/***/ },
/* 200 */
/***/ function(module, exports, __webpack_require__) {

	var baseGetTag = __webpack_require__(12),
	    isObjectLike = __webpack_require__(18);

	/** `Object#toString` result references. */
	var boolTag = '[object Boolean]';

	/**
	 * Checks if `value` is classified as a boolean primitive or object.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
	 * @example
	 *
	 * _.isBoolean(false);
	 * // => true
	 *
	 * _.isBoolean(null);
	 * // => false
	 */
	function isBoolean(value) {
	  return value === true || value === false ||
	    (isObjectLike(value) && baseGetTag(value) == boolTag);
	}

	module.exports = isBoolean;


/***/ },
/* 201 */
/***/ function(module, exports) {

	/**
	 * Checks if `value` is `null`.
	 *
	 * @static
	 * @memberOf _
	 * @since 0.1.0
	 * @category Lang
	 * @param {*} value The value to check.
	 * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
	 * @example
	 *
	 * _.isNull(null);
	 * // => true
	 *
	 * _.isNull(void 0);
	 * // => false
	 */
	function isNull(value) {
	  return value === null;
	}

	module.exports = isNull;


/***/ }
/******/ ]);
define("muton", (function (global) {
    return function () {
        var ret, fn;
        return ret || global.muton;
    };
}(this)));

../node_modules/moment/min/moment.min.js
//! moment.js
//! version : 2.8.4
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
(function(a){function b(a,b,c){switch(arguments.length){case 2:return null!=a?a:b;case 3:return null!=a?a:null!=b?b:c;default:throw new Error("Implement me")}}function c(a,b){return zb.call(a,b)}function d(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function e(a){tb.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+a)}function f(a,b){var c=!0;return m(function(){return c&&(e(a),c=!1),b.apply(this,arguments)},b)}function g(a,b){qc[a]||(e(b),qc[a]=!0)}function h(a,b){return function(c){return p(a.call(this,c),b)}}function i(a,b){return function(c){return this.localeData().ordinal(a.call(this,c),b)}}function j(){}function k(a,b){b!==!1&&F(a),n(this,a),this._d=new Date(+a._d)}function l(a){var b=y(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=tb.localeData(),this._bubble()}function m(a,b){for(var d in b)c(b,d)&&(a[d]=b[d]);return c(b,"toString")&&(a.toString=b.toString),c(b,"valueOf")&&(a.valueOf=b.valueOf),a}function n(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=b._pf),"undefined"!=typeof b._locale&&(a._locale=b._locale),Ib.length>0)for(c in Ib)d=Ib[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function o(a){return 0>a?Math.ceil(a):Math.floor(a)}function p(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.length<b;)d="0"+d;return(e?c?"+":"":"-")+d}function q(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function r(a,b){var c;return b=K(b,a),a.isBefore(b)?c=q(a,b):(c=q(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function s(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(g(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=tb.duration(c,d),t(this,e,a),this}}function t(a,b,c,d){var e=b._milliseconds,f=b._days,g=b._months;d=null==d?!0:d,e&&a._d.setTime(+a._d+e*c),f&&nb(a,"Date",mb(a,"Date")+f*c),g&&lb(a,mb(a,"Month")+g*c),d&&tb.updateOffset(a,f||g)}function u(a){return"[object Array]"===Object.prototype.toString.call(a)}function v(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function w(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&A(a[d])!==A(b[d]))&&g++;return g+f}function x(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=jc[a]||kc[b]||b}return a}function y(a){var b,d,e={};for(d in a)c(a,d)&&(b=x(d),b&&(e[b]=a[d]));return e}function z(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}tb[b]=function(e,f){var g,h,i=tb._locale[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=tb().utc().set(d,a);return i.call(tb._locale,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function A(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function B(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function C(a,b,c){return hb(tb([a,11,31+b-c]),b,c).week}function D(a){return E(a)?366:365}function E(a){return a%4===0&&a%100!==0||a%400===0}function F(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[Bb]<0||a._a[Bb]>11?Bb:a._a[Cb]<1||a._a[Cb]>B(a._a[Ab],a._a[Bb])?Cb:a._a[Db]<0||a._a[Db]>24||24===a._a[Db]&&(0!==a._a[Eb]||0!==a._a[Fb]||0!==a._a[Gb])?Db:a._a[Eb]<0||a._a[Eb]>59?Eb:a._a[Fb]<0||a._a[Fb]>59?Fb:a._a[Gb]<0||a._a[Gb]>999?Gb:-1,a._pf._overflowDayOfYear&&(Ab>b||b>Cb)&&(b=Cb),a._pf.overflow=b)}function G(b){return null==b._isValid&&(b._isValid=!isNaN(b._d.getTime())&&b._pf.overflow<0&&!b._pf.empty&&!b._pf.invalidMonth&&!b._pf.nullInput&&!b._pf.invalidFormat&&!b._pf.userInvalidated,b._strict&&(b._isValid=b._isValid&&0===b._pf.charsLeftOver&&0===b._pf.unusedTokens.length&&b._pf.bigHour===a)),b._isValid}function H(a){return a?a.toLowerCase().replace("_","-"):a}function I(a){for(var b,c,d,e,f=0;f<a.length;){for(e=H(a[f]).split("-"),b=e.length,c=H(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=J(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&w(e,c,!0)>=b-1)break;b--}f++}return null}function J(a){var b=null;if(!Hb[a]&&Jb)try{b=tb.locale(),require("./locale/"+a),tb.locale(b)}catch(c){}return Hb[a]}function K(a,b){var c,d;return b._isUTC?(c=b.clone(),d=(tb.isMoment(a)||v(a)?+a:+tb(a))-+c,c._d.setTime(+c._d+d),tb.updateOffset(c,!1),c):tb(a).local()}function L(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function M(a){var b,c,d=a.match(Nb);for(b=0,c=d.length;c>b;b++)d[b]=pc[d[b]]?pc[d[b]]:L(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function N(a,b){return a.isValid()?(b=O(b,a.localeData()),lc[b]||(lc[b]=M(b)),lc[b](a)):a.localeData().invalidDate()}function O(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Ob.lastIndex=0;d>=0&&Ob.test(a);)a=a.replace(Ob,c),Ob.lastIndex=0,d-=1;return a}function P(a,b){var c,d=b._strict;switch(a){case"Q":return Zb;case"DDDD":return _b;case"YYYY":case"GGGG":case"gggg":return d?ac:Rb;case"Y":case"G":case"g":return cc;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?bc:Sb;case"S":if(d)return Zb;case"SS":if(d)return $b;case"SSS":if(d)return _b;case"DDD":return Qb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Ub;case"a":case"A":return b._locale._meridiemParse;case"x":return Xb;case"X":return Yb;case"Z":case"ZZ":return Vb;case"T":return Wb;case"SSSS":return Tb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?$b:Pb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Pb;case"Do":return d?b._locale._ordinalParse:b._locale._ordinalParseLenient;default:return c=new RegExp(Y(X(a.replace("\\","")),"i"))}}function Q(a){a=a||"";var b=a.match(Vb)||[],c=b[b.length-1]||[],d=(c+"").match(hc)||["-",0,0],e=+(60*d[1])+A(d[2]);return"+"===d[0]?-e:e}function R(a,b,c){var d,e=c._a;switch(a){case"Q":null!=b&&(e[Bb]=3*(A(b)-1));break;case"M":case"MM":null!=b&&(e[Bb]=A(b)-1);break;case"MMM":case"MMMM":d=c._locale.monthsParse(b,a,c._strict),null!=d?e[Bb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[Cb]=A(b));break;case"Do":null!=b&&(e[Cb]=A(parseInt(b.match(/\d{1,2}/)[0],10)));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=A(b));break;case"YY":e[Ab]=tb.parseTwoDigitYear(b);break;case"YYYY":case"YYYYY":case"YYYYYY":e[Ab]=A(b);break;case"a":case"A":c._isPm=c._locale.isPM(b);break;case"h":case"hh":c._pf.bigHour=!0;case"H":case"HH":e[Db]=A(b);break;case"m":case"mm":e[Eb]=A(b);break;case"s":case"ss":e[Fb]=A(b);break;case"S":case"SS":case"SSS":case"SSSS":e[Gb]=A(1e3*("0."+b));break;case"x":c._d=new Date(A(b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=Q(b);break;case"dd":case"ddd":case"dddd":d=c._locale.weekdaysParse(b),null!=d?(c._w=c._w||{},c._w.d=d):c._pf.invalidWeekday=b;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":a=a.substr(0,1);case"gggg":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=A(b));break;case"gg":case"GG":c._w=c._w||{},c._w[a]=tb.parseTwoDigitYear(b)}}function S(a){var c,d,e,f,g,h,i;c=a._w,null!=c.GG||null!=c.W||null!=c.E?(g=1,h=4,d=b(c.GG,a._a[Ab],hb(tb(),1,4).year),e=b(c.W,1),f=b(c.E,1)):(g=a._locale._week.dow,h=a._locale._week.doy,d=b(c.gg,a._a[Ab],hb(tb(),g,h).year),e=b(c.w,1),null!=c.d?(f=c.d,g>f&&++e):f=null!=c.e?c.e+g:g),i=ib(d,e,f,h,g),a._a[Ab]=i.year,a._dayOfYear=i.dayOfYear}function T(a){var c,d,e,f,g=[];if(!a._d){for(e=V(a),a._w&&null==a._a[Cb]&&null==a._a[Bb]&&S(a),a._dayOfYear&&(f=b(a._a[Ab],e[Ab]),a._dayOfYear>D(f)&&(a._pf._overflowDayOfYear=!0),d=db(f,0,a._dayOfYear),a._a[Bb]=d.getUTCMonth(),a._a[Cb]=d.getUTCDate()),c=0;3>c&&null==a._a[c];++c)a._a[c]=g[c]=e[c];for(;7>c;c++)a._a[c]=g[c]=null==a._a[c]?2===c?1:0:a._a[c];24===a._a[Db]&&0===a._a[Eb]&&0===a._a[Fb]&&0===a._a[Gb]&&(a._nextDay=!0,a._a[Db]=0),a._d=(a._useUTC?db:cb).apply(null,g),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()+a._tzm),a._nextDay&&(a._a[Db]=24)}}function U(a){var b;a._d||(b=y(a._i),a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],T(a))}function V(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function W(b){if(b._f===tb.ISO_8601)return void $(b);b._a=[],b._pf.empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=O(b._f,b._locale).match(Nb)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(P(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&b._pf.unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),pc[f]?(d?b._pf.empty=!1:b._pf.unusedTokens.push(f),R(f,d,b)):b._strict&&!d&&b._pf.unusedTokens.push(f);b._pf.charsLeftOver=i-j,h.length>0&&b._pf.unusedInput.push(h),b._pf.bigHour===!0&&b._a[Db]<=12&&(b._pf.bigHour=a),b._isPm&&b._a[Db]<12&&(b._a[Db]+=12),b._isPm===!1&&12===b._a[Db]&&(b._a[Db]=0),T(b),F(b)}function X(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function Y(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Z(a){var b,c,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;f<a._f.length;f++)g=0,b=n({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._pf=d(),b._f=a._f[f],W(b),G(b)&&(g+=b._pf.charsLeftOver,g+=10*b._pf.unusedTokens.length,b._pf.score=g,(null==e||e>g)&&(e=g,c=b));m(a,c||b)}function $(a){var b,c,d=a._i,e=dc.exec(d);if(e){for(a._pf.iso=!0,b=0,c=fc.length;c>b;b++)if(fc[b][1].exec(d)){a._f=fc[b][0]+(e[6]||" ");break}for(b=0,c=gc.length;c>b;b++)if(gc[b][1].exec(d)){a._f+=gc[b][0];break}d.match(Vb)&&(a._f+="Z"),W(a)}else a._isValid=!1}function _(a){$(a),a._isValid===!1&&(delete a._isValid,tb.createFromInputFallback(a))}function ab(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function bb(b){var c,d=b._i;d===a?b._d=new Date:v(d)?b._d=new Date(+d):null!==(c=Kb.exec(d))?b._d=new Date(+c[1]):"string"==typeof d?_(b):u(d)?(b._a=ab(d.slice(0),function(a){return parseInt(a,10)}),T(b)):"object"==typeof d?U(b):"number"==typeof d?b._d=new Date(d):tb.createFromInputFallback(b)}function cb(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function db(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function eb(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function fb(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function gb(a,b,c){var d=tb.duration(a).abs(),e=yb(d.as("s")),f=yb(d.as("m")),g=yb(d.as("h")),h=yb(d.as("d")),i=yb(d.as("M")),j=yb(d.as("y")),k=e<mc.s&&["s",e]||1===f&&["m"]||f<mc.m&&["mm",f]||1===g&&["h"]||g<mc.h&&["hh",g]||1===h&&["d"]||h<mc.d&&["dd",h]||1===i&&["M"]||i<mc.M&&["MM",i]||1===j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,fb.apply({},k)}function hb(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=tb(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ib(a,b,c,d,e){var f,g,h=db(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:D(a-1)+g}}function jb(b){var c,d=b._i,e=b._f;return b._locale=b._locale||tb.localeData(b._l),null===d||e===a&&""===d?tb.invalid({nullInput:!0}):("string"==typeof d&&(b._i=d=b._locale.preparse(d)),tb.isMoment(d)?new k(d,!0):(e?u(e)?Z(b):W(b):bb(b),c=new k(b),c._nextDay&&(c.add(1,"d"),c._nextDay=a),c))}function kb(a,b){var c,d;if(1===b.length&&u(b[0])&&(b=b[0]),!b.length)return tb();for(c=b[0],d=1;d<b.length;++d)b[d][a](c)&&(c=b[d]);return c}function lb(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),B(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function mb(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function nb(a,b,c){return"Month"===b?lb(a,c):a._d["set"+(a._isUTC?"UTC":"")+b](c)}function ob(a,b){return function(c){return null!=c?(nb(this,a,c),tb.updateOffset(this,b),this):mb(this,a)}}function pb(a){return 400*a/146097}function qb(a){return 146097*a/400}function rb(a){tb.duration.fn[a]=function(){return this._data[a]}}function sb(a){"undefined"==typeof ender&&(ub=xb.moment,xb.moment=a?f("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.",tb):tb)}for(var tb,ub,vb,wb="2.8.4",xb="undefined"!=typeof global?global:this,yb=Math.round,zb=Object.prototype.hasOwnProperty,Ab=0,Bb=1,Cb=2,Db=3,Eb=4,Fb=5,Gb=6,Hb={},Ib=[],Jb="undefined"!=typeof module&&module&&module.exports,Kb=/^\/?Date\((\-?\d+)/i,Lb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,Mb=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,Nb=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,Ob=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Pb=/\d\d?/,Qb=/\d{1,3}/,Rb=/\d{1,4}/,Sb=/[+\-]?\d{1,6}/,Tb=/\d+/,Ub=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Vb=/Z|[\+\-]\d\d:?\d\d/gi,Wb=/T/i,Xb=/[\+\-]?\d+/,Yb=/[\+\-]?\d+(\.\d{1,3})?/,Zb=/\d/,$b=/\d\d/,_b=/\d{3}/,ac=/\d{4}/,bc=/[+-]?\d{6}/,cc=/[+-]?\d+/,dc=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ec="YYYY-MM-DDTHH:mm:ssZ",fc=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],gc=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],hc=/([\+\-]|\d\d)/gi,ic=("Date|Hours|Minutes|Seconds|Milliseconds".split("|"),{Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6}),jc={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",Q:"quarter",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},kc={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},lc={},mc={s:45,m:45,h:22,d:26,M:11},nc="DDD w W M D d".split(" "),oc="M D H h m s w W".split(" "),pc={M:function(){return this.month()+1},MMM:function(a){return this.localeData().monthsShort(this,a)},MMMM:function(a){return this.localeData().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.localeData().weekdaysMin(this,a)},ddd:function(a){return this.localeData().weekdaysShort(this,a)},dddd:function(a){return this.localeData().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return p(this.year()%100,2)},YYYY:function(){return p(this.year(),4)},YYYYY:function(){return p(this.year(),5)},YYYYYY:function(){var a=this.year(),b=a>=0?"+":"-";return b+p(Math.abs(a),6)},gg:function(){return p(this.weekYear()%100,2)},gggg:function(){return p(this.weekYear(),4)},ggggg:function(){return p(this.weekYear(),5)},GG:function(){return p(this.isoWeekYear()%100,2)},GGGG:function(){return p(this.isoWeekYear(),4)},GGGGG:function(){return p(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return A(this.milliseconds()/100)},SS:function(){return p(A(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},SSSS:function(){return p(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+":"+p(A(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+p(A(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},x:function(){return this.valueOf()},X:function(){return this.unix()},Q:function(){return this.quarter()}},qc={},rc=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];nc.length;)vb=nc.pop(),pc[vb+"o"]=i(pc[vb],vb);for(;oc.length;)vb=oc.pop(),pc[vb+vb]=h(pc[vb],2);pc.DDDD=h(pc.DDD,3),m(j.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=tb.utc([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=tb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.apply(b,[c]):d},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",_ordinalParse:/\d{1,2}/,preparse:function(a){return a},postformat:function(a){return a},week:function(a){return hb(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),tb=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=b,g._f=c,g._l=e,g._strict=f,g._isUTC=!1,g._pf=d(),jb(g)},tb.suppressDeprecationWarnings=!1,tb.createFromInputFallback=f("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),tb.min=function(){var a=[].slice.call(arguments,0);return kb("isBefore",a)},tb.max=function(){var a=[].slice.call(arguments,0);return kb("isAfter",a)},tb.utc=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=b,g._f=c,g._strict=f,g._pf=d(),jb(g).utc()},tb.unix=function(a){return tb(1e3*a)},tb.duration=function(a,b){var d,e,f,g,h=a,i=null;return tb.isDuration(a)?h={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(h={},b?h[b]=a:h.milliseconds=a):(i=Lb.exec(a))?(d="-"===i[1]?-1:1,h={y:0,d:A(i[Cb])*d,h:A(i[Db])*d,m:A(i[Eb])*d,s:A(i[Fb])*d,ms:A(i[Gb])*d}):(i=Mb.exec(a))?(d="-"===i[1]?-1:1,f=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*d},h={y:f(i[2]),M:f(i[3]),d:f(i[4]),h:f(i[5]),m:f(i[6]),s:f(i[7]),w:f(i[8])}):"object"==typeof h&&("from"in h||"to"in h)&&(g=r(tb(h.from),tb(h.to)),h={},h.ms=g.milliseconds,h.M=g.months),e=new l(h),tb.isDuration(a)&&c(a,"_locale")&&(e._locale=a._locale),e},tb.version=wb,tb.defaultFormat=ec,tb.ISO_8601=function(){},tb.momentProperties=Ib,tb.updateOffset=function(){},tb.relativeTimeThreshold=function(b,c){return mc[b]===a?!1:c===a?mc[b]:(mc[b]=c,!0)},tb.lang=f("moment.lang is deprecated. Use moment.locale instead.",function(a,b){return tb.locale(a,b)}),tb.locale=function(a,b){var c;return a&&(c="undefined"!=typeof b?tb.defineLocale(a,b):tb.localeData(a),c&&(tb.duration._locale=tb._locale=c)),tb._locale._abbr},tb.defineLocale=function(a,b){return null!==b?(b.abbr=a,Hb[a]||(Hb[a]=new j),Hb[a].set(b),tb.locale(a),Hb[a]):(delete Hb[a],null)},tb.langData=f("moment.langData is deprecated. Use moment.localeData instead.",function(a){return tb.localeData(a)}),tb.localeData=function(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return tb._locale;if(!u(a)){if(b=J(a))return b;a=[a]}return I(a)},tb.isMoment=function(a){return a instanceof k||null!=a&&c(a,"_isAMomentObject")},tb.isDuration=function(a){return a instanceof l};for(vb=rc.length-1;vb>=0;--vb)z(rc[vb]);tb.normalizeUnits=function(a){return x(a)},tb.invalid=function(a){var b=tb.utc(0/0);return null!=a?m(b._pf,a):b._pf.userInvalidated=!0,b},tb.parseZone=function(){return tb.apply(null,arguments).parseZone()},tb.parseTwoDigitYear=function(a){return A(a)+(A(a)>68?1900:2e3)},m(tb.fn=k.prototype,{clone:function(){return tb(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=tb(this).utc();return 0<a.year()&&a.year()<=9999?"function"==typeof Date.prototype.toISOString?this.toDate().toISOString():N(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):N(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return G(this)},isDSTShifted:function(){return this._a?this.isValid()&&w(this._a,(this._isUTC?tb.utc(this._a):tb(this._a)).toArray())>0:!1},parsingFlags:function(){return m({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(a){return this.zone(0,a)},local:function(a){return this._isUTC&&(this.zone(0,a),this._isUTC=!1,a&&this.add(this._dateTzOffset(),"m")),this},format:function(a){var b=N(this,a||tb.defaultFormat);return this.localeData().postformat(b)},add:s(1,"add"),subtract:s(-1,"subtract"),diff:function(a,b,c){var d,e,f,g=K(a,this),h=6e4*(this.zone()-g.zone());return b=x(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+g.daysInMonth()),e=12*(this.year()-g.year())+(this.month()-g.month()),f=this-tb(this).startOf("month")-(g-tb(g).startOf("month")),f-=6e4*(this.zone()-tb(this).startOf("month").zone()-(g.zone()-tb(g).startOf("month").zone())),e+=f/d,"year"===b&&(e/=12)):(d=this-g,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-h)/864e5:"week"===b?(d-h)/6048e5:d),c?e:o(e)},from:function(a,b){return tb.duration({to:this,from:a}).locale(this.locale()).humanize(!b)},fromNow:function(a){return this.from(tb(),a)},calendar:function(a){var b=a||tb(),c=K(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,tb(b)))},isLeapYear:function(){return E(this.year())},isDST:function(){return this.zone()<this.clone().month(0).zone()||this.zone()<this.clone().month(5).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=eb(a,this.localeData()),this.add(a-b,"d")):b},month:ob("Month",!0),startOf:function(a){switch(a=x(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this},endOf:function(b){return b=x(b),b===a||"millisecond"===b?this:this.startOf(b).add(1,"isoWeek"===b?"week":b).subtract(1,"ms")},isAfter:function(a,b){var c;return b=x("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=tb.isMoment(a)?a:tb(a),+this>+a):(c=tb.isMoment(a)?+a:+tb(a),c<+this.clone().startOf(b))},isBefore:function(a,b){var c;return b=x("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=tb.isMoment(a)?a:tb(a),+a>+this):(c=tb.isMoment(a)?+a:+tb(a),+this.clone().endOf(b)<c)},isSame:function(a,b){var c;return b=x(b||"millisecond"),"millisecond"===b?(a=tb.isMoment(a)?a:tb(a),+this===+a):(c=+tb(a),+this.clone().startOf(b)<=c&&c<=+this.clone().endOf(b))},min:f("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(a){return a=tb.apply(null,arguments),this>a?this:a}),max:f("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(a){return a=tb.apply(null,arguments),a>this?this:a}),zone:function(a,b){var c,d=this._offset||0;return null==a?this._isUTC?d:this._dateTzOffset():("string"==typeof a&&(a=Q(a)),Math.abs(a)<16&&(a=60*a),!this._isUTC&&b&&(c=this._dateTzOffset()),this._offset=a,this._isUTC=!0,null!=c&&this.subtract(c,"m"),d!==a&&(!b||this._changeInProgress?t(this,tb.duration(d-a,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,tb.updateOffset(this,!0),this._changeInProgress=null)),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?tb(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return B(this.year(),this.month())},dayOfYear:function(a){var b=yb((tb(this).startOf("day")-tb(this).startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")},quarter:function(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)},weekYear:function(a){var b=hb(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")},isoWeekYear:function(a){var b=hb(this,1,4).year;return null==a?b:this.add(a-b,"y")},week:function(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")},isoWeek:function(a){var b=hb(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")},weekday:function(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},isoWeeksInYear:function(){return C(this.year(),1,4)},weeksInYear:function(){var a=this.localeData()._week;return C(this.year(),a.dow,a.doy)},get:function(a){return a=x(a),this[a]()},set:function(a,b){return a=x(a),"function"==typeof this[a]&&this[a](b),this},locale:function(b){var c;return b===a?this._locale._abbr:(c=tb.localeData(b),null!=c&&(this._locale=c),this)},lang:f("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(b){return b===a?this.localeData():this.locale(b)}),localeData:function(){return this._locale},_dateTzOffset:function(){return 15*Math.round(this._d.getTimezoneOffset()/15)}}),tb.fn.millisecond=tb.fn.milliseconds=ob("Milliseconds",!1),tb.fn.second=tb.fn.seconds=ob("Seconds",!1),tb.fn.minute=tb.fn.minutes=ob("Minutes",!1),tb.fn.hour=tb.fn.hours=ob("Hours",!0),tb.fn.date=ob("Date",!0),tb.fn.dates=f("dates accessor is deprecated. Use date instead.",ob("Date",!0)),tb.fn.year=ob("FullYear",!0),tb.fn.years=f("years accessor is deprecated. Use year instead.",ob("FullYear",!0)),tb.fn.days=tb.fn.day,tb.fn.months=tb.fn.month,tb.fn.weeks=tb.fn.week,tb.fn.isoWeeks=tb.fn.isoWeek,tb.fn.quarters=tb.fn.quarter,tb.fn.toJSON=tb.fn.toISOString,m(tb.duration.fn=l.prototype,{_bubble:function(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;g.milliseconds=d%1e3,a=o(d/1e3),g.seconds=a%60,b=o(a/60),g.minutes=b%60,c=o(b/60),g.hours=c%24,e+=o(c/24),h=o(pb(e)),e-=o(qb(h)),f+=o(e/30),e%=30,h+=o(f/12),f%=12,g.days=e,g.months=f,g.years=h},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return o(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*A(this._months/12)},humanize:function(a){var b=gb(this,!a,this.localeData());return a&&(b=this.localeData().pastFuture(+this,b)),this.localeData().postformat(b)},add:function(a,b){var c=tb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=tb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=x(a),this[a.toLowerCase()+"s"]()},as:function(a){var b,c;if(a=x(a),"month"===a||"year"===a)return b=this._days+this._milliseconds/864e5,c=this._months+12*pb(b),"month"===a?c:c/12;switch(b=this._days+Math.round(qb(this._months/12)),a){case"week":return b/7+this._milliseconds/6048e5;case"day":return b+this._milliseconds/864e5;case"hour":return 24*b+this._milliseconds/36e5;case"minute":return 24*b*60+this._milliseconds/6e4;case"second":return 24*b*60*60+this._milliseconds/1e3;
case"millisecond":return Math.floor(24*b*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+a)}},lang:tb.fn.lang,locale:tb.fn.locale,toIsoString:f("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),toISOString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"},localeData:function(){return this._locale}}),tb.duration.fn.toString=tb.duration.fn.toISOString;for(vb in ic)c(ic,vb)&&rb(vb.toLowerCase());tb.duration.fn.asMilliseconds=function(){return this.as("ms")},tb.duration.fn.asSeconds=function(){return this.as("s")},tb.duration.fn.asMinutes=function(){return this.as("m")},tb.duration.fn.asHours=function(){return this.as("h")},tb.duration.fn.asDays=function(){return this.as("d")},tb.duration.fn.asWeeks=function(){return this.as("weeks")},tb.duration.fn.asMonths=function(){return this.as("M")},tb.duration.fn.asYears=function(){return this.as("y")},tb.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===A(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),Jb?module.exports=tb:"function"==typeof define&&define.amd?(define("moment",['require','exports','module'],function(a,b,c){return c.config&&c.config()&&c.config().noGlobal===!0&&(xb.moment=ub),tb}),sb(!0)):sb()}).call(this);
vendors/ng-dialog/js/ngDialog.js
/*
 * ngDialog - easy modals and popup windows
 * http://github.com/likeastore/ngDialog
 * (c) 2013-2015 MIT License, https://likeastore.com
 */

(function (root, factory) {
    // Global Variables
    factory(root.angular);
}(this, function (angular) {
    'use strict';

    var m = angular.module('ngDialog', []);

    var $el = angular.element;
    var isDef = angular.isDefined;
    var style = (document.body || document.documentElement).style;
    var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
    var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
    var focusableElementSelector = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
    var disabledAnimationClass = 'ngdialog-disabled-animation';
    var forceElementsReload = { html: false, body: false };
    var scopes = {};
    var openIdStack = [];
    var keydownIsBound = false;
    var openOnePerName = false;


    m.provider('ngDialog', function () {
        var defaults = this.defaults = {
            className: 'ngdialog-theme-default',
            appendClassName: '',
            disableAnimation: false,
            plain: false,
            showClose: true,
            closeByDocument: true,
            closeByEscape: true,
            closeByNavigation: false,
            appendTo: false,
            preCloseCallback: false,
            overlay: true,
            cache: true,
            trapFocus: true,
            preserveFocus: true,
            ariaAuto: true,
            ariaRole: null,
            ariaLabelledById: null,
            ariaLabelledBySelector: null,
            ariaDescribedById: null,
            ariaDescribedBySelector: null,
            bodyClassName: 'ngdialog-open'
        };

        this.setForceHtmlReload = function (_useIt) {
            forceElementsReload.html = _useIt || false;
        };

        this.setForceBodyReload = function (_useIt) {
            forceElementsReload.body = _useIt || false;
        };

        this.setDefaults = function (newDefaults) {
            angular.extend(defaults, newDefaults);
        };

        this.setOpenOnePerName = function (isOpenOne) {
            openOnePerName = isOpenOne || false;
        };

        var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};

        this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller', '$injector',
            function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller, $injector) {
                var $elements = [];

                var privateMethods = {
                    onDocumentKeydown: function (event) {
                        if (event.keyCode === 27) {
                            publicMethods.close('$escape');
                        }
                    },

                    activate: function($dialog) {
                        var options = $dialog.data('$ngDialogOptions');

                        if (options.trapFocus) {
                            $dialog.on('keydown', privateMethods.onTrapFocusKeydown);

                            // Catch rogue changes (eg. after unfocusing everything by clicking a non-focusable element)
                            $elements.body.on('keydown', privateMethods.onTrapFocusKeydown);
                        }
                    },

                    deactivate: function ($dialog) {
                        $dialog.off('keydown', privateMethods.onTrapFocusKeydown);
                        $elements.body.off('keydown', privateMethods.onTrapFocusKeydown);
                    },

                    deactivateAll: function (els) {
                        angular.forEach(els,function(el) {
                            var $dialog = angular.element(el);
                            privateMethods.deactivate($dialog);
                        });
                    },

                    setBodyPadding: function (width) {
                        var originalBodyPadding = parseInt(($elements.body.css('padding-right') || 0), 10);
                        $elements.body.css('padding-right', (originalBodyPadding + width) + 'px');
                        $elements.body.data('ng-dialog-original-padding', originalBodyPadding);
                        $rootScope.$broadcast('ngDialog.setPadding', width);
                    },

                    resetBodyPadding: function () {
                        var originalBodyPadding = $elements.body.data('ng-dialog-original-padding');
                        if (originalBodyPadding) {
                            $elements.body.css('padding-right', originalBodyPadding + 'px');
                        } else {
                            $elements.body.css('padding-right', '');
                        }
                        $rootScope.$broadcast('ngDialog.setPadding', 0);
                    },

                    performCloseDialog: function ($dialog, value) {
                        var options = $dialog.data('$ngDialogOptions');
                        var id = $dialog.attr('id');
                        var scope = scopes[id];

                        if (!scope) {
                            // Already closed
                            return;
                        }

                        if (typeof $window.Hammer !== 'undefined') {
                            var hammerTime = scope.hammerTime;
                            hammerTime.off('tap', closeByDocumentHandler);
                            hammerTime.destroy && hammerTime.destroy();
                            delete scope.hammerTime;
                        } else {
                            $dialog.unbind('click');
                        }

                        if (dialogsCount === 1) {
                            $elements.body.unbind('keydown', privateMethods.onDocumentKeydown);
                        }

                        if (!$dialog.hasClass('ngdialog-closing')){
                            dialogsCount -= 1;
                        }

                        var previousFocus = $dialog.data('$ngDialogPreviousFocus');
                        if (previousFocus && previousFocus.focus) {
                            previousFocus.focus();
                        }

                        $rootScope.$broadcast('ngDialog.closing', $dialog, value);
                        dialogsCount = dialogsCount < 0 ? 0 : dialogsCount;
                        if (animationEndSupport && !options.disableAnimation) {
                            scope.$destroy();
                            $dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
                                privateMethods.closeDialogElement($dialog, value);
                            }).addClass('ngdialog-closing');
                        } else {
                            scope.$destroy();
                            privateMethods.closeDialogElement($dialog, value);
                        }
                        if (defers[id]) {
                            defers[id].resolve({
                                id: id,
                                value: value,
                                $dialog: $dialog,
                                remainingDialogs: dialogsCount
                            });
                            delete defers[id];
                        }
                        if (scopes[id]) {
                            delete scopes[id];
                        }
                        openIdStack.splice(openIdStack.indexOf(id), 1);
                        if (!openIdStack.length) {
                            $elements.body.unbind('keydown', privateMethods.onDocumentKeydown);
                            keydownIsBound = false;
                        }
                    },

                    closeDialogElement: function($dialog, value) {
                        var options = $dialog.data('$ngDialogOptions');
                        $dialog.remove();
                        if (dialogsCount === 0) {
                            $elements.html.removeClass(options.bodyClassName);
                            $elements.body.removeClass(options.bodyClassName);
                            privateMethods.resetBodyPadding();
                        }
                        $rootScope.$broadcast('ngDialog.closed', $dialog, value);
                    },

                    closeDialog: function ($dialog, value) {
                        var preCloseCallback = $dialog.data('$ngDialogPreCloseCallback');

                        if (preCloseCallback && angular.isFunction(preCloseCallback)) {

                            var preCloseCallbackResult = preCloseCallback.call($dialog, value);

                            if (angular.isObject(preCloseCallbackResult)) {
                                if (preCloseCallbackResult.closePromise) {
                                    preCloseCallbackResult.closePromise.then(function () {
                                        privateMethods.performCloseDialog($dialog, value);
                                    });
                                } else {
                                    preCloseCallbackResult.then(function () {
                                        privateMethods.performCloseDialog($dialog, value);
                                    }, function () {
                                        return;
                                    });
                                }
                            } else if (preCloseCallbackResult !== false) {
                                privateMethods.performCloseDialog($dialog, value);
                            }
                        } else {
                            privateMethods.performCloseDialog($dialog, value);
                        }
                    },

                    onTrapFocusKeydown: function(ev) {
                        var el = angular.element(ev.currentTarget);
                        var $dialog;

                        if (el.hasClass('ngdialog')) {
                            $dialog = el;
                        } else {
                            $dialog = privateMethods.getActiveDialog();

                            if ($dialog === null) {
                                return;
                            }
                        }

                        var isTab = (ev.keyCode === 9);
                        var backward = (ev.shiftKey === true);

                        if (isTab) {
                            privateMethods.handleTab($dialog, ev, backward);
                        }
                    },

                    handleTab: function($dialog, ev, backward) {
                        var focusableElements = privateMethods.getFocusableElements($dialog);

                        if (focusableElements.length === 0) {
                            if (document.activeElement) {
                                document.activeElement.blur();
                            }
                            return;
                        }

                        var currentFocus = document.activeElement;
                        var focusIndex = Array.prototype.indexOf.call(focusableElements, currentFocus);

                        var isFocusIndexUnknown = (focusIndex === -1);
                        var isFirstElementFocused = (focusIndex === 0);
                        var isLastElementFocused = (focusIndex === focusableElements.length - 1);

                        var cancelEvent = false;

                        if (backward) {
                            if (isFocusIndexUnknown || isFirstElementFocused) {
                                focusableElements[focusableElements.length - 1].focus();
                                cancelEvent = true;
                            }
                        } else {
                            if (isFocusIndexUnknown || isLastElementFocused) {
                                focusableElements[0].focus();
                                cancelEvent = true;
                            }
                        }

                        if (cancelEvent) {
                            ev.preventDefault();
                            ev.stopPropagation();
                        }
                    },

                    autoFocus: function($dialog) {
                        var dialogEl = $dialog[0];

                        // Browser's (Chrome 40, Forefix 37, IE 11) don't appear to honor autofocus on the dialog, but we should
                        var autoFocusEl = dialogEl.querySelector('*[autofocus]');
                        if (autoFocusEl !== null) {
                            autoFocusEl.focus();

                            if (document.activeElement === autoFocusEl) {
                                return;
                            }

                            // Autofocus element might was display: none, so let's continue
                        }

                        var focusableElements = privateMethods.getFocusableElements($dialog);

                        if (focusableElements.length > 0) {
                            focusableElements[0].focus();
                            return;
                        }

                        // We need to focus something for the screen readers to notice the dialog
                        var contentElements = privateMethods.filterVisibleElements(dialogEl.querySelectorAll('h1,h2,h3,h4,h5,h6,p,span'));

                        if (contentElements.length > 0) {
                            var contentElement = contentElements[0];
                            $el(contentElement).attr('tabindex', '-1').css('outline', '0');
                            contentElement.focus();
                        }
                    },

                    getFocusableElements: function ($dialog) {
                        var dialogEl = $dialog[0];

                        var rawElements = dialogEl.querySelectorAll(focusableElementSelector);

                        // Ignore untabbable elements, ie. those with tabindex = -1
                        var tabbableElements = privateMethods.filterTabbableElements(rawElements);

                        return privateMethods.filterVisibleElements(tabbableElements);
                    },

                    filterTabbableElements: function (els) {
                        var tabbableFocusableElements = [];

                        for (var i = 0; i < els.length; i++) {
                            var el = els[i];

                            if ($el(el).attr('tabindex') !== '-1') {
                                tabbableFocusableElements.push(el);
                            }
                        }

                        return tabbableFocusableElements;
                    },

                    filterVisibleElements: function (els) {
                        var visibleFocusableElements = [];

                        for (var i = 0; i < els.length; i++) {
                            var el = els[i];

                            if (el.offsetWidth > 0 || el.offsetHeight > 0) {
                                visibleFocusableElements.push(el);
                            }
                        }

                        return visibleFocusableElements;
                    },

                    getActiveDialog: function () {
                        var dialogs = document.querySelectorAll('.ngdialog');

                        if (dialogs.length === 0) {
                            return null;
                        }

                        // TODO: This might be incorrect if there are a mix of open dialogs with different 'appendTo' values
                        return $el(dialogs[dialogs.length - 1]);
                    },

                    applyAriaAttributes: function ($dialog, options) {
                        if (options.ariaAuto) {
                            if (!options.ariaRole) {
                                var detectedRole = (privateMethods.getFocusableElements($dialog).length > 0) ?
                                    'dialog' :
                                    'alertdialog';

                                options.ariaRole = detectedRole;
                            }

                            if (!options.ariaLabelledBySelector) {
                                options.ariaLabelledBySelector = 'h1,h2,h3,h4,h5,h6';
                            }

                            if (!options.ariaDescribedBySelector) {
                                options.ariaDescribedBySelector = 'article,section,p';
                            }
                        }

                        if (options.ariaRole) {
                            $dialog.attr('role', options.ariaRole);
                        }

                        privateMethods.applyAriaAttribute(
                            $dialog, 'aria-labelledby', options.ariaLabelledById, options.ariaLabelledBySelector);

                        privateMethods.applyAriaAttribute(
                            $dialog, 'aria-describedby', options.ariaDescribedById, options.ariaDescribedBySelector);
                    },

                    applyAriaAttribute: function($dialog, attr, id, selector) {
                        if (id) {
                            $dialog.attr(attr, id);
                        }

                        if (selector) {
                            var dialogId = $dialog.attr('id');

                            var firstMatch = $dialog[0].querySelector(selector);

                            if (!firstMatch) {
                                return;
                            }

                            var generatedId = dialogId + '-' + attr;

                            $el(firstMatch).attr('id', generatedId);

                            $dialog.attr(attr, generatedId);

                            return generatedId;
                        }
                    },

                    detectUIRouter: function() {
                        //Detect if ui-router module is installed if not return false
                        try {
                            angular.module('ui.router');
                            return true;
                        } catch(err) {
                            return false;
                        }
                    },

                    getRouterLocationEventName: function() {
                        if(privateMethods.detectUIRouter()) {
                            return '$stateChangeSuccess';
                        }
                        return '$locationChangeSuccess';
                    }
                };

                var publicMethods = {
                    __PRIVATE__: privateMethods,

                    /*
                     * @param {Object} options:
                     * - template {String} - id of ng-template, url for partial, plain string (if enabled)
                     * - plain {Boolean} - enable plain string templates, default false
                     * - scope {Object}
                     * - controller {String}
                     * - controllerAs {String}
                     * - className {String} - dialog theme class
                     * - appendClassName {String} - dialog theme class to be appended to defaults
                     * - disableAnimation {Boolean} - set to true to disable animation
                     * - showClose {Boolean} - show close button, default true
                     * - closeByEscape {Boolean} - default true
                     * - closeByDocument {Boolean} - default true
                     * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set)
                     * - bodyClassName {String} - class added to body at open dialog
                     * @return {Object} dialog
                     */
                    open: function (opts) {
                        var dialogID = null;
                        opts = opts || {};
                        if (openOnePerName && opts.name) {
                            dialogID = opts.name+' dialog';
                            if (this.isOpen(dialogID)) {
                                return;
                            }
                        }
                        var options = angular.copy(defaults);
                        var localID = ++globalID;
                        dialogID = dialogID || 'ngdialog' + localID;
                        openIdStack.push(dialogID);

                        // Merge opts.data with predefined via setDefaults
                        if (typeof options.data !== 'undefined') {
                            if (typeof opts.data === 'undefined') {
                                opts.data = {};
                            }
                            opts.data = angular.merge(angular.copy(options.data), opts.data);
                        }

                        angular.extend(options, opts);

                        var defer;
                        defers[dialogID] = defer = $q.defer();

                        var scope;
                        scopes[dialogID] = scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();

                        var $dialog, $dialogParent;

                        var resolve = angular.extend({}, options.resolve);

                        angular.forEach(resolve, function (value, key) {
                            resolve[key] = angular.isString(value) ? $injector.get(value) : $injector.invoke(value, null, null, key);
                        });

                        $q.all({
                            template: loadTemplate(options.template || options.templateUrl),
                            locals: $q.all(resolve)
                        }).then(function (setup) {
                            var template = setup.template,
                                locals = setup.locals;

                            if (options.showClose) {
                                template += '<div class="ngdialog-close"></div>';
                            }

                            var hasOverlayClass = options.overlay ? '' : ' ngdialog-no-overlay';
                            $dialog = $el('<div id="'+dialogID + '" class="ngdialog' + hasOverlayClass + '"></div>');
                            $dialog.html((options.overlay ?
                                '<div class="ngdialog-overlay"></div><div class="ngdialog-content" role="document">' + template + '</div>' :
                                '<div class="ngdialog-content" role="document">' + template + '</div>'));

                            $dialog.data('$ngDialogOptions', options);

                            scope.ngDialogId = dialogID;

                            if (options.data && angular.isString(options.data)) {
                                var firstLetter = options.data.replace(/^\s*/, '')[0];
                                scope.ngDialogData = (firstLetter === '{' || firstLetter === '[') ? angular.fromJson(options.data) : new String(options.data);
                                scope.ngDialogData.ngDialogId = dialogID;
                            } else if (options.data && angular.isObject(options.data)) {
                                scope.ngDialogData = options.data;
                                scope.ngDialogData.ngDialogId = dialogID;
                            }

                            if (options.className) {
                                $dialog.addClass(options.className);
                            }

                            if (options.appendClassName) {
                                $dialog.addClass(options.appendClassName);
                            }

                            if (options.disableAnimation) {
                                $dialog.addClass(disabledAnimationClass);
                            }

                            if (options.appendTo && angular.isString(options.appendTo)) {
                                $dialogParent = angular.element(document.querySelector(options.appendTo));
                            } else {
                                $dialogParent = $elements.body;
                            }

                            privateMethods.applyAriaAttributes($dialog, options);

                            if (options.preCloseCallback) {
                                var preCloseCallback;

                                if (angular.isFunction(options.preCloseCallback)) {
                                    preCloseCallback = options.preCloseCallback;
                                } else if (angular.isString(options.preCloseCallback)) {
                                    if (scope) {
                                        if (angular.isFunction(scope[options.preCloseCallback])) {
                                            preCloseCallback = scope[options.preCloseCallback];
                                        } else if (scope.$parent && angular.isFunction(scope.$parent[options.preCloseCallback])) {
                                            preCloseCallback = scope.$parent[options.preCloseCallback];
                                        } else if ($rootScope && angular.isFunction($rootScope[options.preCloseCallback])) {
                                            preCloseCallback = $rootScope[options.preCloseCallback];
                                        }
                                    }
                                }

                                if (preCloseCallback) {
                                    $dialog.data('$ngDialogPreCloseCallback', preCloseCallback);
                                }
                            }

                            scope.closeThisDialog = function (value) {
                                privateMethods.closeDialog($dialog, value);
                            };

                            if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {

                                var label;

                                if (options.controllerAs && angular.isString(options.controllerAs)) {
                                    label = options.controllerAs;
                                }

                                var controllerInstance = $controller(options.controller, angular.extend(
                                    locals,
                                    {
                                        $scope: scope,
                                        $element: $dialog
                                    }),
                                    true,
                                    label
                                );

                                if(options.bindToController) {
                                    angular.extend(controllerInstance.instance, {ngDialogId: scope.ngDialogId, ngDialogData: scope.ngDialogData, closeThisDialog: scope.closeThisDialog});
                                }

                                $dialog.data('$ngDialogControllerController', controllerInstance());
                            }

                            $timeout(function () {
                                var $activeDialogs = document.querySelectorAll('.ngdialog');
                                privateMethods.deactivateAll($activeDialogs);

                                $compile($dialog)(scope);
                                var widthDiffs = $window.innerWidth - $elements.body.prop('clientWidth');
                                $elements.html.addClass(options.bodyClassName);
                                $elements.body.addClass(options.bodyClassName);
                                var scrollBarWidth = widthDiffs - ($window.innerWidth - $elements.body.prop('clientWidth'));
                                if (scrollBarWidth > 0) {
                                    privateMethods.setBodyPadding(scrollBarWidth);
                                }
                                $dialogParent.append($dialog);

                                privateMethods.activate($dialog);

                                if (options.trapFocus) {
                                    privateMethods.autoFocus($dialog);
                                }

                                if (options.name) {
                                    $rootScope.$broadcast('ngDialog.opened', {dialog: $dialog, name: options.name});
                                } else {
                                    $rootScope.$broadcast('ngDialog.opened', $dialog);
                                }
                            });

                            if (!keydownIsBound) {
                                $elements.body.bind('keydown', privateMethods.onDocumentKeydown);
                                keydownIsBound = true;
                            }

                            if (options.closeByNavigation) {
                                var eventName = privateMethods.getRouterLocationEventName();
                                $rootScope.$on(eventName, function () {
                                    privateMethods.closeDialog($dialog);
                                });
                            }

                            if (options.preserveFocus) {
                                $dialog.data('$ngDialogPreviousFocus', document.activeElement);
                            }

                            closeByDocumentHandler = function (event) {
                                var isOverlay = options.closeByDocument ? $el(event.target).hasClass('ngdialog-overlay') : false;
                                var isCloseBtn = $el(event.target).hasClass('ngdialog-close');

                                if (isOverlay || isCloseBtn) {
                                    publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
                                }
                            };

                            if (typeof $window.Hammer !== 'undefined') {
                                var hammerTime = scope.hammerTime = $window.Hammer($dialog[0]);
                                hammerTime.on('tap', closeByDocumentHandler);
                            } else {
                                $dialog.bind('click', closeByDocumentHandler);
                            }

                            dialogsCount += 1;

                            return publicMethods;
                        });

                        return {
                            id: dialogID,
                            closePromise: defer.promise,
                            close: function (value) {
                                privateMethods.closeDialog($dialog, value);
                            }
                        };

                        function loadTemplateUrl (tmpl, config) {
                            $rootScope.$broadcast('ngDialog.templateLoading', tmpl);
                            return $http.get(tmpl, (config || {})).then(function(res) {
                                $rootScope.$broadcast('ngDialog.templateLoaded', tmpl);
                                return res.data || '';
                            });
                        }

                        function loadTemplate (tmpl) {
                            if (!tmpl) {
                                return 'Empty template';
                            }

                            if (angular.isString(tmpl) && options.plain) {
                                return tmpl;
                            }

                            if (typeof options.cache === 'boolean' && !options.cache) {
                                return loadTemplateUrl(tmpl, {cache: false});
                            }

                            return loadTemplateUrl(tmpl, {cache: $templateCache});
                        }
                    },

                    /*
                     * @param {Object} options:
                     * - template {String} - id of ng-template, url for partial, plain string (if enabled)
                     * - plain {Boolean} - enable plain string templates, default false
                     * - name {String}
                     * - scope {Object}
                     * - controller {String}
                     * - controllerAs {String}
                     * - className {String} - dialog theme class
                     * - appendClassName {String} - dialog theme class to be appended to defaults
                     * - showClose {Boolean} - show close button, default true
                     * - closeByEscape {Boolean} - default false
                     * - closeByDocument {Boolean} - default false
                     * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set); not called on confirm
                     * - bodyClassName {String} - class added to body at open dialog
                     *
                     * @return {Object} dialog
                     */
                    openConfirm: function (opts) {
                        var defer = $q.defer();
                        var options = angular.copy(defaults);

                        opts = opts || {};

                        // Merge opts.data with predefined via setDefaults
                        if (typeof options.data !== 'undefined') {
                            if (typeof opts.data === 'undefined') {
                                opts.data = {};
                            }
                            opts.data = angular.merge(angular.copy(options.data), opts.data);
                        }

                        angular.extend(options, opts);

                        options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
                        options.scope.confirm = function (value) {
                            defer.resolve(value);
                            var $dialog = $el(document.getElementById(openResult.id));
                            privateMethods.performCloseDialog($dialog, value);
                        };

                        var openResult = publicMethods.open(options);
                        if (openResult) {
                            openResult.closePromise.then(function (data) {
                                if (data) {
                                    return defer.reject(data.value);
                                }
                                return defer.reject();
                            });
                            return defer.promise;
                        }
                    },

                    isOpen: function(id) {
                        var $dialog = $el(document.getElementById(id));
                        return $dialog.length > 0;
                    },

                    /*
                     * @param {String} id
                     * @return {Object} dialog
                     */
                    close: function (id, value) {
                        var $dialog = $el(document.getElementById(id));

                        if ($dialog.length) {
                            privateMethods.closeDialog($dialog, value);
                        } else {
                            if (id === '$escape') {
                                var topDialogId = openIdStack[openIdStack.length - 1];
                                $dialog = $el(document.getElementById(topDialogId));
                                if ($dialog.data('$ngDialogOptions').closeByEscape) {
                                    privateMethods.closeDialog($dialog, '$escape');
                                }
                            } else {
                                publicMethods.closeAll(value);
                            }
                        }

                        return publicMethods;
                    },

                    closeAll: function (value) {
                        var $all = document.querySelectorAll('.ngdialog');

                        // Reverse order to ensure focus restoration works as expected
                        for (var i = $all.length - 1; i >= 0; i--) {
                            var dialog = $all[i];
                            privateMethods.closeDialog($el(dialog), value);
                        }
                    },

                    getOpenDialogs: function() {
                        return openIdStack;
                    },

                    getDefaults: function () {
                        return defaults;
                    }
                };

                angular.forEach(
                    ['html', 'body'],
                    function(elementName) {
                        $elements[elementName] = $document.find(elementName);
                        if (forceElementsReload[elementName]) {
                            var eventName = privateMethods.getRouterLocationEventName();
                            $rootScope.$on(eventName, function () {
                                $elements[elementName] = $document.find(elementName);
                            });
                        }
                    }
                );

                return publicMethods;
            }];
    });

    m.directive('ngDialog', ['ngDialog', function (ngDialog) {
        return {
            restrict: 'A',
            scope: {
                ngDialogScope: '='
            },
            link: function (scope, elem, attrs) {
                elem.on('click', function (e) {
                    e.preventDefault();

                    var ngDialogScope = angular.isDefined(scope.ngDialogScope) ? scope.ngDialogScope : 'noScope';
                    angular.isDefined(attrs.ngDialogClosePrevious) && ngDialog.close(attrs.ngDialogClosePrevious);

                    var defaults = ngDialog.getDefaults();

                    ngDialog.open({
                        template: attrs.ngDialog,
                        className: attrs.ngDialogClass || defaults.className,
                        appendClassName: attrs.ngDialogAppendClass,
                        controller: attrs.ngDialogController,
                        controllerAs: attrs.ngDialogControllerAs,
                        bindToController: attrs.ngDialogBindToController,
                        scope: ngDialogScope,
                        data: attrs.ngDialogData,
                        showClose: attrs.ngDialogShowClose === 'false' ? false : (attrs.ngDialogShowClose === 'true' ? true : defaults.showClose),
                        closeByDocument: attrs.ngDialogCloseByDocument === 'false' ? false : (attrs.ngDialogCloseByDocument === 'true' ? true : defaults.closeByDocument),
                        closeByEscape: attrs.ngDialogCloseByEscape === 'false' ? false : (attrs.ngDialogCloseByEscape === 'true' ? true : defaults.closeByEscape),
                        overlay: attrs.ngDialogOverlay === 'false' ? false : (attrs.ngDialogOverlay === 'true' ? true : defaults.overlay),
                        preCloseCallback: attrs.ngDialogPreCloseCallback || defaults.preCloseCallback,
                        bodyClassName: attrs.ngDialogBodyClass || defaults.bodyClassName
                    });
                });
            }
        };
    }]);

    return m;
}));

define("ngDialog", ["angular"], function(){});

vendors/angular-filter/dist/angular-filter.js
/**
 * Bunch of useful filters for angularJS(with no external dependencies!)
 * @version v0.5.17 - 2017-09-22 * @link https://github.com/a8m/angular-filter
 * @author Ariel Mashraki <[email protected]>
 * @license MIT License, http://www.opensource.org/licenses/MIT
 */
(function ( window, angular, undefined ) {
/*jshint globalstrict:true*/
'use strict';

var isDefined = angular.isDefined,
    isUndefined = angular.isUndefined,
    isFunction = angular.isFunction,
    isString = angular.isString,
    isNumber = angular.isNumber,
    isObject = angular.isObject,
    isArray = angular.isArray,
    forEach = angular.forEach,
    extend = angular.extend,
    copy = angular.copy,
    equals = angular.equals;


/**
 * @description
 * get an object and return array of values
 * @param object
 * @returns {Array}
 */
function toArray(object) {
  return isArray(object) 
    ? object 
    : Object.keys(object).map(function(key) {
      return object[key];
    });
}

/**
 * @param value
 * @returns {boolean}
 */
function isNull(value) {
    return value === null;
}

/**
 * @description
 * return if object contains partial object
 * @param partial{object}
 * @param object{object}
 * @returns {boolean}
 */
function objectContains(partial, object) {
  var keys = Object.keys(partial);

  return keys.map(function(el) {
    return (object[el] !== undefined) && (object[el] == partial[el]);
  }).indexOf(false) == -1;

}

/**
 * @description
 * search for approximate pattern in string
 * @param word
 * @param pattern
 * @returns {*}
 */
function hasApproxPattern(word, pattern) {
  // cheaper version of indexOf; instead of creating each
  // iteration new str.
  function indexOf(word, p, c) {
    var j = 0;
    while ((p + j) <= word.length) {
      if (word.charAt(p + j) == c) return j;
      j++;
    }
    return -1;
  }
  var p = 0;
  for (var i = 0; i <= pattern.length; i++) {
    var index = indexOf(word, p, pattern.charAt(i));
    if (index == -1) return false;
    p += index + 1;
  }
  return true
}

/**
 * @description
 * return the first n element of an array,
 * if expression provided, is returns as long the expression return truthy
 * @param array
 * @param n {number}
 * @param expression {$parse}
 * @return array or single object
 */
function getFirstMatches(array, n, expression) {
  var count = 0;

  return array.filter(function(elm) {
    var rest = isDefined(expression) ? (count < n && expression(elm)) : count < n;
    count = rest ? count+1 : count;

    return rest;
  });
}
/**
 * Polyfill to ECMA6 String.prototype.contains
 */
if (!String.prototype.contains) {
  String.prototype.contains = function() {
    return String.prototype.indexOf.apply(this, arguments) !== -1;
  };
}

/**
 * @param num {Number}
 * @param decimal {Number}
 * @returns {Number}
 */
function convertToDecimal(num, decimal){
  return Math.round(num * Math.pow(10,decimal)) / (Math.pow(10, decimal));
}

/**
 * @description
 * Get an object, and return an array composed of it's properties names(nested too).
 * @param obj {Object}
 * @param stack {Array}
 * @param parent {String}
 * @returns {Array}
 * @example
 * parseKeys({ a:1, b: { c:2, d: { e: 3 } } }) ==> ["a", "b.c", "b.d.e"]
 */
function deepKeys(obj, stack, parent) {
  stack = stack || [];
  var keys = Object.keys(obj);

  keys.forEach(function(el) {
    //if it's a nested object
    if(isObject(obj[el]) && !isArray(obj[el])) {
      //concatenate the new parent if exist
      var p = parent ? parent + '.' + el : parent;
      deepKeys(obj[el], stack, p || el);
    } else {
      //create and save the key
      var key = parent ? parent + '.' + el : el;
      stack.push(key)
    }
  });
  return stack
}

/**
 * @description
 * Test if given object is a Scope instance
 * @param obj
 * @returns {Boolean}
 */
function isScope(obj) {
  return obj && obj.$evalAsync && obj.$watch;
}

/**
 * @ngdoc filter
 * @name a8m.angular
 * @kind function
 *
 * @description
 * reference to angular function
 */

angular.module('a8m.angular', [])

    .filter('isUndefined', function () {
      return function (input) {
        return angular.isUndefined(input);
      }
    })
    .filter('isDefined', function() {
      return function (input) {
        return angular.isDefined(input);
      }
    })
    .filter('isFunction', function() {
      return function (input) {
        return angular.isFunction(input);
      }
    })
    .filter('isString', function() {
      return function (input) {
        return angular.isString(input)
      }
    })
    .filter('isNumber', function() {
      return function (input) {
        return angular.isNumber(input);
      }
    })
    .filter('isArray', function() {
      return function (input) {
        return angular.isArray(input);
      }
    })
    .filter('isObject', function() {
      return function (input) {
        return angular.isObject(input);
      }
    })
    .filter('isEqual', function() {
      return function (o1, o2) {
        return angular.equals(o1, o2);
      }
    });

/**
 * @ngdoc filter
 * @name a8m.conditions
 * @kind function
 *
 * @description
 * reference to math conditions
 */
 angular.module('a8m.conditions', [])

  .filter({
    isGreaterThan  : isGreaterThanFilter,
    '>'            : isGreaterThanFilter,

    isGreaterThanOrEqualTo  : isGreaterThanOrEqualToFilter,
    '>='                    : isGreaterThanOrEqualToFilter,

    isLessThan  : isLessThanFilter,
    '<'         : isLessThanFilter,

    isLessThanOrEqualTo  : isLessThanOrEqualToFilter,
    '<='                 : isLessThanOrEqualToFilter,

    isEqualTo  : isEqualToFilter,
    '=='       : isEqualToFilter,

    isNotEqualTo  : isNotEqualToFilter,
    '!='          : isNotEqualToFilter,

    isIdenticalTo  : isIdenticalToFilter,
    '==='          : isIdenticalToFilter,

    isNotIdenticalTo  : isNotIdenticalToFilter,
    '!=='             : isNotIdenticalToFilter
  });

  function isGreaterThanFilter() {
    return function (input, check) {
      return input > check;
    };
  }

  function isGreaterThanOrEqualToFilter() {
    return function (input, check) {
      return input >= check;
    };
  }

  function isLessThanFilter() {
    return function (input, check) {
      return input < check;
    };
  }

  function isLessThanOrEqualToFilter() {
    return function (input, check) {
      return input <= check;
    };
  }

  function isEqualToFilter() {
    return function (input, check) {
      return input == check;
    };
  }

  function isNotEqualToFilter() {
    return function (input, check) {
      return input != check;
    };
  }

  function isIdenticalToFilter() {
    return function (input, check) {
      return input === check;
    };
  }

  function isNotIdenticalToFilter() {
    return function (input, check) {
      return input !== check;
    };
  }
/**
 * @ngdoc filter
 * @name isNull
 * @kind function
 *
 * @description
 * checks if value is null or not
 * @return Boolean
 */
angular.module('a8m.is-null', [])
    .filter('isNull', function () {
      return function(input) {
        return isNull(input);
      }
    });

/**
 * @ngdoc filter
 * @name after-where
 * @kind function
 *
 * @description
 * get a collection and properties object, and returns all of the items
 * in the collection after the first that found with the given properties.
 *
 */
angular.module('a8m.after-where', [])
    .filter('afterWhere', function() {
      return function (collection, object) {

        collection = isObject(collection)
          ? toArray(collection)
          : collection;

        if(!isArray(collection) || isUndefined(object)) return collection;

        var index = collection.map( function( elm ) {
          return objectContains(object, elm);
        }).indexOf( true );

        return collection.slice((index === -1) ? 0 : index);
      }
    });

/**
 * @ngdoc filter
 * @name after
 * @kind function
 *
 * @description
 * get a collection and specified count, and returns all of the items
 * in the collection after the specified count.
 *
 */

angular.module('a8m.after', [])
    .filter('after', function() {
      return function (collection, count) {
        collection = isObject(collection)
          ? toArray(collection)
          : collection;

        return (isArray(collection))
          ? collection.slice(count)
          : collection;
      }
    });

/**
 * @ngdoc filter
 * @name before-where
 * @kind function
 *
 * @description
 * get a collection and properties object, and returns all of the items
 * in the collection before the first that found with the given properties.
 */
angular.module('a8m.before-where', [])
  .filter('beforeWhere', function() {
    return function (collection, object) {

      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      if(!isArray(collection) || isUndefined(object)) return collection;

      var index = collection.map( function( elm ) {
        return objectContains(object, elm);
      }).indexOf( true );

      return collection.slice(0, (index === -1) ? collection.length : ++index);
    }
  });

/**
 * @ngdoc filter
 * @name before
 * @kind function
 *
 * @description
 * get a collection and specified count, and returns all of the items
 * in the collection before the specified count.
 */
angular.module('a8m.before', [])
    .filter('before', function() {
      return function (collection, count) {
        collection = isObject(collection)
          ? toArray(collection)
          : collection;

        return (isArray(collection))
          ? collection.slice(0, (!count) ? count : --count)
          : collection;
      }
    });

/**
 * @ngdoc filter
 * @name chunkBy
 * @kind function
 *
 * @description
 * Collect data into fixed-length chunks or blocks
 */

angular.module('a8m.chunk-by', ['a8m.filter-watcher'])
    .filter('chunkBy', ['filterWatcher', function (filterWatcher) {
      return function (array, n, fillVal) {

        return filterWatcher.isMemoized('chunkBy', arguments) ||
            filterWatcher.memoize('chunkBy', arguments, this,
                _chunkBy(array, n, fillVal));
        /**
         * @description
         * Get array with size `n` in `val` inside it.
         * @param n
         * @param val
         * @returns {Array}
         */
        function fill(n, val) {
          var ret = [];
          while (n--) ret[n] = val;
          return ret;
        }

        function _chunkBy(array, n, fillVal) {
          if (!isArray(array)) return array;
          return array.map(function (el, i, self) {
            i = i * n;
            el = self.slice(i, i + n);
            return !isUndefined(fillVal) && el.length < n
                ? el.concat(fill(n - el.length, fillVal))
                : el;
          }).slice(0, Math.ceil(array.length / n));
        }
      }
    }]);

/**
 * @ngdoc filter
 * @name concat
 * @kind function
 *
 * @description
 * get (array/object, object/array) and return merged collection
 */
angular.module('a8m.concat', [])
  .filter('concat', [function () {
    return function (collection, joined) {

      if (isUndefined(joined)) return collection;

      if (isArray(collection)) {
        return isObject(joined)
          ? collection.concat(toArray(joined))
          : collection.concat(joined);
      }

      if (isObject(collection)) {
        var array = toArray(collection);
        return (isObject(joined))
          ? array.concat(toArray(joined))
          : array.concat(joined);
      }
      return collection;
    };
  }
]);

/**
 * @ngdoc filter
 * @name contains
 * @kind function
 *
 * @description
 * Checks if given expression is present in one or more object in the collection
 */
angular.module('a8m.contains', [])
  .filter({
    contains: ['$parse', containsFilter],
    some: ['$parse', containsFilter]
  });

function containsFilter($parse) {
    return function (collection, expression) {

      collection = isObject(collection) ? toArray(collection) : collection;

      if(!isArray(collection) || isUndefined(expression)) {
        return false;
      }

      return collection.some(function(elm) {
        return ((isString(expression) && isObject(elm)) || isFunction(expression))
          ? $parse(expression)(elm)
          : elm === expression;
      });

    }
 }

/**
 * @ngdoc filter
 * @name countBy
 * @kind function
 *
 * @description
 * Sorts a list into groups and returns a count for the number of objects in each group.
 */

angular.module('a8m.count-by', [])

  .filter('countBy', [ '$parse', function ( $parse ) {
    return function (collection, property) {

      var result = {},
        get = $parse(property),
        prop;

      collection = (isObject(collection)) ? toArray(collection) : collection;

      if(!isArray(collection) || isUndefined(property)) {
        return collection;
      }

      collection.forEach( function( elm ) {
        prop = get(elm);

        if(!result[prop]) {
          result[prop] = 0;
        }

        result[prop]++;
      });

      return result;
    }
  }]);

/**
 * @ngdoc filter
 * @name defaults
 * @kind function
 *
 * @description
 * defaultsFilter allows to specify a default fallback value for properties that resolve to undefined.
 */
angular.module('a8m.defaults', [])
  .filter('defaults', ['$parse', function( $parse ) {
    return function(collection, defaults) {

      collection = isObject(collection) ? toArray(collection) : collection;

      if(!isArray(collection) || !isObject(defaults)) {
        return collection;
      }

      var keys = deepKeys(defaults);

      collection.forEach(function(elm) {
        //loop through all the keys
        keys.forEach(function(key) {
          var getter = $parse(key);
          var setter = getter.assign;
          //if it's not exist
          if(isUndefined(getter(elm))) {
            //get from defaults, and set to the returned object
            setter(elm, getter(defaults))
          }
        });
      });

      return collection;
    }
  }]);
/**
 * @ngdoc filter
 * @name every
 * @kind function
 *
 * @description
 * Checks if given expression is present in all members in the collection
 *
 */
angular.module('a8m.every', [])
  .filter('every', ['$parse', function($parse) {
    return function (collection, expression) {
      collection = isObject(collection) ? toArray(collection) : collection;

      if(!isArray(collection) || isUndefined(expression)) {
        return true;
      }

      return collection.every( function(elm) {
        return (isObject(elm) || isFunction(expression))
          ? $parse(expression)(elm)
          : elm === expression;
      });
    }
  }]);

/**
 * @ngdoc filter
 * @name filterBy
 * @kind function
 *
 * @description
 * filter by specific properties, avoid the rest
 */
angular.module('a8m.filter-by', [])
  .filter('filterBy', ['$parse', function( $parse ) {
    return function(collection, properties, search, strict) {
      var comparator;

      search = (isString(search) || isNumber(search)) ?
        String(search).toLowerCase() : undefined;

      collection = isObject(collection) ? toArray(collection) : collection;

      if(!isArray(collection) || isUndefined(search)) {
        return collection;
      }

      return collection.filter(function(elm) {
        return properties.some(function(prop) {

          /**
           * check if there is concatenate properties
           * example:
           * object: { first: 'foo', last:'bar' }
           * filterBy: ['first + last'] => search by full name(i.e 'foo bar')
           */
          if(!~prop.indexOf('+')) {
            comparator = $parse(prop)(elm)
          } else {
            var propList = prop.replace(/\s+/g, '').split('+');
            comparator = propList
              .map(function(prop) { return $parse(prop)(elm); })
              .join(' ');
          }

          if (!isString(comparator) && !isNumber(comparator)) {
            return false;
          }

          comparator = String(comparator).toLowerCase();

          return strict ? comparator === search : comparator.contains(search);
        });
      });
    }
  }]);

/**
 * @ngdoc filter
 * @name first
 * @kind function
 *
 * @description
 * Gets the first element or first n elements of an array
 * if callback is provided, is returns as long the callback return truthy
 */
angular.module('a8m.first', [])
  .filter('first', ['$parse', function( $parse ) {
    return function(collection) {
      var n
        , getter
        , args;

      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      if(!isArray(collection)) {
        return collection;
      }

      args = Array.prototype.slice.call(arguments, 1);
      n = (isNumber(args[0])) ? args[0] : 1;
      getter = (!isNumber(args[0]))  ? args[0] : (!isNumber(args[1])) ? args[1] : undefined;

      return (args.length) ? getFirstMatches(collection, n,(getter) ? $parse(getter) : getter) :
        collection[0];
    }
  }]);

/**
 * @ngdoc filter
 * @name flatten
 * @kind function
 *
 * @description
 * Flattens a nested array (the nesting can be to any depth).
 * If you pass shallow, the array will only be flattened a single level
 */
angular.module('a8m.flatten', [])
  .filter('flatten', function () {
    return function(collection, shallow) {

      shallow = shallow || false;
      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      if(!isArray(collection)) {
        return collection;
      }

      return !shallow
        ? flatten(collection, 0)
        : [].concat.apply([], collection);
    }
  });

/**
 * flatten nested array (the nesting can be to any depth).
 * @param array {Array}
 * @param i {int}
 * @returns {Array}
 * @private
 */
function flatten(array, i) {
  i = i || 0;

  if(i >= array.length)
    return array;

  if(isArray(array[i])) {
    return flatten(array.slice(0,i)
      .concat(array[i], array.slice(i+1)), i);
  }
  return flatten(array, i+1);
}

/**
 * @ngdoc filter
 * @name fuzzyByKey
 * @kind function
 *
 * @description
 * fuzzy string searching by key
 */
angular.module('a8m.fuzzy-by', [])
  .filter('fuzzyBy', ['$parse', function ( $parse ) {
    return function (collection, property, search, csensitive) {

      var sensitive = csensitive || false,
        prop, getter;

      collection = isObject(collection) ? toArray(collection) : collection;

      if(!isArray(collection) || isUndefined(property)
        || isUndefined(search)) {
        return collection;
      }

      getter = $parse(property);

      return collection.filter(function(elm) {

        prop = getter(elm);
        if(!isString(prop)) {
          return false;
        }

        prop = (sensitive) ? prop : prop.toLowerCase();
        search = (sensitive) ? search : search.toLowerCase();

        return hasApproxPattern(prop, search) !== false
      })
    }

 }]);
/**
 * @ngdoc filter
 * @name fuzzy
 * @kind function
 *
 * @description
 * fuzzy string searching for array of strings, objects
 */
angular.module('a8m.fuzzy', [])
  .filter('fuzzy', function () {
    return function (collection, search, csensitive) {
      var sensitive = csensitive || false;
      collection = isObject(collection) ? toArray(collection) : collection;

      if(!isArray(collection) || isUndefined(search)) {
        return collection;
      }

      search = (sensitive) ? search : search.toLowerCase();

      return collection.filter(function(elm) {
        if(isString(elm)) {
          elm = (sensitive) ? elm : elm.toLowerCase();
          return hasApproxPattern(elm, search) !== false
        }
        return (isObject(elm)) ? _hasApproximateKey(elm, search) : false;
      });

      /**
       * checks if object has key{string} that match
       * to fuzzy search pattern
       * @param object
       * @param search
       * @returns {boolean}
       * @private
       */
      function _hasApproximateKey(object, search) {
        var properties = Object.keys(object),
          prop, flag;
        return 0 < properties.filter(function (elm) {
          prop = object[elm];

          //avoid iteration if we found some key that equal[performance]
          if(flag) return true;

          if (isString(prop)) {
            prop = (sensitive) ? prop : prop.toLowerCase();
            return flag = (hasApproxPattern(prop, search) !== false);
          }

          return false;

        }).length;
      }
    }
  });

/**
 * @ngdoc filter
 * @name groupBy
 * @kind function
 *
 * @description
 * Create an object composed of keys generated from the result of running each element of a collection,
 * each key is an array of the elements.
 */

angular.module('a8m.group-by', [ 'a8m.filter-watcher' ])
  .filter('groupBy', [ '$parse', 'filterWatcher', function ( $parse, filterWatcher ) {
    return function (collection, property) {

      if(!isObject(collection) || isUndefined(property)) {
        return collection;
      }

      return filterWatcher.isMemoized('groupBy', arguments) ||
        filterWatcher.memoize('groupBy', arguments, this,
          _groupBy(collection, $parse(property)));

      /**
       * groupBy function
       * @param collection
       * @param getter
       * @returns {{}}
       */
      function _groupBy(collection, getter) {
        var result = {};
        var prop;

        forEach( collection, function( elm ) {
          prop = getter(elm);

          if(!result[prop]) {
            result[prop] = [];
          }
          result[prop].push(elm);
        });
        return result;
      }
    }
 }]);

/**
 * @ngdoc filter
 * @name isEmpty
 * @kind function
 *
 * @description
 * get collection or string and return if it empty
 */
angular.module('a8m.is-empty', [])
  .filter('isEmpty', function () {
    return function(collection) {
      return isObject(collection)
        ? !toArray(collection).length
        : !collection.length;
    }
  });

/**
 * @ngdoc filter
 * @name join
 * @kind function
 *
 * @description
 * join a collection by a provided delimiter (space by default)
 */
angular.module('a8m.join', [])
  .filter('join', function () {
    return function (input, delimiter) {
      if (isUndefined(input) || !isArray(input)) {
        return input;
      }
      if (isUndefined(delimiter)) delimiter = ' ';

      return input.join(delimiter);
    };
  })
;

/**
 * @ngdoc filter
 * @name last
 * @kind function
 *
 * @description
 * Gets the last element or last n elements of an array
 * if callback is provided, is returns as long the callback return truthy
 */
angular.module('a8m.last', [])
  .filter('last', ['$parse', function( $parse ) {
    return function(collection) {
      var n
        , getter
        , args
        //cuz reverse change our src collection
        //and we don't want side effects
        , reversed = copy(collection);

      reversed = isObject(reversed)
        ? toArray(reversed)
        : reversed;

      if(!isArray(reversed)) {
        return reversed;
      }

      args = Array.prototype.slice.call(arguments, 1);
      n = (isNumber(args[0])) ? args[0] : 1;
      getter = (!isNumber(args[0]))  ? args[0] : (!isNumber(args[1])) ? args[1] : undefined;

      return (args.length)
        //send reversed collection as arguments, and reverse it back as result
        ? getFirstMatches(reversed.reverse(), n,(getter) ? $parse(getter) : getter).reverse()
        //get the last element
        : reversed[reversed.length-1];
    }
  }]);

/**
 * @ngdoc filter
 * @name map
 * @kind function
 *
 * @description
 * Returns a new collection of the results of each expression execution.
 */
angular.module('a8m.map', [])
  .filter('map', ['$parse', function($parse) {
    return function (collection, expression) {

      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      if(!isArray(collection) || isUndefined(expression)) {
        return collection;
      }

      return collection.map(function (elm) {
        return $parse(expression)(elm);
      });
    }
  }]);

/**
 * @ngdoc filter
 * @name omit
 * @kind function
 *
 * @description
 * filter collection by expression
 */

angular.module('a8m.omit', [])

  .filter('omit', ['$parse', function($parse) {
    return function (collection, expression) {

      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      if(!isArray(collection) || isUndefined(expression)) {
        return collection;
      }

      return collection.filter(function (elm) {
        return !($parse(expression)(elm));
      });
    }
  }]);

/**
 * @ngdoc filter
 * @name pick
 * @kind function
 *
 * @description
 * filter collection by expression
 */

angular.module('a8m.pick', [])

  .filter('pick', ['$parse', function($parse) {
    return function (collection, expression) {

      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      if(!isArray(collection) || isUndefined(expression)) {
        return collection;
      }

      return collection.filter(function (elm) {
        return $parse(expression)(elm);
      });
    }
  }]);

/**
 * @ngdoc filter
 * @name range
 * @kind function
 *
 * @description
 * rangeFilter provides some support for a for loop using numbers
 */
angular.module('a8m.range', [])
  .filter('range', function () {
    return function (input, total, start, increment, cb) {
      start = start || 0;
      increment = increment || 1;
      for (var i = 0; i < parseInt(total); i++) {
        var j = start + i * increment;
        input.push(isFunction(cb) ? cb(j) : j);
      }
      return input;
    };
  });
/**
 * @ngdoc filter
 * @name removeWith
 * @kind function
 *
 * @description
 * get collection and properties object, and removed elements
 * with this properties
 */

angular.module('a8m.remove-with', [])
  .filter('removeWith', function() {
    return function (collection, object) {

      if(isUndefined(object)) {
        return collection;
      }
      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      return collection.filter(function (elm) {
        return !objectContains(object, elm);
      });
    }
  });


/**
 * @ngdoc filter
 * @name remove
 * @kind function
 *
 * @description
 * remove specific members from collection
 */

angular.module('a8m.remove', [])

  .filter('remove', function () {
    return function (collection) {
      collection = isObject(collection) ? toArray(collection) : collection;
      var args = Array.prototype.slice.call(arguments, 1);

      if(!isArray(collection)) {
        return collection;
      }

      return collection.filter( function( member ) {
        return !args.some(function(nest) {
          return equals(nest, member);
        })
      });
    }
  });

/**
 * @ngdoc filter
 * @name reverse
 * @kind function
 *
 * @description
 * Reverses a string or collection
 */
angular.module('a8m.reverse', [])
    .filter('reverse',[ function () {
      return function (input) {
        input = isObject(input) ? toArray(input) : input;

        if(isString(input)) {
          return input.split('').reverse().join('');
        }

        return isArray(input)
          ? input.slice().reverse()
          : input;
      }
    }]);

/**
 * @ngdoc filter
 * @name searchField
 * @kind function
 *
 * @description
 * for each member, join several strings field and add them to
 * new field called 'searchField' (use for search filtering)
 */
angular.module('a8m.search-field', [])
  .filter('searchField', ['$parse', function ($parse) {
    return function (collection) {

      var get, field;

      collection = isObject(collection) ? toArray(collection) : collection;

      var args = Array.prototype.slice.call(arguments, 1);

      if(!isArray(collection) || !args.length) {
        return collection;
      }

      return collection.map(function(member) {

        field = args.map(function(field) {
          get = $parse(field);
          return get(member);
        }).join(' ');

        return extend(member, { searchField: field });
      });
    }
  }]);

/**
 * @ngdoc filter
 * @name toArray
 * @kind function
 *
 * @description
 * Convert objects into stable arrays.
 * if addKey set to true,the filter also attaches a new property
 * $key to the value containing the original key that was used in
 * the object we are iterating over to reference the property
 */
angular.module('a8m.to-array', [])
  .filter('toArray', function() {
    return function (collection, addKey) {

      if(!isObject(collection)) {
        return collection;
      }

      return !addKey
        ? toArray(collection)
        : Object.keys(collection).map(function (key) {
            return extend(collection[key], { $key: key });
          });
    }
  });

/**
 * @ngdoc filter
 * @name unique/uniq
 * @kind function
 *
 * @description
 * get collection and filter duplicate members
 * if uniqueFilter get a property(nested to) as argument it's
 * filter by this property as unique identifier
 */

angular.module('a8m.unique', [])
  .filter({
      unique: ['$parse', uniqFilter],
      uniq: ['$parse', uniqFilter]
    });

function uniqFilter($parse) {
    return function (collection, property) {

      collection = isObject(collection) ? toArray(collection) : collection;

      if (!isArray(collection)) {
        return collection;
      }

      //store all unique identifiers
      var uniqueItems = [],
          get = $parse(property);

      return (isUndefined(property))
        //if it's kind of primitive array
        ? collection.filter(function (elm, pos, self) {
          return self.indexOf(elm) === pos;
        })
        //else compare with equals
        : collection.filter(function (elm) {
          var prop = get(elm);
          if(some(uniqueItems, prop)) {
            return false;
          }
          uniqueItems.push(prop);
          return true;
      });

      //checked if the unique identifier is already exist
      function some(array, member) {
        if(isUndefined(member)) {
          return false;
        }
        return array.some(function(el) {
          return equals(el, member);
        });
      }
    }
}

/**
 * @ngdoc filter
 * @name where
 * @kind function
 *
 * @description
 * of each element in a collection to the given properties object,
 * returning an array of all elements that have equivalent property values.
 *
 */
angular.module('a8m.where', [])
  .filter('where', function() {
    return function (collection, object) {
      if(isUndefined(object)) return collection;
      collection = isObject(collection)
        ? toArray(collection)
        : collection;

      return collection.filter(function (elm) {
        return objectContains(object, elm);
      });
    }
  });

/**
 * @ngdoc filter
 * @name xor
 * @kind function
 *
 * @description
 * Exclusive or filter by expression
 */

angular.module('a8m.xor', [])

  .filter('xor', ['$parse', function($parse) {
    return function (col1, col2, expression) {

      expression = expression || false;

      col1 = isObject(col1) ? toArray(col1) : col1;
      col2 = isObject(col2) ? toArray(col2) : col2;

      if(!isArray(col1) || !isArray(col2)) return col1;

      return col1.concat(col2)
        .filter(function(elm) {
          return !(some(elm, col1) && some(elm, col2));
        });

      function some(el, col) {
        var getter = $parse(expression);
        return col.some(function(dElm) {
          return expression
            ? equals(getter(dElm), getter(el))
            : equals(dElm, el);
        });
      }
    }
  }]);

/**
 * @ngdoc filter
 * @name abs
 * @kind function
 *
 * @description
 * Will return the absolute value of a number
 */
angular.module('a8m.math.abs', [])
  .filter('abs', function () {
    return function (input) {
      return Math.abs(input);
    }
  });

/**
 * @ngdoc filter
 * @name formatBytes
 * @kind function
 *
 * @description
 * Convert bytes into appropriate display 
 * 1024 bytes => 1 KB
 */
angular.module('a8m.math.byteFmt', [])
  .filter('byteFmt', function () {
    var compared = [{str: 'B', val: 1024}];
    ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'].forEach(function(el, i) {
      compared.push({str: el, val: compared[i].val * 1024 });
    });
    return function (bytes, decimal) {
      if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
        isNumber(bytes) && isFinite(bytes)) {
        var i = 0;
        while (i < compared.length-1 && bytes >= compared[i].val) i++;
        bytes /= i > 0 ? compared[i-1].val : 1;
        return convertToDecimal(bytes, decimal) + ' ' + compared[i].str;
      }
      return 'NaN';
    }
  });

/**
 * @ngdoc filter
 * @name degrees
 * @kind function
 *
 * @description
 * Convert angle from radians to degrees
 */
angular.module('a8m.math.degrees', [])
  .filter('degrees', function () {
    return function (radians, decimal) {
      // if decimal is not an integer greater than -1, we cannot do. quit with error "NaN"
      // if degrees is not a real number, we cannot do also. quit with error "NaN"
      if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
        isNumber(radians) && isFinite(radians)) {
        var degrees = (radians * 180) / Math.PI;
        return Math.round(degrees * Math.pow(10,decimal)) / (Math.pow(10,decimal));
      } else {
        return 'NaN';
      }
    }
  });

 
 
/**
 * @ngdoc filter
 * @name formatBytes
 * @kind function
 *
 * @description
 * Convert bytes into appropriate display 
 * 1024 kilobytes => 1 MB
 */
angular.module('a8m.math.kbFmt', [])
  .filter('kbFmt', function () {
    var compared = [{str: 'KB', val: 1024}];
    ['MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'].forEach(function(el, i) {
      compared.push({str: el, val: compared[i].val * 1024 });
    });
    return function (bytes, decimal) {
      if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
        isNumber(bytes) && isFinite(bytes)) {
        var i = 0;
        while (i < compared.length-1 && bytes >= compared[i].val) i++;
        bytes /= i > 0 ? compared[i-1].val : 1;
        return convertToDecimal(bytes, decimal) + ' ' + compared[i].str;
      }
      return 'NaN';
    }
  });
/**
 * @ngdoc filter
 * @name max
 * @kind function
 *
 * @description
 * Math.max will get an array and return the max value. if an expression
 * is provided, will return max value by expression.
 */
angular.module('a8m.math.max', [])
  .filter('max', ['$parse', function ($parse) {
    return function (input, expression) {

      if(!isArray(input)) {
        return input;
      }
      return isUndefined(expression)
        ? Math.max.apply(Math, input)
        : input[indexByMax(input, expression)];
    };

    /**
     * @private
     * @param array
     * @param exp
     * @returns {number|*|Number}
     */
    function indexByMax(array, exp) {
      var mappedArray = array.map(function(elm){
        return $parse(exp)(elm);
      });
      return mappedArray.indexOf(Math.max.apply(Math, mappedArray));
    }
  }]);
/**
 * @ngdoc filter
 * @name min
 * @kind function
 *
 * @description
 * Math.min will get an array and return the min value. if an expression
 * is provided, will return min value by expression.
 */
angular.module('a8m.math.min', [])
  .filter('min', ['$parse', function ($parse) {
    return function (input, expression) {

      if(!isArray(input)) {
        return input;
      }
      return isUndefined(expression)
        ? Math.min.apply(Math, input)
        : input[indexByMin(input, expression)];
    };

    /**
     * @private
     * @param array
     * @param exp
     * @returns {number|*|Number}
     */
    function indexByMin(array, exp) {
      var mappedArray = array.map(function(elm){
        return $parse(exp)(elm);
      });
      return mappedArray.indexOf(Math.min.apply(Math, mappedArray));
    }
  }]);
/**
 * @ngdoc filter
 * @name Percent
 * @kind function
 *
 * @description
 * percentage between two numbers
 */
angular.module('a8m.math.percent', [])
  .filter('percent', function () {
    return function (input, divided, round) {

      var divider = isString(input) ? Number(input) : input;
      divided = divided || 100;
      round = round || false;

      if (!isNumber(divider) || isNaN(divider)) return input;

      return round
        ? Math.round((divider / divided) * 100)
        : (divider / divided) * 100;
    }
  });

/**
 * @ngdoc filter
 * @name toRadians
 * @kind function
 *
 * @description
 * Convert angle from degrees to radians
 */
angular.module('a8m.math.radians', [])
  .filter('radians', function() {
    return function (degrees, decimal) {
      // if decimal is not an integer greater than -1, we cannot do. quit with error "NaN"
      // if degrees is not a real number, we cannot do also. quit with error "NaN"
      if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
        isNumber(degrees) && isFinite(degrees)) {
        var radians = (degrees * 3.14159265359) / 180;
        return Math.round(radians * Math.pow(10,decimal)) / (Math.pow(10,decimal));
      }
      return 'NaN';
    }
  });

 
 
/**
 * @ngdoc filter
 * @name Radix
 * @kind function
 *
 * @description
 * converting decimal numbers to different bases(radix)
 */
angular.module('a8m.math.radix', [])
  .filter('radix', function () {
    return function (input, radix) {
      var RANGE = /^[2-9]$|^[1-2]\d$|^3[0-6]$/;

      if(!isNumber(input) || !RANGE.test(radix)) {
        return input;
      }

      return input.toString(radix).toUpperCase();
    }
  });

/**
 * @ngdoc filter
 * @name formatBytes
 * @kind function
 *
 * @description
 * Convert number into abbreviations.
 * i.e: K for one thousand, M for Million, B for billion
 * e.g: number of users:235,221, decimal:1 => 235.2 K
 */
angular.module('a8m.math.shortFmt', [])
  .filter('shortFmt', function () {
    return function (number, decimal) {
      if(isNumber(decimal) && isFinite(decimal) && decimal%1===0 && decimal >= 0 &&
        isNumber(number) && isFinite(number)){
        if(number < 1e3) {
          return '' + number;  // Coerce to string
        } else if(number < 1e6) {
          return convertToDecimal((number / 1e3), decimal) + ' K';
        } else if(number < 1e9){
          return convertToDecimal((number / 1e6), decimal) + ' M';
        } else {
          return convertToDecimal((number / 1e9), decimal) + ' B';
        }

      }
      return 'NaN';
    }
  });
/**
 * @ngdoc filter
 * @name sum
 * @kind function
 *
 * @description
 * Sum up all values within an array
 */
angular.module('a8m.math.sum', [])
  .filter('sum', function () {
    return function (input, initial) {
      return !isArray(input)
        ? input
        : input.reduce(function(prev, curr) {
          return prev + curr;
        }, initial || 0);
    }
  });

/**
 * @ngdoc filter
 * @name endsWith
 * @kind function
 *
 * @description
 * checks whether string ends with the ends parameter.
 */
angular.module('a8m.ends-with', [])

  .filter('endsWith', function () {
    return function (input, ends, csensitive) {

      var sensitive = csensitive || false,
        position;

      if(!isString(input) || isUndefined(ends)) {
        return input;
      }

      input = (sensitive) ? input : input.toLowerCase();
      position = input.length - ends.length;

      return input.indexOf((sensitive) ? ends : ends.toLowerCase(), position) !== -1;
    }
  });

/**
 * @ngdoc filter
 * @name latinize
 * @kind function
 *
 * @description
 * remove accents/diacritics from a string
 */
angular.module('a8m.latinize', [])
  .filter('latinize',[ function () {
    var defaultDiacriticsRemovalap = [
      {'base':'A', 'letters':'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
      {'base':'AA','letters':'\uA732'},
      {'base':'AE','letters':'\u00C6\u01FC\u01E2'},
      {'base':'AO','letters':'\uA734'},
      {'base':'AU','letters':'\uA736'},
      {'base':'AV','letters':'\uA738\uA73A'},
      {'base':'AY','letters':'\uA73C'},
      {'base':'B', 'letters':'\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
      {'base':'C', 'letters':'\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
      {'base':'D', 'letters':'\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'},
      {'base':'DZ','letters':'\u01F1\u01C4'},
      {'base':'Dz','letters':'\u01F2\u01C5'},
      {'base':'E', 'letters':'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
      {'base':'F', 'letters':'\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
      {'base':'G', 'letters':'\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
      {'base':'H', 'letters':'\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
      {'base':'I', 'letters':'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
      {'base':'J', 'letters':'\u004A\u24BF\uFF2A\u0134\u0248'},
      {'base':'K', 'letters':'\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
      {'base':'L', 'letters':'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
      {'base':'LJ','letters':'\u01C7'},
      {'base':'Lj','letters':'\u01C8'},
      {'base':'M', 'letters':'\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
      {'base':'N', 'letters':'\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
      {'base':'NJ','letters':'\u01CA'},
      {'base':'Nj','letters':'\u01CB'},
      {'base':'O', 'letters':'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
      {'base':'OI','letters':'\u01A2'},
      {'base':'OO','letters':'\uA74E'},
      {'base':'OU','letters':'\u0222'},
      {'base':'OE','letters':'\u008C\u0152'},
      {'base':'oe','letters':'\u009C\u0153'},
      {'base':'P', 'letters':'\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
      {'base':'Q', 'letters':'\u0051\u24C6\uFF31\uA756\uA758\u024A'},
      {'base':'R', 'letters':'\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
      {'base':'S', 'letters':'\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
      {'base':'T', 'letters':'\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
      {'base':'TZ','letters':'\uA728'},
      {'base':'U', 'letters':'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
      {'base':'V', 'letters':'\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
      {'base':'VY','letters':'\uA760'},
      {'base':'W', 'letters':'\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
      {'base':'X', 'letters':'\u0058\u24CD\uFF38\u1E8A\u1E8C'},
      {'base':'Y', 'letters':'\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
      {'base':'Z', 'letters':'\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
      {'base':'a', 'letters':'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'},
      {'base':'aa','letters':'\uA733'},
      {'base':'ae','letters':'\u00E6\u01FD\u01E3'},
      {'base':'ao','letters':'\uA735'},
      {'base':'au','letters':'\uA737'},
      {'base':'av','letters':'\uA739\uA73B'},
      {'base':'ay','letters':'\uA73D'},
      {'base':'b', 'letters':'\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
      {'base':'c', 'letters':'\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
      {'base':'d', 'letters':'\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
      {'base':'dz','letters':'\u01F3\u01C6'},
      {'base':'e', 'letters':'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
      {'base':'f', 'letters':'\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
      {'base':'g', 'letters':'\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
      {'base':'h', 'letters':'\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
      {'base':'hv','letters':'\u0195'},
      {'base':'i', 'letters':'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
      {'base':'j', 'letters':'\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
      {'base':'k', 'letters':'\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
      {'base':'l', 'letters':'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
      {'base':'lj','letters':'\u01C9'},
      {'base':'m', 'letters':'\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
      {'base':'n', 'letters':'\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'},
      {'base':'nj','letters':'\u01CC'},
      {'base':'o', 'letters':'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
      {'base':'oi','letters':'\u01A3'},
      {'base':'ou','letters':'\u0223'},
      {'base':'oo','letters':'\uA74F'},
      {'base':'p','letters':'\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
      {'base':'q','letters':'\u0071\u24E0\uFF51\u024B\uA757\uA759'},
      {'base':'r','letters':'\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
      {'base':'s','letters':'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
      {'base':'t','letters':'\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
      {'base':'tz','letters':'\uA729'},
      {'base':'u','letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
      {'base':'v','letters':'\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
      {'base':'vy','letters':'\uA761'},
      {'base':'w','letters':'\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
      {'base':'x','letters':'\u0078\u24E7\uFF58\u1E8B\u1E8D'},
      {'base':'y','letters':'\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
      {'base':'z','letters':'\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
    ];

    var diacriticsMap = {};
    for (var i = 0; i < defaultDiacriticsRemovalap.length; i++) {
      var letters = defaultDiacriticsRemovalap[i].letters.split("");
      for (var j = 0; j < letters.length ; j++){
        diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base;
      }
    }

    // "what?" version ... http://jsperf.com/diacritics/12
    function removeDiacritics (str) {
      return str.replace(/[^\u0000-\u007E]/g, function(a){
        return diacriticsMap[a] || a;
      });
    }

    return function (input) {

      return isString(input)
        ? removeDiacritics(input)
        : input;
    }
  }]);

/**
 * @ngdoc filter
 * @name ltrim
 * @kind function
 *
 * @description
 * Left trim. Similar to trimFilter, but only for left side.
 */
angular.module('a8m.ltrim', [])
  .filter('ltrim', function () {
    return function(input, chars) {

      var trim = chars || '\\s';

      return isString(input)
        ? input.replace(new RegExp('^' + trim + '+'), '')
        : input;
    }
  });

/**
 * @ngdoc filter
 * @name match
 * @kind function
 *
 * @description
 * Return the matched pattern in a string.
 */
angular.module('a8m.match', [])
  .filter('match', function () {
    return function (input, pattern, flag) {

      var reg = new RegExp(pattern, flag);

      return isString(input)
        ? input.match(reg)
        : null;
    }
  });

/**
 * @ngdoc filter
 * @name phone-us
 * @kind function
 *
 * @description
 * format a string or a number into a us-style
 * phone number in the form (***) ***-****
 */
angular.module('a8m.phoneUS', [])
  .filter('phoneUS', function () {
    return function(num) {
      num += '';
      return '(' + num.slice(0, 3) + ') ' + num.slice(3, 6) + '-' + num.slice(6);
    }
  });

/**
 * @ngdoc filter
 * @name repeat
 * @kind function
 *
 * @description
 * Repeats a string n times
 */
angular.module('a8m.repeat', [])
  .filter('repeat',[ function () {
    return function (input, n, separator) {

      var times = ~~n;

      if(!isString(input)) {
        return input;
      }

      return !times
        ? input
        : strRepeat(input, --n, separator || '');
    }
  }]);

/**
 * Repeats a string n times with given separator
 * @param str string to repeat
 * @param n number of times
 * @param sep separator
 * @returns {*}
 */
function strRepeat(str, n, sep) {
  if(!n) {
    return str;
  }
  return str + sep + strRepeat(str, --n, sep);
}
/**
* @ngdoc filter
* @name rtrim
* @kind function
*
* @description
* Right trim. Similar to trimFilter, but only for right side.
*/
angular.module('a8m.rtrim', [])
  .filter('rtrim', function () {
    return function(input, chars) {

      var trim = chars || '\\s';

      return isString(input)
        ? input.replace(new RegExp(trim + '+$'), '')
        : input;
    }
  });

/**
 * @ngdoc filter
 * @name slugify
 * @kind function
 *
 * @description
 * remove spaces from string, replace with "-" or given argument
 */
angular.module('a8m.slugify', [])
  .filter('slugify',[ function () {
    return function (input, sub) {

      var replace = (isUndefined(sub)) ? '-' : sub;

      return isString(input)
        ? input.toLowerCase().replace(/\s+/g, replace)
        : input;
    }
  }]);

/**
 * @ngdoc filter
 * @name split
 * @kind function
 *
 * @description
 * split a string by a provided delimiter (none '' by default) and skip first n-delimiters
 */
angular.module('a8m.split', [])
  .filter('split', function () {
    function escapeRegExp(str) {
      return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    }

    return function (input, delimiter, skip) {
      var _regexp, _matches, _splitted, _temp;

      if (isUndefined(input) || !isString(input)) {
        return null;
      }
      if (isUndefined(delimiter)) delimiter = '';
      if (isNaN(skip)) skip = 0;

      _regexp = new RegExp(escapeRegExp(delimiter), 'g');
      _matches = input.match(_regexp);
      
      if (isNull(_matches) || skip >= _matches.length) {
        return [input];
      }

      if (skip === 0) return input.split(delimiter);
      
      _splitted = input.split(delimiter);
      _temp = _splitted.splice(0, skip + 1);
      _splitted.unshift(_temp.join(delimiter));
    
      return _splitted;
    };
  })
;

/**
 * @ngdoc filter
 * @name startWith
 * @kind function
 *
 * @description
 * checks whether string starts with the starts parameter.
 */
angular.module('a8m.starts-with', [])
  .filter('startsWith', function () {
    return function (input, start, csensitive) {

      var sensitive = csensitive || false;

      if(!isString(input) || isUndefined(start)) {
        return input;
      }

      input = (sensitive) ? input : input.toLowerCase();

      return !input.indexOf((sensitive) ? start : start.toLowerCase());
    }
  });

/**
 * @ngdoc filter
 * @name stringular
 * @kind function
 *
 * @description
 * get string with {n} and replace match with enumeration values
 */
angular.module('a8m.stringular', [])
  .filter('stringular', function () {
    return function(input) {

      var args = Array.prototype.slice.call(arguments, 1);

      return input.replace(/{(\d+)}/g, function (match, number) {
        return isUndefined(args[number]) ? match : args[number];
      });
    }
  });

/**
 * @ngdoc filter
 * @name stripTags
 * @kind function
 *
 * @description
 * strip html tags from string
 */
angular.module('a8m.strip-tags', [])
  .filter('stripTags', function () {
    return function(input) {
      return isString(input)
        ? input.replace(/<\S[^><]*>/g, '')
        : input;
    }
  });

/**
 * @ngdoc filter
 * @name test
 * @kind function
 *
 * @description
 * test if a string match a pattern.
 */
angular.module('a8m.test', [])
  .filter('test', function () {
    return function (input, pattern, flag) {

      var reg = new RegExp(pattern, flag);

      return isString(input)
        ? reg.test(input)
        : input;
    }
  });

/**
 * @ngdoc filter
 * @name trim
 * @kind function
 *
 * @description
 *  Strip whitespace (or other characters) from the beginning and end of a string
 */
angular.module('a8m.trim', [])
  .filter('trim', function () {
    return function(input, chars) {

      var trim = chars || '\\s';

      return isString(input)
        ? input.replace(new RegExp('^' + trim + '+|' + trim + '+$', 'g'), '')
        : input;
    }
  });

/**
 * @ngdoc filter
 * @name truncate
 * @kind function
 *
 * @description
 * truncates a string given a specified length, providing a custom string to denote an omission.
 */
angular.module('a8m.truncate', [])
  .filter('truncate', function () {
    return function(input, length, suffix, preserve) {

      length = isUndefined(length) ? input.length : length;
      preserve = preserve || false;
      suffix = suffix || '';

      if(!isString(input) || (input.length <= length)) return input;

      return input.substring(0, (preserve)
        ? ((input.indexOf(' ', length) === -1) ? input.length : input.indexOf(' ', length))
        : length) + suffix;
    };
  });

/**
 * @ngdoc filter
 * @name ucfirst
 * @kind function
 *
 * @description
 * ucfirst
 */
angular.module('a8m.ucfirst', [])
  .filter({
    ucfirst: ucfirstFilter,
    titleize: ucfirstFilter
  });

function ucfirstFilter() {
  return function (input) {
    return isString(input)
      ? input
      .split(' ')
      .map(function (ch) {
        return ch.charAt(0).toUpperCase() + ch.substring(1);
      })
      .join(' ')
      : input;
  }
}

/**
 * @ngdoc filter
 * @name uriComponentEncode
 * @kind function
 *
 * @description
 * get string as parameter and return encoded string
 */
angular.module('a8m.uri-component-encode', [])
  .filter('uriComponentEncode',['$window', function ($window) {
      return function (input) {
        return isString(input)
          ? $window.encodeURIComponent(input)
          : input;
      }
    }]);

/**
 * @ngdoc filter
 * @name uriEncode
 * @kind function
 *
 * @description
 * get string as parameter and return encoded string
 */
angular.module('a8m.uri-encode', [])
  .filter('uriEncode',['$window', function ($window) {
      return function (input) {
        return isString(input)
          ? $window.encodeURI(input)
          : input;
      }
    }]);

/**
 * @ngdoc filter
 * @name wrap
 * @kind function
 *
 * @description
 * Wrap a string with another string
 */
angular.module('a8m.wrap', [])
  .filter('wrap', function () {
    return function(input, wrap, ends) {
      return isString(input) && isDefined(wrap)
        ? [wrap, input, ends || wrap].join('')
        : input;
    }
  });

/**
 * @ngdoc provider
 * @name filterWatcher
 * @kind function
 *
 * @description
 * store specific filters result in $$cache, based on scope life time(avoid memory leak).
 * on scope.$destroy remove it's cache from $$cache container
 */

angular.module('a8m.filter-watcher', [])
  .provider('filterWatcher', function() {

    this.$get = ['$window', '$rootScope', function($window, $rootScope) {

      /**
       * Cache storing
       * @type {Object}
       */
      var $$cache = {};

      /**
       * Scope listeners container
       * scope.$destroy => remove all cache keys
       * bind to current scope.
       * @type {Object}
       */
      var $$listeners = {};

      /**
       * $timeout without triggering the digest cycle
       * @type {function}
       */
      var $$timeout = $window.setTimeout;

      /**
       * @description
       * get `HashKey` string based on the given arguments.
       * @param fName
       * @param args
       * @returns {string}
       */
      function getHashKey(fName, args) {
        function replacerFactory() {
          var cache = [];
          return function(key, val) {
            if(isObject(val) && !isNull(val)) {
              if (~cache.indexOf(val)) return '[Circular]';
              cache.push(val)
            }
            if($window == val) return '$WINDOW';
            if($window.document == val) return '$DOCUMENT';
            if(isScope(val)) return '$SCOPE';
            return val;
          }
        }
        return [fName, JSON.stringify(args, replacerFactory())]
          .join('#')
          .replace(/"/g,'');
      }

      /**
       * @description
       * fir on $scope.$destroy,
       * remove cache based scope from `$$cache`,
       * and remove itself from `$$listeners`
       * @param event
       */
      function removeCache(event) {
        var id = event.targetScope.$id;
        forEach($$listeners[id], function(key) {
          delete $$cache[key];
        });
        delete $$listeners[id];
      }

      /**
       * @description
       * for angular version that greater than v.1.3.0
       * it clear cache when the digest cycle is end.
       */
      function cleanStateless() {
        $$timeout(function() {
          if(!$rootScope.$$phase)
            $$cache = {};
        }, 2000);
      }

      /**
       * @description
       * Store hashKeys in $$listeners container
       * on scope.$destroy, remove them all(bind an event).
       * @param scope
       * @param hashKey
       * @returns {*}
       */
      function addListener(scope, hashKey) {
        var id = scope.$id;
        if(isUndefined($$listeners[id])) {
          scope.$on('$destroy', removeCache);
          $$listeners[id] = [];
        }
        return $$listeners[id].push(hashKey);
      }

      /**
       * @description
       * return the `cacheKey` or undefined.
       * @param filterName
       * @param args
       * @returns {*}
       */
      function $$isMemoized(filterName, args) {
        var hashKey = getHashKey(filterName, args);
        return $$cache[hashKey];
      }

      /**
       * @description
       * store `result` in `$$cache` container, based on the hashKey.
       * add $destroy listener and return result
       * @param filterName
       * @param args
       * @param scope
       * @param result
       * @returns {*}
       */
      function $$memoize(filterName, args, scope, result) {
        var hashKey = getHashKey(filterName, args);
        //store result in `$$cache` container
        $$cache[hashKey] = result;
        // for angular versions that less than 1.3
        // add to `$destroy` listener, a cleaner callback
        if(isScope(scope)) {
          addListener(scope, hashKey);
        } else {
          cleanStateless();
        }
        return result;
      }

      return {
        isMemoized: $$isMemoized,
        memoize: $$memoize
      }
    }];
  });
  

/**
 * @ngdoc module
 * @name angular.filters
 * @description
 * Bunch of useful filters for angularJS
 */

angular.module('angular.filter', [

  'a8m.ucfirst',
  'a8m.uri-encode',
  'a8m.uri-component-encode',
  'a8m.slugify',
  'a8m.latinize',
  'a8m.strip-tags',
  'a8m.stringular',
  'a8m.truncate',
  'a8m.starts-with',
  'a8m.ends-with',
  'a8m.wrap',
  'a8m.trim',
  'a8m.ltrim',
  'a8m.rtrim',
  'a8m.repeat',
  'a8m.test',
  'a8m.match',
  'a8m.split',
  'a8m.phoneUS',

  'a8m.to-array',
  'a8m.concat',
  'a8m.contains',
  'a8m.unique',
  'a8m.is-empty',
  'a8m.after',
  'a8m.after-where',
  'a8m.before',
  'a8m.before-where',
  'a8m.defaults',
  'a8m.where',
  'a8m.reverse',
  'a8m.remove',
  'a8m.remove-with',
  'a8m.group-by',
  'a8m.count-by',
  'a8m.chunk-by',
  'a8m.search-field',
  'a8m.fuzzy-by',
  'a8m.fuzzy',
  'a8m.omit',
  'a8m.pick',
  'a8m.every',
  'a8m.filter-by',
  'a8m.xor',
  'a8m.map',
  'a8m.first',
  'a8m.last',
  'a8m.flatten',
  'a8m.join',
  'a8m.range',

  'a8m.math.max',
  'a8m.math.min',
  'a8m.math.abs',
  'a8m.math.percent',
  'a8m.math.radix',
  'a8m.math.sum',
  'a8m.math.degrees',
  'a8m.math.radians',
  'a8m.math.byteFmt',
  'a8m.math.kbFmt',
  'a8m.math.shortFmt',

  'a8m.angular',
  'a8m.conditions',
  'a8m.is-null',

  'a8m.filter-watcher'
]);
})( window, window.angular );
define("angularFilter", ["angular"], function(){});

vendors/tvg-common/dist/TVGCommon.umd.min.js
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("angular"), require("lodash"));
	else if(typeof define === 'function' && define.amd)
		define('TVGCommon',["angular", "lodash"], factory);
	else if(typeof exports === 'object')
		exports["TVGCommon"] = factory(require("angular"), require("lodash"));
	else
		root["TVGCommon"] = factory(root["angular"], root["_"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_125__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.l = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// identity function for calling harmony imports with the correct context
/******/ 	__webpack_require__.i = function(value) { return value; };

/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};

/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};

/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 126);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(42),
    isLength = __webpack_require__(7),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var arrayTag = '[object Array]';

/** Used for native method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objToString = objectProto.toString;

/* Native method references for those with the same name as other `lodash` methods. */
var nativeIsArray = getNative(Array, 'isArray');

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(function() { return arguments; }());
 * // => false
 */
var isArray = nativeIsArray || function(value) {
  return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
};

module.exports = isArray;


/***/ }),
/* 1 */
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_1__;

/***/ }),
/* 2 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is object-like.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

module.exports = isObjectLike;


/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(4);

/**
 * Converts `value` to an object if it's not one.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {Object} Returns the object.
 */
function toObject(value) {
  return isObject(value) ? value : Object(value);
}

module.exports = toObject;


/***/ }),
/* 4 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(1);
 * // => false
 */
function isObject(value) {
  // Avoid a V8 JIT bug in Chrome 19-20.
  // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

module.exports = isObject;


/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(42),
    isArrayLike = __webpack_require__(6),
    isObject = __webpack_require__(4),
    shimKeys = __webpack_require__(108);

/* Native method references for those with the same name as other `lodash` methods. */
var nativeKeys = getNative(Object, 'keys');

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
var keys = !nativeKeys ? shimKeys : function(object) {
  var Ctor = object == null ? undefined : object.constructor;
  if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
      (typeof object != 'function' && isArrayLike(object))) {
    return shimKeys(object);
  }
  return isObject(object) ? nativeKeys(object) : [];
};

module.exports = keys;


/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {

var getLength = __webpack_require__(17),
    isLength = __webpack_require__(7);

/**
 * Checks if `value` is array-like.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 */
function isArrayLike(value) {
  return value != null && isLength(getLength(value));
}

module.exports = isArrayLike;


/***/ }),
/* 7 */
/***/ (function(module, exports) {

/**
 * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
 * of an array-like value.
 */
var MAX_SAFE_INTEGER = 9007199254740991;

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 */
function isLength(value) {
  return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

module.exports = isLength;


/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {

var isArrayLike = __webpack_require__(6),
    isObjectLike = __webpack_require__(2);

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Native method references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;

/**
 * Checks if `value` is classified as an `arguments` object.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  return isObjectLike(value) && isArrayLike(value) &&
    hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
}

module.exports = isArguments;


/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {

var baseForOwn = __webpack_require__(83),
    createBaseEach = __webpack_require__(39);

/**
 * The base implementation of `_.forEach` without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array|Object|string} Returns `collection`.
 */
var baseEach = createBaseEach(baseForOwn);

module.exports = baseEach;


/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {

var baseMatches = __webpack_require__(90),
    baseMatchesProperty = __webpack_require__(91),
    bindCallback = __webpack_require__(12),
    identity = __webpack_require__(50),
    property = __webpack_require__(51);

/**
 * The base implementation of `_.callback` which supports specifying the
 * number of arguments to provide to `func`.
 *
 * @private
 * @param {*} [func=_.identity] The value to convert to a callback.
 * @param {*} [thisArg] The `this` binding of `func`.
 * @param {number} [argCount] The number of arguments to provide to `func`.
 * @returns {Function} Returns the callback.
 */
function baseCallback(func, thisArg, argCount) {
  var type = typeof func;
  if (type == 'function') {
    return thisArg === undefined
      ? func
      : bindCallback(func, thisArg, argCount);
  }
  if (func == null) {
    return identity;
  }
  if (type == 'object') {
    return baseMatches(func);
  }
  return thisArg === undefined
    ? property(func)
    : baseMatchesProperty(func, thisArg);
}

module.exports = baseCallback;


/***/ }),
/* 11 */
/***/ (function(module, exports, __webpack_require__) {

var toObject = __webpack_require__(3);

/**
 * The base implementation of `get` without support for string paths
 * and default values.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array} path The path of the property to get.
 * @param {string} [pathKey] The key representation of path.
 * @returns {*} Returns the resolved value.
 */
function baseGet(object, path, pathKey) {
  if (object == null) {
    return;
  }
  if (pathKey !== undefined && pathKey in toObject(object)) {
    path = [pathKey];
  }
  var index = 0,
      length = path.length;

  while (object != null && index < length) {
    object = object[path[index++]];
  }
  return (index && index == length) ? object : undefined;
}

module.exports = baseGet;


/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {

var identity = __webpack_require__(50);

/**
 * A specialized version of `baseCallback` which only supports `this` binding
 * and specifying the number of arguments to provide to `func`.
 *
 * @private
 * @param {Function} func The function to bind.
 * @param {*} thisArg The `this` binding of `func`.
 * @param {number} [argCount] The number of arguments to provide to `func`.
 * @returns {Function} Returns the callback.
 */
function bindCallback(func, thisArg, argCount) {
  if (typeof func != 'function') {
    return identity;
  }
  if (thisArg === undefined) {
    return func;
  }
  switch (argCount) {
    case 1: return function(value) {
      return func.call(thisArg, value);
    };
    case 3: return function(value, index, collection) {
      return func.call(thisArg, value, index, collection);
    };
    case 4: return function(accumulator, value, index, collection) {
      return func.call(thisArg, accumulator, value, index, collection);
    };
    case 5: return function(value, other, key, object, source) {
      return func.call(thisArg, value, other, key, object, source);
    };
  }
  return function() {
    return func.apply(thisArg, arguments);
  };
}

module.exports = bindCallback;


/***/ }),
/* 13 */
/***/ (function(module, exports) {

/** Used to detect unsigned integer values. */
var reIsUint = /^\d+$/;

/**
 * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
 * of an array-like value.
 */
var MAX_SAFE_INTEGER = 9007199254740991;

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
  length = length == null ? MAX_SAFE_INTEGER : length;
  return value > -1 && value % 1 == 0 && value < length;
}

module.exports = isIndex;


/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {

var baseToString = __webpack_require__(96),
    isArray = __webpack_require__(0);

/** Used to match property names within property paths. */
var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

/**
 * Converts `value` to property path array if it's not one.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {Array} Returns the property path array.
 */
function toPath(value) {
  if (isArray(value)) {
    return value;
  }
  var result = [];
  baseToString(value).replace(rePropName, function(match, number, quote, string) {
    result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
  });
  return result;
}

module.exports = toPath;


/***/ }),
/* 15 */
/***/ (function(module, exports, __webpack_require__) {

var isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var stringTag = '[object String]';

/** Used for native method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objToString = objectProto.toString;

/**
 * Checks if `value` is classified as a `String` primitive or object.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isString('abc');
 * // => true
 *
 * _.isString(1);
 * // => false
 */
function isString(value) {
  return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
}

module.exports = isString;


/***/ }),
/* 16 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_angular__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_angular_utf8_base64__ = __webpack_require__(25);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_angular_utf8_base64___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_angular_utf8_base64__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_angular_cookie__ = __webpack_require__(23);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_angular_cookie___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_angular_cookie__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_angular_cookies__ = __webpack_require__(24);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_angular_cookies___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_angular_cookies__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__cookies_factory__ = __webpack_require__(26);






/* harmony default export */ __webpack_exports__["default"] = __WEBPACK_IMPORTED_MODULE_0_angular___default.a.module('Cookies', [__WEBPACK_IMPORTED_MODULE_1_angular_utf8_base64___default.a, __WEBPACK_IMPORTED_MODULE_3_angular_cookies___default.a, __WEBPACK_IMPORTED_MODULE_2_angular_cookie___default.a]).factory('CookieFac', __WEBPACK_IMPORTED_MODULE_4__cookies_factory__["a" /* default */]).name;

/***/ }),
/* 17 */
/***/ (function(module, exports, __webpack_require__) {

var baseProperty = __webpack_require__(37);

/**
 * Gets the "length" property value of `object`.
 *
 * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
 * that affects Safari on at least iOS 8.1-8.3 ARM64.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {*} Returns the "length" value.
 */
var getLength = baseProperty('length');

module.exports = getLength;


/***/ }),
/* 18 */
/***/ (function(module, exports, __webpack_require__) {

var isArray = __webpack_require__(0),
    toObject = __webpack_require__(3);

/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
    reIsPlainProp = /^\w*$/;

/**
 * Checks if `value` is a property name and not a property path.
 *
 * @private
 * @param {*} value The value to check.
 * @param {Object} [object] The object to query keys on.
 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 */
function isKey(value, object) {
  var type = typeof value;
  if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
    return true;
  }
  if (isArray(value)) {
    return false;
  }
  var result = !reIsDeepProp.test(value);
  return result || (object != null && value in toObject(object));
}

module.exports = isKey;


/***/ }),
/* 19 */
/***/ (function(module, exports, __webpack_require__) {

var isLength = __webpack_require__(7),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    objectTag = '[object Object]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dateTag] = typedArrayTags[errorTag] =
typedArrayTags[funcTag] = typedArrayTags[mapTag] =
typedArrayTags[numberTag] = typedArrayTags[objectTag] =
typedArrayTags[regexpTag] = typedArrayTags[setTag] =
typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;

/** Used for native method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objToString = objectProto.toString;

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
function isTypedArray(value) {
  return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
}

module.exports = isTypedArray;


/***/ }),
/* 20 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is `undefined`.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
 * @example
 *
 * _.isUndefined(void 0);
 * // => true
 *
 * _.isUndefined(null);
 * // => false
 */
function isUndefined(value) {
  return value === undefined;
}

module.exports = isUndefined;


/***/ }),
/* 21 */
/***/ (function(module, exports, __webpack_require__) {

var isArguments = __webpack_require__(8),
    isArray = __webpack_require__(0),
    isIndex = __webpack_require__(13),
    isLength = __webpack_require__(7),
    isObject = __webpack_require__(4);

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Creates an array of the own and inherited enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects.
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keysIn(new Foo);
 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
 */
function keysIn(object) {
  if (object == null) {
    return [];
  }
  if (!isObject(object)) {
    object = Object(object);
  }
  var length = object.length;
  length = (length && isLength(length) &&
    (isArray(object) || isArguments(object)) && length) || 0;

  var Ctor = object.constructor,
      index = -1,
      isProto = typeof Ctor == 'function' && Ctor.prototype === object,
      result = Array(length),
      skipIndexes = length > 0;

  while (++index < length) {
    result[index] = (index + '');
  }
  for (var key in object) {
    if (!(skipIndexes && isIndex(key, length)) &&
        !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
      result.push(key);
    }
  }
  return result;
}

module.exports = keysIn;


/***/ }),
/* 22 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var EventEmitter = function () {

  // constructor :: ($rootScope) -> void
  function EventEmitter(emitter /* $rootScope*/) {
    _classCallCheck(this, EventEmitter);

    this.eventHandlers = {};
    this.emitter = emitter;
    this.namespace = '';
  }

  // emit :: (String, mixed) -> EventEmitter


  _createClass(EventEmitter, [{
    key: 'emit',
    value: function emit(eventName) {
      var _emitter;

      var identifier = this.namespace + ':' + eventName;

      for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        params[_key - 1] = arguments[_key];
      }

      (_emitter = this.emitter).$emit.apply(_emitter, [identifier].concat(params));
      return this;
    }

    // on :: (String, Function) -> EventEmitter

  }, {
    key: 'on',
    value: function on(eventName, callback) {
      var handler = function handler(evt) {
        for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
          args[_key2 - 1] = arguments[_key2];
        }

        return callback.apply(undefined, args);
      };
      var identifier = this.namespace + ':' + eventName;

      this.eventHandlers[identifier] = this.eventHandlers[identifier] || [];
      this.eventHandlers[identifier].push(this.emitter.$on(identifier, handler));

      return this;
    }

    // off :: (String) -> EventEmitter

  }, {
    key: 'off',
    value: function off(identifier) {
      [].concat(this.eventHandlers[identifier]).map(function (eventHandlerFunc) {
        return eventHandlerFunc();
      });

      this.eventHandlers[identifier] = [];

      return this;
    }
  }]);

  return EventEmitter;
}();

/* harmony default export */ __webpack_exports__["a"] = EventEmitter;

/***/ }),
/* 23 */
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__(27);
module.exports = 'ipCookie';


/***/ }),
/* 24 */
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__(28);
module.exports = 'ngCookies';


/***/ }),
/* 25 */
/***/ (function(module, exports, __webpack_require__) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (root, factory) {
    if (true) {
        // AMD. Register as an anonymous module.
        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function (angular) {
            return (root.returnExportsGlobal = factory(angular));
        }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
    } else if (typeof module === 'object' && module.exports) {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require('angular'));
    } else {
        // Browser globals
        root.returnExportsGlobal = factory(root.angular);
    }
}(this, function (angular) {

/*
 * Encapsulation of Andrey Bezyazychniy's encapsulation of Vassilis Petroulias's base64.js library.
 * As well as Andrey Bezyazychniy's AngularJS wrapper, an additional CommonJS wrapper has been added.
 * Original notice included below
 */

/*
 Copyright Vassilis Petroulias [DRDigit]

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
var B64 = {
    alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
    lookup: null,
    ie: /MSIE /.test(navigator.userAgent),
    ieo: /MSIE [67]/.test(navigator.userAgent),
    encode: function (s) {
        /* jshint bitwise:false */
        var buffer = B64.toUtf8(s),
            position = -1,
            result,
            len = buffer.length,
            nan0, nan1, nan2, enc = [, , , ];

        if (B64.ie) {
            result = [];
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1))
                    enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63;
                }
                result.push(B64.alphabet.charAt(enc[0]), B64.alphabet.charAt(enc[1]), B64.alphabet.charAt(enc[2]), B64.alphabet.charAt(enc[3]));
            }
            return result.join('');
        } else {
            result = '';
            while (++position < len) {
                nan0 = buffer[position];
                nan1 = buffer[++position];
                enc[0] = nan0 >> 2;
                enc[1] = ((nan0 & 3) << 4) | (nan1 >> 4);
                if (isNaN(nan1))
                    enc[2] = enc[3] = 64;
                else {
                    nan2 = buffer[++position];
                    enc[2] = ((nan1 & 15) << 2) | (nan2 >> 6);
                    enc[3] = (isNaN(nan2)) ? 64 : nan2 & 63;
                }
                result += B64.alphabet[enc[0]] + B64.alphabet[enc[1]] + B64.alphabet[enc[2]] + B64.alphabet[enc[3]];
            }
            return result;
        }
    },
    decode: function (s) {
        /* jshint bitwise:false */
        s = s.replace(/\s/g, '');
        if (s.length % 4)
            throw new Error('InvalidLengthError: decode failed: The string to be decoded is not the correct length for a base64 encoded string.');
        if(/[^A-Za-z0-9+\/=\s]/g.test(s))
            throw new Error('InvalidCharacterError: decode failed: The string contains characters invalid in a base64 encoded string.');

        var buffer = B64.fromUtf8(s),
            position = 0,
            result,
            len = buffer.length;

        if (B64.ieo) {
            result = [];
            while (position < len) {
                if (buffer[position] < 128)
                    result.push(String.fromCharCode(buffer[position++]));
                else if (buffer[position] > 191 && buffer[position] < 224)
                    result.push(String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63)));
                else
                    result.push(String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63)));
            }
            return result.join('');
        } else {
            result = '';
            while (position < len) {
                if (buffer[position] < 128)
                    result += String.fromCharCode(buffer[position++]);
                else if (buffer[position] > 191 && buffer[position] < 224)
                    result += String.fromCharCode(((buffer[position++] & 31) << 6) | (buffer[position++] & 63));
                else
                    result += String.fromCharCode(((buffer[position++] & 15) << 12) | ((buffer[position++] & 63) << 6) | (buffer[position++] & 63));
            }
            return result;
        }
    },
    toUtf8: function (s) {
        /* jshint bitwise:false */
        var position = -1,
            len = s.length,
            chr, buffer = [];
        if (/^[\x00-\x7f]*$/.test(s)) while (++position < len)
            buffer.push(s.charCodeAt(position));
        else while (++position < len) {
            chr = s.charCodeAt(position);
            if (chr < 128)
                buffer.push(chr);
            else if (chr < 2048)
                buffer.push((chr >> 6) | 192, (chr & 63) | 128);
            else
                buffer.push((chr >> 12) | 224, ((chr >> 6) & 63) | 128, (chr & 63) | 128);
        }
        return buffer;
    },
    fromUtf8: function (s) {
        /* jshint bitwise:false */
        var position = -1,
            len, buffer = [],
            enc = [, , , ];
        if (!B64.lookup) {
            len = B64.alphabet.length;
            B64.lookup = {};
            while (++position < len)
                B64.lookup[B64.alphabet.charAt(position)] = position;
            position = -1;
        }
        len = s.length;
        while (++position < len) {
            enc[0] = B64.lookup[s.charAt(position)];
            enc[1] = B64.lookup[s.charAt(++position)];
            buffer.push((enc[0] << 2) | (enc[1] >> 4));
            enc[2] = B64.lookup[s.charAt(++position)];
            if (enc[2] === 64)
                break;
            buffer.push(((enc[1] & 15) << 4) | (enc[2] >> 2));
            enc[3] = B64.lookup[s.charAt(++position)];
            if (enc[3] === 64)
                break;
            buffer.push(((enc[2] & 3) << 6) | enc[3]);
        }
        return buffer;
    }
};

var B64url = {
    decode: function(input) {
        // Replace non-url compatible chars with base64 standard chars
        input = input
            .replace(/-/g, '+')
            .replace(/_/g, '/');

        // Pad out with standard base64 required padding characters
        var pad = input.length % 4;
        if(pad) {
          if(pad === 1) {
            throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding');
          }
          input += new Array(5-pad).join('=');
        }

        return B64.decode(input);
    },

    encode: function(input) {
        var output = B64.encode(input);
        return output
            .replace(/\+/g, '-')
            .replace(/\//g, '_')
            .split('=', 1)[0];
    }
};

return angular
    .module('utf8-base64', [])
    .constant('base64', {
        decode: B64.decode,
        encode: B64.encode,
        urldecode: B64url.decode,
        urlencode: B64url.encode,
    })
    .name;
}));


/***/ }),
/* 26 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_angular__);
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }



function CookieFactory(base64, ipCookie) {
  // this factory will take in a cookie name, and decode it and return the cookie object... too this factory will need to be able to set / update params on these cookies
  function _getCookie(cookieName) {
    var value = ipCookie(cookieName);
    if (!__WEBPACK_IMPORTED_MODULE_0_angular___default.a.isDefined(value)) {
      return null;
    }
    return value;
  }

  function _setCookie(cookieName, cookieString, options) {
    return ipCookie(cookieName, cookieString, options);
  }

  function _removeCookie(key, options) {
    return ipCookie.remove(key, options);
  }

  function _getTVGFormatCookie(cookieName) {
    var cookie = _getCookie(cookieName);
    var cookieData = cookie ? base64.decode(cookie).split(';') : [];

    return cookieData.reduce(function (acc, key) {
      var tmp = key.split('=');
      return _extends({}, acc, _defineProperty({}, tmp[0], tmp[1]));
    }, {});
  }

  function _convertCookieData(keyValueObject) {
    var tmp = '';
    __WEBPACK_IMPORTED_MODULE_0_angular___default.a.forEach(keyValueObject, function (value, key) {
      tmp += key + '=' + value + ';';
    });

    return tmp;
  }

  // Set values to null to remove them from the cookie
  function _setTVGFormatCookieValue(cookieName, keyValueObject) {
    var cookieData = _getTVGFormatCookie(cookieName);

    if (keyValueObject === null || keyValueObject === undefined || !__WEBPACK_IMPORTED_MODULE_0_angular___default.a.isObject(keyValueObject) || (typeof keyValueObject === 'undefined' ? 'undefined' : _typeof(keyValueObject)) !== 'object') {
      return false;
    }

    __WEBPACK_IMPORTED_MODULE_0_angular___default.a.extend(cookieData, keyValueObject);

    var newString = _convertCookieData(cookieData);

    return _setCookie(cookieName, base64.encode(newString), { path: '/' });
  }

  function _setEncodedCookie(cookieName, value, options) {
    _setCookie(cookieName, base64.encode(value), options);
  }

  function _getEncodedCookie(cookieName) {
    return base64.decode(_getCookie(cookieName));
  }

  return {
    getCookie: _getCookie,
    setCookie: _setCookie,
    removeCookie: _removeCookie,
    getTVGFormatCookie: _getTVGFormatCookie,
    setTVGFormatCookieValue: _setTVGFormatCookieValue,
    getEncodedCookie: _getEncodedCookie,
    setEncodedCookie: _setEncodedCookie
  };
}

CookieFactory.$inject = ['base64', 'ipCookie'];

/* harmony default export */ __webpack_exports__["a"] = CookieFactory;

/***/ }),
/* 27 */
/***/ (function(module, exports) {

/*
 * Copyright 2013 Ivan Pusic
 * Contributors:
 *   Matjaz Lipus
 */
angular.module('ivpusic.cookie', ['ipCookie']);
angular.module('ipCookie', ['ng']).
factory('ipCookie', ['$document',
  function ($document) {
    'use strict';
      
    function tryDecodeURIComponent(value) {
        try {
            return decodeURIComponent(value);
        } catch(e) {
              // Ignore any invalid uri component
        }
    }

    return (function () {
      function cookieFun(key, value, options) {

        var cookies,
          list,
          i,
          cookie,
          pos,
          name,
          hasCookies,
          all,
          expiresFor;

        options = options || {};
        var dec = options.decode || tryDecodeURIComponent;
        var enc = options.encode || encodeURIComponent;

        if (value !== undefined) {
          // we are setting value
          value = typeof value === 'object' ? JSON.stringify(value) : String(value);

          if (typeof options.expires === 'number') {
            expiresFor = options.expires;
            options.expires = new Date();
            // Trying to delete a cookie; set a date far in the past
            if (expiresFor === -1) {
              options.expires = new Date('Thu, 01 Jan 1970 00:00:00 GMT');
              // A new 
            } else if (options.expirationUnit !== undefined) {
              if (options.expirationUnit === 'hours') {
                options.expires.setHours(options.expires.getHours() + expiresFor);
              } else if (options.expirationUnit === 'minutes') {
                options.expires.setMinutes(options.expires.getMinutes() + expiresFor);
              } else if (options.expirationUnit === 'seconds') {
                options.expires.setSeconds(options.expires.getSeconds() + expiresFor);
              } else if (options.expirationUnit === 'milliseconds') {
                options.expires.setMilliseconds(options.expires.getMilliseconds() + expiresFor);
              } else {
                options.expires.setDate(options.expires.getDate() + expiresFor);
              }
            } else {
              options.expires.setDate(options.expires.getDate() + expiresFor);
            }
          }
          return ($document[0].cookie = [
            enc(key),
            '=',
            enc(value),
            options.expires ? '; expires=' + options.expires.toUTCString() : '',
            options.path ? '; path=' + options.path : '',
            options.domain ? '; domain=' + options.domain : '',
            options.secure ? '; secure' : ''
          ].join(''));
        }

        list = [];
        all = $document[0].cookie;
        if (all) {
          list = all.split('; ');
        }

        cookies = {};
        hasCookies = false;

        for (i = 0; i < list.length; ++i) {
          if (list[i]) {
            cookie = list[i];
            pos = cookie.indexOf('=');
            name = cookie.substring(0, pos);
            value = dec(cookie.substring(pos + 1));
            if(angular.isUndefined(value))
              continue;

            if (key === undefined || key === name) {
              try {
                cookies[name] = JSON.parse(value);
              } catch (e) {
                cookies[name] = value;
              }
              if (key === name) {
                return cookies[name];
              }
              hasCookies = true;
            }
          }
        }
        if (hasCookies && key === undefined) {
          return cookies;
        }
      }
      cookieFun.remove = function (key, options) {
        var hasCookie = cookieFun(key) !== undefined;

        if (hasCookie) {
          if (!options) {
            options = {};
          }
          options.expires = -1;
          cookieFun(key, '', options);
        }
        return hasCookie;
      };
      return cookieFun;
    }());
  }
]);


/***/ }),
/* 28 */
/***/ (function(module, exports) {

/**
 * @license AngularJS v1.5.8
 * (c) 2010-2016 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function(window, angular) {'use strict';

/**
 * @ngdoc module
 * @name ngCookies
 * @description
 *
 * # ngCookies
 *
 * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
 *
 *
 * <div doc-module-components="ngCookies"></div>
 *
 * See {@link ngCookies.$cookies `$cookies`} for usage.
 */


angular.module('ngCookies', ['ng']).
  /**
   * @ngdoc provider
   * @name $cookiesProvider
   * @description
   * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
   * */
   provider('$cookies', [function $CookiesProvider() {
    /**
     * @ngdoc property
     * @name $cookiesProvider#defaults
     * @description
     *
     * Object containing default options to pass when setting cookies.
     *
     * The object may have following properties:
     *
     * - **path** - `{string}` - The cookie will be available only for this path and its
     *   sub-paths. By default, this is the URL that appears in your `<base>` tag.
     * - **domain** - `{string}` - The cookie will be available only for this domain and
     *   its sub-domains. For security reasons the user agent will not accept the cookie
     *   if the current domain is not a sub-domain of this domain or equal to it.
     * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
     *   or a Date object indicating the exact date/time this cookie will expire.
     * - **secure** - `{boolean}` - If `true`, then the cookie will only be available through a
     *   secured connection.
     *
     * Note: By default, the address that appears in your `<base>` tag will be used as the path.
     * This is important so that cookies will be visible for all routes when html5mode is enabled.
     *
     **/
    var defaults = this.defaults = {};

    function calcOptions(options) {
      return options ? angular.extend({}, defaults, options) : defaults;
    }

    /**
     * @ngdoc service
     * @name $cookies
     *
     * @description
     * Provides read/write access to browser's cookies.
     *
     * <div class="alert alert-info">
     * Up until Angular 1.3, `$cookies` exposed properties that represented the
     * current browser cookie values. In version 1.4, this behavior has changed, and
     * `$cookies` now provides a standard api of getters, setters etc.
     * </div>
     *
     * Requires the {@link ngCookies `ngCookies`} module to be installed.
     *
     * @example
     *
     * ```js
     * angular.module('cookiesExample', ['ngCookies'])
     *   .controller('ExampleController', ['$cookies', function($cookies) {
     *     // Retrieving a cookie
     *     var favoriteCookie = $cookies.get('myFavorite');
     *     // Setting a cookie
     *     $cookies.put('myFavorite', 'oatmeal');
     *   }]);
     * ```
     */
    this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
      return {
        /**
         * @ngdoc method
         * @name $cookies#get
         *
         * @description
         * Returns the value of given cookie key
         *
         * @param {string} key Id to use for lookup.
         * @returns {string} Raw cookie value.
         */
        get: function(key) {
          return $$cookieReader()[key];
        },

        /**
         * @ngdoc method
         * @name $cookies#getObject
         *
         * @description
         * Returns the deserialized value of given cookie key
         *
         * @param {string} key Id to use for lookup.
         * @returns {Object} Deserialized cookie value.
         */
        getObject: function(key) {
          var value = this.get(key);
          return value ? angular.fromJson(value) : value;
        },

        /**
         * @ngdoc method
         * @name $cookies#getAll
         *
         * @description
         * Returns a key value object with all the cookies
         *
         * @returns {Object} All cookies
         */
        getAll: function() {
          return $$cookieReader();
        },

        /**
         * @ngdoc method
         * @name $cookies#put
         *
         * @description
         * Sets a value for given cookie key
         *
         * @param {string} key Id for the `value`.
         * @param {string} value Raw value to be stored.
         * @param {Object=} options Options object.
         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
         */
        put: function(key, value, options) {
          $$cookieWriter(key, value, calcOptions(options));
        },

        /**
         * @ngdoc method
         * @name $cookies#putObject
         *
         * @description
         * Serializes and sets a value for given cookie key
         *
         * @param {string} key Id for the `value`.
         * @param {Object} value Value to be stored.
         * @param {Object=} options Options object.
         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
         */
        putObject: function(key, value, options) {
          this.put(key, angular.toJson(value), options);
        },

        /**
         * @ngdoc method
         * @name $cookies#remove
         *
         * @description
         * Remove given cookie
         *
         * @param {string} key Id of the key-value pair to delete.
         * @param {Object=} options Options object.
         *    See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
         */
        remove: function(key, options) {
          $$cookieWriter(key, undefined, calcOptions(options));
        }
      };
    }];
  }]);

angular.module('ngCookies').
/**
 * @ngdoc service
 * @name $cookieStore
 * @deprecated
 * @requires $cookies
 *
 * @description
 * Provides a key-value (string-object) storage, that is backed by session cookies.
 * Objects put or retrieved from this storage are automatically serialized or
 * deserialized by angular's toJson/fromJson.
 *
 * Requires the {@link ngCookies `ngCookies`} module to be installed.
 *
 * <div class="alert alert-danger">
 * **Note:** The $cookieStore service is **deprecated**.
 * Please use the {@link ngCookies.$cookies `$cookies`} service instead.
 * </div>
 *
 * @example
 *
 * ```js
 * angular.module('cookieStoreExample', ['ngCookies'])
 *   .controller('ExampleController', ['$cookieStore', function($cookieStore) {
 *     // Put cookie
 *     $cookieStore.put('myFavorite','oatmeal');
 *     // Get cookie
 *     var favoriteCookie = $cookieStore.get('myFavorite');
 *     // Removing a cookie
 *     $cookieStore.remove('myFavorite');
 *   }]);
 * ```
 */
 factory('$cookieStore', ['$cookies', function($cookies) {

    return {
      /**
       * @ngdoc method
       * @name $cookieStore#get
       *
       * @description
       * Returns the value of given cookie key
       *
       * @param {string} key Id to use for lookup.
       * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
       */
      get: function(key) {
        return $cookies.getObject(key);
      },

      /**
       * @ngdoc method
       * @name $cookieStore#put
       *
       * @description
       * Sets a value for given cookie key
       *
       * @param {string} key Id for the `value`.
       * @param {Object} value Value to be stored.
       */
      put: function(key, value) {
        $cookies.putObject(key, value);
      },

      /**
       * @ngdoc method
       * @name $cookieStore#remove
       *
       * @description
       * Remove given cookie
       *
       * @param {string} key Id of the key-value pair to delete.
       */
      remove: function(key) {
        $cookies.remove(key);
      }
    };

  }]);

/**
 * @name $$cookieWriter
 * @requires $document
 *
 * @description
 * This is a private service for writing cookies
 *
 * @param {string} name Cookie name
 * @param {string=} value Cookie value (if undefined, cookie will be deleted)
 * @param {Object=} options Object with options that need to be stored for the cookie.
 */
function $$CookieWriter($document, $log, $browser) {
  var cookiePath = $browser.baseHref();
  var rawDocument = $document[0];

  function buildCookieString(name, value, options) {
    var path, expires;
    options = options || {};
    expires = options.expires;
    path = angular.isDefined(options.path) ? options.path : cookiePath;
    if (angular.isUndefined(value)) {
      expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
      value = '';
    }
    if (angular.isString(expires)) {
      expires = new Date(expires);
    }

    var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
    str += path ? ';path=' + path : '';
    str += options.domain ? ';domain=' + options.domain : '';
    str += expires ? ';expires=' + expires.toUTCString() : '';
    str += options.secure ? ';secure' : '';

    // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
    // - 300 cookies
    // - 20 cookies per unique domain
    // - 4096 bytes per cookie
    var cookieLength = str.length + 1;
    if (cookieLength > 4096) {
      $log.warn("Cookie '" + name +
        "' possibly not set or overflowed because it was too large (" +
        cookieLength + " > 4096 bytes)!");
    }

    return str;
  }

  return function(name, value, options) {
    rawDocument.cookie = buildCookieString(name, value, options);
  };
}

$$CookieWriter.$inject = ['$document', '$log', '$browser'];

angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
  this.$get = $$CookieWriter;
});


})(window, window.angular);


/***/ }),
/* 29 */
/***/ (function(module, exports) {

/**
 * Gets the last element of `array`.
 *
 * @static
 * @memberOf _
 * @category Array
 * @param {Array} array The array to query.
 * @returns {*} Returns the last element of `array`.
 * @example
 *
 * _.last([1, 2, 3]);
 * // => 3
 */
function last(array) {
  var length = array ? array.length : 0;
  return length ? array[length - 1] : undefined;
}

module.exports = last;


/***/ }),
/* 30 */
/***/ (function(module, exports, __webpack_require__) {

var arrayFilter = __webpack_require__(72),
    baseCallback = __webpack_require__(10),
    baseFilter = __webpack_require__(79),
    isArray = __webpack_require__(0);

/**
 * Iterates over elements of `collection`, returning an array of all elements
 * `predicate` returns truthy for. The predicate is bound to `thisArg` and
 * invoked with three arguments: (value, index|key, collection).
 *
 * If a property name is provided for `predicate` the created `_.property`
 * style callback returns the property value of the given element.
 *
 * If a value is also provided for `thisArg` the created `_.matchesProperty`
 * style callback returns `true` for elements that have a matching property
 * value, else `false`.
 *
 * If an object is provided for `predicate` the created `_.matches` style
 * callback returns `true` for elements that have the properties of the given
 * object, else `false`.
 *
 * @static
 * @memberOf _
 * @alias select
 * @category Collection
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function|Object|string} [predicate=_.identity] The function invoked
 *  per iteration.
 * @param {*} [thisArg] The `this` binding of `predicate`.
 * @returns {Array} Returns the new filtered array.
 * @example
 *
 * _.filter([4, 5, 6], function(n) {
 *   return n % 2 == 0;
 * });
 * // => [4, 6]
 *
 * var users = [
 *   { 'user': 'barney', 'age': 36, 'active': true },
 *   { 'user': 'fred',   'age': 40, 'active': false }
 * ];
 *
 * // using the `_.matches` callback shorthand
 * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');
 * // => ['barney']
 *
 * // using the `_.matchesProperty` callback shorthand
 * _.pluck(_.filter(users, 'active', false), 'user');
 * // => ['fred']
 *
 * // using the `_.property` callback shorthand
 * _.pluck(_.filter(users, 'active'), 'user');
 * // => ['barney']
 */
function filter(collection, predicate, thisArg) {
  var func = isArray(collection) ? arrayFilter : baseFilter;
  predicate = baseCallback(predicate, thisArg, 3);
  return func(collection, predicate);
}

module.exports = filter;


/***/ }),
/* 31 */
/***/ (function(module, exports, __webpack_require__) {

var baseIndexOf = __webpack_require__(86),
    getLength = __webpack_require__(17),
    isArray = __webpack_require__(0),
    isIterateeCall = __webpack_require__(43),
    isLength = __webpack_require__(7),
    isString = __webpack_require__(15),
    values = __webpack_require__(116);

/* Native method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * Checks if `target` is in `collection` using
 * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 * for equality comparisons. If `fromIndex` is negative, it's used as the offset
 * from the end of `collection`.
 *
 * @static
 * @memberOf _
 * @alias contains, include
 * @category Collection
 * @param {Array|Object|string} collection The collection to search.
 * @param {*} target The value to search for.
 * @param {number} [fromIndex=0] The index to search from.
 * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
 * @returns {boolean} Returns `true` if a matching element is found, else `false`.
 * @example
 *
 * _.includes([1, 2, 3], 1);
 * // => true
 *
 * _.includes([1, 2, 3], 1, 2);
 * // => false
 *
 * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
 * // => true
 *
 * _.includes('pebbles', 'eb');
 * // => true
 */
function includes(collection, target, fromIndex, guard) {
  var length = collection ? getLength(collection) : 0;
  if (!isLength(length)) {
    collection = values(collection);
    length = collection.length;
  }
  if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
    fromIndex = 0;
  } else {
    fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
  }
  return (typeof collection == 'string' || !isArray(collection) && isString(collection))
    ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1)
    : (!!length && baseIndexOf(collection, target, fromIndex) > -1);
}

module.exports = includes;


/***/ }),
/* 32 */
/***/ (function(module, exports) {

/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';

/* Native method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * Creates a function that invokes `func` with the `this` binding of the
 * created function and arguments from `start` and beyond provided as an array.
 *
 * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/Web/JavaScript/Reference/Functions/rest_parameters).
 *
 * @static
 * @memberOf _
 * @category Function
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @returns {Function} Returns the new function.
 * @example
 *
 * var say = _.restParam(function(what, names) {
 *   return what + ' ' + _.initial(names).join(', ') +
 *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
 * });
 *
 * say('hello', 'fred', 'barney', 'pebbles');
 * // => 'hello fred, barney, & pebbles'
 */
function restParam(func, start) {
  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
  return function() {
    var args = arguments,
        index = -1,
        length = nativeMax(args.length - start, 0),
        rest = Array(length);

    while (++index < length) {
      rest[index] = args[start + index];
    }
    switch (start) {
      case 0: return func.call(this, rest);
      case 1: return func.call(this, args[0], rest);
      case 2: return func.call(this, args[0], args[1], rest);
    }
    var otherArgs = Array(start + 1);
    index = -1;
    while (++index < start) {
      otherArgs[index] = args[index];
    }
    otherArgs[start] = rest;
    return func.apply(this, otherArgs);
  };
}

module.exports = restParam;


/***/ }),
/* 33 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.forEach` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns `array`.
 */
function arrayEach(array, iteratee) {
  var index = -1,
      length = array.length;

  while (++index < length) {
    if (iteratee(array[index], index, array) === false) {
      break;
    }
  }
  return array;
}

module.exports = arrayEach;


/***/ }),
/* 34 */
/***/ (function(module, exports, __webpack_require__) {

var createBaseFor = __webpack_require__(40);

/**
 * The base implementation of `baseForIn` and `baseForOwn` which iterates
 * over `object` properties returned by `keysFunc` invoking `iteratee` for
 * each property. Iteratee functions may exit iteration early by explicitly
 * returning `false`.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @returns {Object} Returns `object`.
 */
var baseFor = createBaseFor();

module.exports = baseFor;


/***/ }),
/* 35 */
/***/ (function(module, exports, __webpack_require__) {

var baseFor = __webpack_require__(34),
    keysIn = __webpack_require__(21);

/**
 * The base implementation of `_.forIn` without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function baseForIn(object, iteratee) {
  return baseFor(object, iteratee, keysIn);
}

module.exports = baseForIn;


/***/ }),
/* 36 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsEqualDeep = __webpack_require__(87),
    isObject = __webpack_require__(4),
    isObjectLike = __webpack_require__(2);

/**
 * The base implementation of `_.isEqual` without support for `this` binding
 * `customizer` functions.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {Function} [customizer] The function to customize comparing values.
 * @param {boolean} [isLoose] Specify performing partial comparisons.
 * @param {Array} [stackA] Tracks traversed `value` objects.
 * @param {Array} [stackB] Tracks traversed `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
    return value !== value && other !== other;
  }
  return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
}

module.exports = baseIsEqual;


/***/ }),
/* 37 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.property` without support for deep paths.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @returns {Function} Returns the new function.
 */
function baseProperty(key) {
  return function(object) {
    return object == null ? undefined : object[key];
  };
}

module.exports = baseProperty;


/***/ }),
/* 38 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.slice` without an iteratee call guard.
 *
 * @private
 * @param {Array} array The array to slice.
 * @param {number} [start=0] The start position.
 * @param {number} [end=array.length] The end position.
 * @returns {Array} Returns the slice of `array`.
 */
function baseSlice(array, start, end) {
  var index = -1,
      length = array.length;

  start = start == null ? 0 : (+start || 0);
  if (start < 0) {
    start = -start > length ? 0 : (length + start);
  }
  end = (end === undefined || end > length) ? length : (+end || 0);
  if (end < 0) {
    end += length;
  }
  length = start > end ? 0 : ((end - start) >>> 0);
  start >>>= 0;

  var result = Array(length);
  while (++index < length) {
    result[index] = array[index + start];
  }
  return result;
}

module.exports = baseSlice;


/***/ }),
/* 39 */
/***/ (function(module, exports, __webpack_require__) {

var getLength = __webpack_require__(17),
    isLength = __webpack_require__(7),
    toObject = __webpack_require__(3);

/**
 * Creates a `baseEach` or `baseEachRight` function.
 *
 * @private
 * @param {Function} eachFunc The function to iterate over a collection.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseEach(eachFunc, fromRight) {
  return function(collection, iteratee) {
    var length = collection ? getLength(collection) : 0;
    if (!isLength(length)) {
      return eachFunc(collection, iteratee);
    }
    var index = fromRight ? length : -1,
        iterable = toObject(collection);

    while ((fromRight ? index-- : ++index < length)) {
      if (iteratee(iterable[index], index, iterable) === false) {
        break;
      }
    }
    return collection;
  };
}

module.exports = createBaseEach;


/***/ }),
/* 40 */
/***/ (function(module, exports, __webpack_require__) {

var toObject = __webpack_require__(3);

/**
 * Creates a base function for `_.forIn` or `_.forInRight`.
 *
 * @private
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseFor(fromRight) {
  return function(object, iteratee, keysFunc) {
    var iterable = toObject(object),
        props = keysFunc(object),
        length = props.length,
        index = fromRight ? length : -1;

    while ((fromRight ? index-- : ++index < length)) {
      var key = props[index];
      if (iteratee(iterable[key], key, iterable) === false) {
        break;
      }
    }
    return object;
  };
}

module.exports = createBaseFor;


/***/ }),
/* 41 */
/***/ (function(module, exports, __webpack_require__) {

var baseCallback = __webpack_require__(10),
    baseFind = __webpack_require__(80),
    baseFindIndex = __webpack_require__(81),
    isArray = __webpack_require__(0);

/**
 * Creates a `_.find` or `_.findLast` function.
 *
 * @private
 * @param {Function} eachFunc The function to iterate over a collection.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new find function.
 */
function createFind(eachFunc, fromRight) {
  return function(collection, predicate, thisArg) {
    predicate = baseCallback(predicate, thisArg, 3);
    if (isArray(collection)) {
      var index = baseFindIndex(collection, predicate, fromRight);
      return index > -1 ? collection[index] : undefined;
    }
    return baseFind(collection, predicate, eachFunc);
  };
}

module.exports = createFind;


/***/ }),
/* 42 */
/***/ (function(module, exports, __webpack_require__) {

var isNative = __webpack_require__(110);

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = object == null ? undefined : object[key];
  return isNative(value) ? value : undefined;
}

module.exports = getNative;


/***/ }),
/* 43 */
/***/ (function(module, exports, __webpack_require__) {

var isArrayLike = __webpack_require__(6),
    isIndex = __webpack_require__(13),
    isObject = __webpack_require__(4);

/**
 * Checks if the provided arguments are from an iteratee call.
 *
 * @private
 * @param {*} value The potential iteratee value argument.
 * @param {*} index The potential iteratee index or key argument.
 * @param {*} object The potential iteratee object argument.
 * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
 */
function isIterateeCall(value, index, object) {
  if (!isObject(object)) {
    return false;
  }
  var type = typeof index;
  if (type == 'number'
      ? (isArrayLike(object) && isIndex(index, object.length))
      : (type == 'string' && index in object)) {
    var other = object[index];
    return value === value ? (value === other) : (other !== other);
  }
  return false;
}

module.exports = isIterateeCall;


/***/ }),
/* 44 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(4);

/**
 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` if suitable for strict
 *  equality comparisons, else `false`.
 */
function isStrictComparable(value) {
  return value === value && !isObject(value);
}

module.exports = isStrictComparable;


/***/ }),
/* 45 */
/***/ (function(module, exports, __webpack_require__) {

var isArguments = __webpack_require__(8),
    isArray = __webpack_require__(0),
    isArrayLike = __webpack_require__(6),
    isFunction = __webpack_require__(46),
    isObjectLike = __webpack_require__(2),
    isString = __webpack_require__(15),
    keys = __webpack_require__(5);

/**
 * Checks if `value` is empty. A value is considered empty unless it's an
 * `arguments` object, array, string, or jQuery-like collection with a length
 * greater than `0` or an object with own enumerable properties.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {Array|Object|string} value The value to inspect.
 * @returns {boolean} Returns `true` if `value` is empty, else `false`.
 * @example
 *
 * _.isEmpty(null);
 * // => true
 *
 * _.isEmpty(true);
 * // => true
 *
 * _.isEmpty(1);
 * // => true
 *
 * _.isEmpty([1, 2, 3]);
 * // => false
 *
 * _.isEmpty({ 'a': 1 });
 * // => false
 */
function isEmpty(value) {
  if (value == null) {
    return true;
  }
  if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||
      (isObjectLike(value) && isFunction(value.splice)))) {
    return !value.length;
  }
  return !keys(value).length;
}

module.exports = isEmpty;


/***/ }),
/* 46 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(4);

/** `Object#toString` result references. */
var funcTag = '[object Function]';

/** Used for native method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objToString = objectProto.toString;

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in older versions of Chrome and Safari which return 'function' for regexes
  // and Safari 8 which returns 'object' for typed array constructors.
  return isObject(value) && objToString.call(value) == funcTag;
}

module.exports = isFunction;


/***/ }),
/* 47 */
/***/ (function(module, exports, __webpack_require__) {

var baseForIn = __webpack_require__(35),
    isArguments = __webpack_require__(8),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var objectTag = '[object Object]';

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objToString = objectProto.toString;

/**
 * Checks if `value` is a plain object, that is, an object created by the
 * `Object` constructor or one with a `[[Prototype]]` of `null`.
 *
 * **Note:** This method assumes objects created by the `Object` constructor
 * have no inherited enumerable properties.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 * }
 *
 * _.isPlainObject(new Foo);
 * // => false
 *
 * _.isPlainObject([1, 2, 3]);
 * // => false
 *
 * _.isPlainObject({ 'x': 0, 'y': 0 });
 * // => true
 *
 * _.isPlainObject(Object.create(null));
 * // => true
 */
function isPlainObject(value) {
  var Ctor;

  // Exit early for non `Object` objects.
  if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) ||
      (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
    return false;
  }
  // IE < 9 iterates inherited properties before own properties. If the first
  // iterated property is an object's own property then there are no inherited
  // enumerable properties.
  var result;
  // In most environments an object's own properties are iterated before
  // its inherited properties. If the last iterated property is an object's
  // own property then there are no inherited enumerable properties.
  baseForIn(value, function(subValue, key) {
    result = key;
  });
  return result === undefined || hasOwnProperty.call(value, result);
}

module.exports = isPlainObject;


/***/ }),
/* 48 */
/***/ (function(module, exports, __webpack_require__) {

var baseGet = __webpack_require__(11),
    toPath = __webpack_require__(14);

/**
 * Gets the property value at `path` of `object`. If the resolved value is
 * `undefined` the `defaultValue` is used in its place.
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
 * @returns {*} Returns the resolved value.
 * @example
 *
 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
 *
 * _.get(object, 'a[0].b.c');
 * // => 3
 *
 * _.get(object, ['a', '0', 'b', 'c']);
 * // => 3
 *
 * _.get(object, 'a.b.c', 'default');
 * // => 'default'
 */
function get(object, path, defaultValue) {
  var result = object == null ? undefined : baseGet(object, toPath(path), (path + ''));
  return result === undefined ? defaultValue : result;
}

module.exports = get;


/***/ }),
/* 49 */
/***/ (function(module, exports, __webpack_require__) {

var baseMerge = __webpack_require__(92),
    createAssigner = __webpack_require__(98);

/**
 * Recursively merges own enumerable properties of the source object(s), that
 * don't resolve to `undefined` into the destination object. Subsequent sources
 * overwrite property assignments of previous sources. If `customizer` is
 * provided it's invoked to produce the merged values of the destination and
 * source properties. If `customizer` returns `undefined` merging is handled
 * by the method instead. The `customizer` is bound to `thisArg` and invoked
 * with five arguments: (objectValue, sourceValue, key, object, source).
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The destination object.
 * @param {...Object} [sources] The source objects.
 * @param {Function} [customizer] The function to customize assigned values.
 * @param {*} [thisArg] The `this` binding of `customizer`.
 * @returns {Object} Returns `object`.
 * @example
 *
 * var users = {
 *   'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
 * };
 *
 * var ages = {
 *   'data': [{ 'age': 36 }, { 'age': 40 }]
 * };
 *
 * _.merge(users, ages);
 * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
 *
 * // using a customizer callback
 * var object = {
 *   'fruits': ['apple'],
 *   'vegetables': ['beet']
 * };
 *
 * var other = {
 *   'fruits': ['banana'],
 *   'vegetables': ['carrot']
 * };
 *
 * _.merge(object, other, function(a, b) {
 *   if (_.isArray(a)) {
 *     return a.concat(b);
 *   }
 * });
 * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
 */
var merge = createAssigner(baseMerge);

module.exports = merge;


/***/ }),
/* 50 */
/***/ (function(module, exports) {

/**
 * This method returns the first argument provided to it.
 *
 * @static
 * @memberOf _
 * @category Utility
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'user': 'fred' };
 *
 * _.identity(object) === object;
 * // => true
 */
function identity(value) {
  return value;
}

module.exports = identity;


/***/ }),
/* 51 */
/***/ (function(module, exports, __webpack_require__) {

var baseProperty = __webpack_require__(37),
    basePropertyDeep = __webpack_require__(94),
    isKey = __webpack_require__(18);

/**
 * Creates a function that returns the property value at `path` on a
 * given object.
 *
 * @static
 * @memberOf _
 * @category Utility
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new function.
 * @example
 *
 * var objects = [
 *   { 'a': { 'b': { 'c': 2 } } },
 *   { 'a': { 'b': { 'c': 1 } } }
 * ];
 *
 * _.map(objects, _.property('a.b.c'));
 * // => [2, 1]
 *
 * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
 * // => [1, 2]
 */
function property(path) {
  return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
}

module.exports = property;


/***/ }),
/* 52 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * The Bucket mutator manipulates the features by introducing small random mutations by picking a random
 * bucket from the list, allowing multivariance testing.
 */
var isArray = __webpack_require__(0);
var isEmpty = __webpack_require__(45);
var includes = __webpack_require__(31);

function pickOneElement(array) {
    if (!isArray(array)) {
        throw 'Not an array!';
    }

    var index = Math.floor(Math.random() * (array.length));
    return array[index];
}

function isBucketGene(gene) {
    return !isEmpty(gene) && gene.type === 'bucket';
}

function containsGene(featureProperties, gene) {
    return includes(featureProperties.buckets, gene.toggle);
}

module.exports = {
    mutate: function(featureProperties, gene) {
        if (isBucketGene(gene) && containsGene(featureProperties, gene)) {
            return gene.toggle;
        } else {
            return pickOneElement(featureProperties.buckets);
        }
    },

    containsMultivariant: function(featureProperties) {
        return this.isBucketListValid(featureProperties.buckets);
    },

    isBucketListValid: function(bucketList) {
        return isArray(bucketList) && bucketList.length >= 0;
    }
};


/***/ }),
/* 53 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * The Throttle mutator manipulates the features by introducing small random mutations by randomly activate
 * or deactivate feture toggles.
 */
var isUndefined = __webpack_require__(20);
var isString = __webpack_require__(15);
var isPlainObject = __webpack_require__(47);
var isEmpty = __webpack_require__(45);

function isPercentage(value) {
    return !isUndefined(value) && isString(value) && value.match(/[0-100]%/);
}

function isThrottleNode(throttle) {
    return isPlainObject(throttle) && isString(throttle['value']) && isPercentage(throttle['value']);
}

function extractPercentage(throttle) {
    var percentage;
    if (isThrottleNode(throttle)) {
        percentage = throttle['value'];
    } else {
        percentage = throttle;
    }
    return percentage;
}

function getPercentageDecimal(throttle) {
    var percentage = extractPercentage(throttle);
    var value = percentage.substr(0, percentage.length - 2);
    return value / 10;
}

function isThrottleValid(throttle) {
    return isThrottleNode(throttle) || isPercentage(throttle);
}

function isThrottleGene(gene) {
    return !isEmpty(gene) && gene.type === 'throttle';
}

function shouldMutate(throttle) {
    return !isUndefined(throttle['mutate']) && throttle['mutate'] === 'force';
}

module.exports = {
    mutate: function (throttle, gene) {
        if (!shouldMutate(throttle) && isThrottleGene(gene)) {
            return gene.toggle;
        } else {
            var percentage = getPercentageDecimal(throttle);
            return Math.random() < percentage;
        }
    },

    isThrottleValid: function (throttle) {
        return isThrottleValid(throttle);
    }
};


/***/ }),
/* 54 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * This module contains multiple chemical reactions for use freely.
 */
var keys = __webpack_require__(5);

module.exports = {
    separateProperties: function (userProperties, feature) {
        return {
            userPropertyNames: keys(userProperties),
            featurePropertyNames: keys(feature)
        };
    }
};


/***/ }),
/* 55 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * This module checks for errors and proof-reads the molecules.
 */
var get = __webpack_require__(48);
var isUndefined = __webpack_require__(20);
var isBoolean = __webpack_require__(109);
var isNull = __webpack_require__(111);
var isArray = __webpack_require__(0);
var isObject = __webpack_require__(4);

var bucketMutator = __webpack_require__(52);
var throttleMutator = __webpack_require__(53);

module.exports = {
    areInstructionsValid: function (featureInstructions) {
        var toggle = get(featureInstructions, 'toggle');
        var throttle = get(featureInstructions, 'throttle');
        var buckets = get(featureInstructions, 'buckets');

        return this.isToggleValid(toggle) && this.isThrottleValid(throttle) && this.areBucketsValid(buckets);
    },

    isToggleValid: function (toggle) {
        return isUndefined(toggle) || isBoolean(toggle);
    },

    isThrottleValid: function(throttle) {
        return isUndefined(throttle) || throttleMutator.isThrottleValid(throttle);
    },

    areBucketsValid: function(buckets) {
        return isUndefined(buckets) || bucketMutator.isBucketListValid(buckets);
    },

    checkFeatureInstructions: function (featureInstructions) {
        var valid = isUndefined(featureInstructions) || isNull(featureInstructions) || !isArray(featureInstructions) && isObject(featureInstructions);

        if (!valid) {
            throw new Error('Invalid feature instructions!');
        }
    }
};


/***/ }),
/* 56 */
/***/ (function(module, exports) {

/*
  angular-md5 - v0.1.8 
  2015-11-17
*/

/* commonjs package manager support (eg componentjs) */
if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports) {
  module.exports = "angular-md5";
}
(function(angular) {
  angular.module("angular-md5", [ "gdi2290.md5" ]);
  angular.module("ngMd5", [ "gdi2290.md5" ]);
  angular.module("gdi2290.md5", [ "gdi2290.gravatar-filter", "gdi2290.md5-service", "gdi2290.md5-filter" ]);
  "use strict";
  angular.module("gdi2290.gravatar-filter", []).filter("gravatar", [ "md5", function(md5) {
    var cache = {};
    return function(text, defaultText) {
      if (!cache[text]) {
        defaultText = defaultText ? md5.createHash(defaultText.toString().toLowerCase()) : "";
        cache[text] = text ? md5.createHash(text.toString().toLowerCase()) : defaultText;
      }
      return cache[text];
    };
  } ]);
  "use strict";
  angular.module("gdi2290.md5-filter", []).filter("md5", [ "md5", function(md5) {
    return function(text) {
      return text ? md5.createHash(text.toString().toLowerCase()) : text;
    };
  } ]);
  "use strict";
  angular.module("gdi2290.md5-service", []).factory("md5", [ function() {
    var md5 = {
      createHash: function(str) {
        if (null === str) {
          return null;
        }
        var xl;
        var rotateLeft = function(lValue, iShiftBits) {
          return lValue << iShiftBits | lValue >>> 32 - iShiftBits;
        };
        var addUnsigned = function(lX, lY) {
          var lX4, lY4, lX8, lY8, lResult;
          lX8 = lX & 2147483648;
          lY8 = lY & 2147483648;
          lX4 = lX & 1073741824;
          lY4 = lY & 1073741824;
          lResult = (lX & 1073741823) + (lY & 1073741823);
          if (lX4 & lY4) {
            return lResult ^ 2147483648 ^ lX8 ^ lY8;
          }
          if (lX4 | lY4) {
            if (lResult & 1073741824) {
              return lResult ^ 3221225472 ^ lX8 ^ lY8;
            } else {
              return lResult ^ 1073741824 ^ lX8 ^ lY8;
            }
          } else {
            return lResult ^ lX8 ^ lY8;
          }
        };
        var _F = function(x, y, z) {
          return x & y | ~x & z;
        };
        var _G = function(x, y, z) {
          return x & z | y & ~z;
        };
        var _H = function(x, y, z) {
          return x ^ y ^ z;
        };
        var _I = function(x, y, z) {
          return y ^ (x | ~z);
        };
        var _FF = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };
        var _GG = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };
        var _HH = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };
        var _II = function(a, b, c, d, x, s, ac) {
          a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
          return addUnsigned(rotateLeft(a, s), b);
        };
        var convertToWordArray = function(str) {
          var lWordCount;
          var lMessageLength = str.length;
          var lNumberOfWords_temp1 = lMessageLength + 8;
          var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - lNumberOfWords_temp1 % 64) / 64;
          var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
          var lWordArray = new Array(lNumberOfWords - 1);
          var lBytePosition = 0;
          var lByteCount = 0;
          while (lByteCount < lMessageLength) {
            lWordCount = (lByteCount - lByteCount % 4) / 4;
            lBytePosition = lByteCount % 4 * 8;
            lWordArray[lWordCount] = lWordArray[lWordCount] | str.charCodeAt(lByteCount) << lBytePosition;
            lByteCount++;
          }
          lWordCount = (lByteCount - lByteCount % 4) / 4;
          lBytePosition = lByteCount % 4 * 8;
          lWordArray[lWordCount] = lWordArray[lWordCount] | 128 << lBytePosition;
          lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
          lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
          return lWordArray;
        };
        var wordToHex = function(lValue) {
          var wordToHexValue = "", wordToHexValue_temp = "", lByte, lCount;
          for (lCount = 0; lCount <= 3; lCount++) {
            lByte = lValue >>> lCount * 8 & 255;
            wordToHexValue_temp = "0" + lByte.toString(16);
            wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
          }
          return wordToHexValue;
        };
        var x = [], k, AA, BB, CC, DD, a, b, c, d, S11 = 7, S12 = 12, S13 = 17, S14 = 22, S21 = 5, S22 = 9, S23 = 14, S24 = 20, S31 = 4, S32 = 11, S33 = 16, S34 = 23, S41 = 6, S42 = 10, S43 = 15, S44 = 21;
        x = convertToWordArray(str);
        a = 1732584193;
        b = 4023233417;
        c = 2562383102;
        d = 271733878;
        xl = x.length;
        for (k = 0; k < xl; k += 16) {
          AA = a;
          BB = b;
          CC = c;
          DD = d;
          a = _FF(a, b, c, d, x[k + 0], S11, 3614090360);
          d = _FF(d, a, b, c, x[k + 1], S12, 3905402710);
          c = _FF(c, d, a, b, x[k + 2], S13, 606105819);
          b = _FF(b, c, d, a, x[k + 3], S14, 3250441966);
          a = _FF(a, b, c, d, x[k + 4], S11, 4118548399);
          d = _FF(d, a, b, c, x[k + 5], S12, 1200080426);
          c = _FF(c, d, a, b, x[k + 6], S13, 2821735955);
          b = _FF(b, c, d, a, x[k + 7], S14, 4249261313);
          a = _FF(a, b, c, d, x[k + 8], S11, 1770035416);
          d = _FF(d, a, b, c, x[k + 9], S12, 2336552879);
          c = _FF(c, d, a, b, x[k + 10], S13, 4294925233);
          b = _FF(b, c, d, a, x[k + 11], S14, 2304563134);
          a = _FF(a, b, c, d, x[k + 12], S11, 1804603682);
          d = _FF(d, a, b, c, x[k + 13], S12, 4254626195);
          c = _FF(c, d, a, b, x[k + 14], S13, 2792965006);
          b = _FF(b, c, d, a, x[k + 15], S14, 1236535329);
          a = _GG(a, b, c, d, x[k + 1], S21, 4129170786);
          d = _GG(d, a, b, c, x[k + 6], S22, 3225465664);
          c = _GG(c, d, a, b, x[k + 11], S23, 643717713);
          b = _GG(b, c, d, a, x[k + 0], S24, 3921069994);
          a = _GG(a, b, c, d, x[k + 5], S21, 3593408605);
          d = _GG(d, a, b, c, x[k + 10], S22, 38016083);
          c = _GG(c, d, a, b, x[k + 15], S23, 3634488961);
          b = _GG(b, c, d, a, x[k + 4], S24, 3889429448);
          a = _GG(a, b, c, d, x[k + 9], S21, 568446438);
          d = _GG(d, a, b, c, x[k + 14], S22, 3275163606);
          c = _GG(c, d, a, b, x[k + 3], S23, 4107603335);
          b = _GG(b, c, d, a, x[k + 8], S24, 1163531501);
          a = _GG(a, b, c, d, x[k + 13], S21, 2850285829);
          d = _GG(d, a, b, c, x[k + 2], S22, 4243563512);
          c = _GG(c, d, a, b, x[k + 7], S23, 1735328473);
          b = _GG(b, c, d, a, x[k + 12], S24, 2368359562);
          a = _HH(a, b, c, d, x[k + 5], S31, 4294588738);
          d = _HH(d, a, b, c, x[k + 8], S32, 2272392833);
          c = _HH(c, d, a, b, x[k + 11], S33, 1839030562);
          b = _HH(b, c, d, a, x[k + 14], S34, 4259657740);
          a = _HH(a, b, c, d, x[k + 1], S31, 2763975236);
          d = _HH(d, a, b, c, x[k + 4], S32, 1272893353);
          c = _HH(c, d, a, b, x[k + 7], S33, 4139469664);
          b = _HH(b, c, d, a, x[k + 10], S34, 3200236656);
          a = _HH(a, b, c, d, x[k + 13], S31, 681279174);
          d = _HH(d, a, b, c, x[k + 0], S32, 3936430074);
          c = _HH(c, d, a, b, x[k + 3], S33, 3572445317);
          b = _HH(b, c, d, a, x[k + 6], S34, 76029189);
          a = _HH(a, b, c, d, x[k + 9], S31, 3654602809);
          d = _HH(d, a, b, c, x[k + 12], S32, 3873151461);
          c = _HH(c, d, a, b, x[k + 15], S33, 530742520);
          b = _HH(b, c, d, a, x[k + 2], S34, 3299628645);
          a = _II(a, b, c, d, x[k + 0], S41, 4096336452);
          d = _II(d, a, b, c, x[k + 7], S42, 1126891415);
          c = _II(c, d, a, b, x[k + 14], S43, 2878612391);
          b = _II(b, c, d, a, x[k + 5], S44, 4237533241);
          a = _II(a, b, c, d, x[k + 12], S41, 1700485571);
          d = _II(d, a, b, c, x[k + 3], S42, 2399980690);
          c = _II(c, d, a, b, x[k + 10], S43, 4293915773);
          b = _II(b, c, d, a, x[k + 1], S44, 2240044497);
          a = _II(a, b, c, d, x[k + 8], S41, 1873313359);
          d = _II(d, a, b, c, x[k + 15], S42, 4264355552);
          c = _II(c, d, a, b, x[k + 6], S43, 2734768916);
          b = _II(b, c, d, a, x[k + 13], S44, 1309151649);
          a = _II(a, b, c, d, x[k + 4], S41, 4149444226);
          d = _II(d, a, b, c, x[k + 11], S42, 3174756917);
          c = _II(c, d, a, b, x[k + 2], S43, 718787259);
          b = _II(b, c, d, a, x[k + 9], S44, 3951481745);
          a = addUnsigned(a, AA);
          b = addUnsigned(b, BB);
          c = addUnsigned(c, CC);
          d = addUnsigned(d, DD);
        }
        var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
        return temp.toLowerCase();
      }
    };
    return md5;
  } ]);
})(angular);

/***/ }),
/* 57 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__event_emitter__ = __webpack_require__(22);


/* This should be the generic service */
function EventEmitterService($rootScope) {
  return new __WEBPACK_IMPORTED_MODULE_0__event_emitter__["a" /* default */]($rootScope);
}

EventEmitterService.$inject = ['$rootScope'];

/* harmony default export */ __webpack_exports__["a"] = EventEmitterService;

/***/ }),
/* 58 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash__ = __webpack_require__(125);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_muton__ = __webpack_require__(121);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_muton___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_muton__);
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }




function FeaturesToggleFactory($location, FEATURES, CookieFac, md5) {
  var overridesEnabled = true;

  // Overrides

  var ConversionDelegate = {
    toFeatures: function toFeatures(featuresStr) {
      return featuresStr.split(',').reduce(function (acc, feature) {
        var featureParts = feature.split(':');
        var featureName = featureParts[0];
        var featureValue = featureParts[1];

        return Object.assign({}, _defineProperty({}, featureName, featureValue === 'true'), acc);
      }, {});
    },
    toFeatureOverrides: function toFeatureOverrides(features) {
      var featureNames = __WEBPACK_IMPORTED_MODULE_0_lodash___default.a.keys(features);
      return __WEBPACK_IMPORTED_MODULE_0_lodash___default.a.reduce(featureNames, function (result, name) {
        var colon = result.length === 0 ? '' : ',';
        return result + colon + name + ':' + __WEBPACK_IMPORTED_MODULE_0_lodash___default.a.get(features, name);
      }, '');
    }
  };

  var CookieDelegate = {
    getFeaturesConfigCookie: function getFeaturesConfigCookie() {
      return CookieFac.getEncodedCookie('featuresConfig');
    },
    setFeaturesConfigCookie: function setFeaturesConfigCookie(rawFeatures) {
      if (!__WEBPACK_IMPORTED_MODULE_0_lodash___default.a.isUndefined(rawFeatures)) {
        var features = md5.createHash(JSON.stringify(rawFeatures));
        CookieFac.setEncodedCookie('featuresConfig', features, { path: '/' });
      }
    },
    getFeaturesCookieContent: function getFeaturesCookieContent() {
      return CookieFac.getEncodedCookie('features');
    },
    setFeaturesCookie: function setFeaturesCookie(features) {
      var featureOverrides = ConversionDelegate.toFeatureOverrides(features);
      CookieFac.setEncodedCookie('features', featureOverrides, { path: '/' });
    },
    hasCookieOverrides: function hasCookieOverrides() {
      var cookieContent = CookieDelegate.getFeaturesCookieContent();
      return __WEBPACK_IMPORTED_MODULE_0_lodash___default.a.isString(cookieContent) && cookieContent.length;
    },
    getFeaturesCookie: function getFeaturesCookie() {
      var featureContent = CookieDelegate.getFeaturesCookieContent();
      return ConversionDelegate.toFeatures(featureContent);
    }
  };

  var UrlDelegate = {
    hasUrlOverrides: function hasUrlOverrides() {
      return !__WEBPACK_IMPORTED_MODULE_0_lodash___default.a.isUndefined($location.search().featureOverrides);
    },
    getUrlOverrides: function getUrlOverrides() {
      return ConversionDelegate.toFeatures($location.search().featureOverrides);
    }
  };

  var ConfigDelegate = {
    configChanged: function configChanged(rawFeatures) {
      var featuresConfig = md5.createHash(JSON.stringify(rawFeatures));
      var persistedFeaturesConfig = CookieDelegate.getFeaturesConfigCookie();
      return !__WEBPACK_IMPORTED_MODULE_0_lodash___default.a.isEqual(featuresConfig, persistedFeaturesConfig);
    },
    isOverridesEnabled: function isOverridesEnabled() {
      return !__WEBPACK_IMPORTED_MODULE_0_lodash___default.a.isUndefined(overridesEnabled) && overridesEnabled;
    }
  };

  function _getFeatures(userProperties) {
    var featuresFromConf = __WEBPACK_IMPORTED_MODULE_1_muton___default.a.getFeatureMutations(userProperties, FEATURES);
    var features = void 0;

    overridesEnabled = __WEBPACK_IMPORTED_MODULE_0_lodash___default.a.get(featuresFromConf, 'featureOverridesEnabled');
    featuresFromConf = __WEBPACK_IMPORTED_MODULE_0_lodash___default.a.omit(featuresFromConf, 'featureOverridesEnabled');

    if (ConfigDelegate.isOverridesEnabled() && UrlDelegate.hasUrlOverrides()) {
      features = UrlDelegate.getUrlOverrides();
      CookieDelegate.setFeaturesCookie(features);
      CookieDelegate.setFeaturesConfigCookie(FEATURES);
    } else if (CookieDelegate.hasCookieOverrides() && !ConfigDelegate.configChanged(FEATURES)) {
      features = CookieDelegate.getFeaturesCookie();
    } else {
      features = featuresFromConf;
      CookieDelegate.setFeaturesCookie(features);
      CookieDelegate.setFeaturesConfigCookie(FEATURES);
    }

    return features;
  }

  function _setFeatures(features) {
    CookieDelegate.setFeaturesCookie(features);
  }

  function _areOverridesEnabled() {
    return ConfigDelegate.isOverridesEnabled();
  }

  return {
    getFeatures: _getFeatures,
    setFeatures: _setFeatures,
    areOverridesEnabled: _areOverridesEnabled
  };
}

FeaturesToggleFactory.$inject = ['$location', 'FEATURES', 'CookieFac', 'md5'];

/* harmony default export */ __webpack_exports__["a"] = FeaturesToggleFactory;

/***/ }),
/* 59 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__user_actions_events__ = __webpack_require__(63);


var UserActionEventsService = function UserActionEventsService($rootScope) {
  return new __WEBPACK_IMPORTED_MODULE_0__user_actions_events__["a" /* default */]($rootScope);
};

UserActionEventsService.inject = ['$rootScope'];

/* harmony default export */ __webpack_exports__["a"] = UserActionEventsService;

/***/ }),
/* 60 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_angular__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__event_emitter_service__ = __webpack_require__(57);



/* harmony default export */ __webpack_exports__["default"] = __WEBPACK_IMPORTED_MODULE_0_angular___default.a.module('EventEmitter', []).service('EventEmitterService', __WEBPACK_IMPORTED_MODULE_1__event_emitter_service__["a" /* default */]).name;

/***/ }),
/* 61 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_angular__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_angular_md5__ = __webpack_require__(56);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_angular_md5___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_angular_md5__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__cookies__ = __webpack_require__(16);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__features_toggle_factory__ = __webpack_require__(58);





/* harmony default export */ __webpack_exports__["default"] = __WEBPACK_IMPORTED_MODULE_0_angular___default.a.module('FeaturesToggle', [__WEBPACK_IMPORTED_MODULE_1_angular_md5___default.a, __WEBPACK_IMPORTED_MODULE_2__cookies__["default"]]).factory('FeaturesFac', __WEBPACK_IMPORTED_MODULE_3__features_toggle_factory__["a" /* default */]).name;

/***/ }),
/* 62 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_angular__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__user_actions_events_service__ = __webpack_require__(59);



/* harmony default export */ __webpack_exports__["default"] = __WEBPACK_IMPORTED_MODULE_0_angular___default.a.module('UserActionEvents', []).service('UserActionEventsService', __WEBPACK_IMPORTED_MODULE_1__user_actions_events_service__["a" /* default */]).name;

/***/ }),
/* 63 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__event_emitter_event_emitter__ = __webpack_require__(22);
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }



/**
 * Notifies interested parties about user generated actions
 *
 * @class UserActionEvents
 * @extends EventEmitter
 */

var UserActionEvents = function (_EventsEmitter) {
  _inherits(UserActionEvents, _EventsEmitter);

  function UserActionEvents(emitter /* $rootScope */) {
    _classCallCheck(this, UserActionEvents);

    var _this = _possibleConstructorReturn(this, (UserActionEvents.__proto__ || Object.getPrototypeOf(UserActionEvents)).call(this, emitter));

    _this.namespace = 'useraction';
    return _this;
  }

  return UserActionEvents;
}(__WEBPACK_IMPORTED_MODULE_0__event_emitter_event_emitter__["a" /* default */]);

/* harmony default export */ __webpack_exports__["a"] = UserActionEvents;

/***/ }),
/* 64 */
/***/ (function(module, exports, __webpack_require__) {

module.exports = __webpack_require__(31);


/***/ }),
/* 65 */
/***/ (function(module, exports, __webpack_require__) {

var baseEach = __webpack_require__(9),
    createFind = __webpack_require__(41);

/**
 * Iterates over elements of `collection`, returning the first element
 * `predicate` returns truthy for. The predicate is bound to `thisArg` and
 * invoked with three arguments: (value, index|key, collection).
 *
 * If a property name is provided for `predicate` the created `_.property`
 * style callback returns the property value of the given element.
 *
 * If a value is also provided for `thisArg` the created `_.matchesProperty`
 * style callback returns `true` for elements that have a matching property
 * value, else `false`.
 *
 * If an object is provided for `predicate` the created `_.matches` style
 * callback returns `true` for elements that have the properties of the given
 * object, else `false`.
 *
 * @static
 * @memberOf _
 * @alias detect
 * @category Collection
 * @param {Array|Object|string} collection The collection to search.
 * @param {Function|Object|string} [predicate=_.identity] The function invoked
 *  per iteration.
 * @param {*} [thisArg] The `this` binding of `predicate`.
 * @returns {*} Returns the matched element, else `undefined`.
 * @example
 *
 * var users = [
 *   { 'user': 'barney',  'age': 36, 'active': true },
 *   { 'user': 'fred',    'age': 40, 'active': false },
 *   { 'user': 'pebbles', 'age': 1,  'active': true }
 * ];
 *
 * _.result(_.find(users, function(chr) {
 *   return chr.age < 40;
 * }), 'user');
 * // => 'barney'
 *
 * // using the `_.matches` callback shorthand
 * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
 * // => 'pebbles'
 *
 * // using the `_.matchesProperty` callback shorthand
 * _.result(_.find(users, 'active', false), 'user');
 * // => 'fred'
 *
 * // using the `_.property` callback shorthand
 * _.result(_.find(users, 'active'), 'user');
 * // => 'barney'
 */
var find = createFind(baseEach);

module.exports = find;


/***/ }),
/* 66 */
/***/ (function(module, exports, __webpack_require__) {

var baseEachRight = __webpack_require__(78),
    createFind = __webpack_require__(41);

/**
 * This method is like `_.find` except that it iterates over elements of
 * `collection` from right to left.
 *
 * @static
 * @memberOf _
 * @category Collection
 * @param {Array|Object|string} collection The collection to search.
 * @param {Function|Object|string} [predicate=_.identity] The function invoked
 *  per iteration.
 * @param {*} [thisArg] The `this` binding of `predicate`.
 * @returns {*} Returns the matched element, else `undefined`.
 * @example
 *
 * _.findLast([1, 2, 3, 4], function(n) {
 *   return n % 2 == 1;
 * });
 * // => 3
 */
var findLast = createFind(baseEachRight, true);

module.exports = findLast;


/***/ }),
/* 67 */
/***/ (function(module, exports, __webpack_require__) {

var arrayEach = __webpack_require__(33),
    baseEach = __webpack_require__(9),
    createForEach = __webpack_require__(99);

/**
 * Iterates over elements of `collection` invoking `iteratee` for each element.
 * The `iteratee` is bound to `thisArg` and invoked with three arguments:
 * (value, index|key, collection). Iteratee functions may exit iteration early
 * by explicitly returning `false`.
 *
 * **Note:** As with other "Collections" methods, objects with a "length" property
 * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
 * may be used for object iteration.
 *
 * @static
 * @memberOf _
 * @alias each
 * @category Collection
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 * @param {*} [thisArg] The `this` binding of `iteratee`.
 * @returns {Array|Object|string} Returns `collection`.
 * @example
 *
 * _([1, 2]).forEach(function(n) {
 *   console.log(n);
 * }).value();
 * // => logs each value from left to right and returns the array
 *
 * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
 *   console.log(n, key);
 * });
 * // => logs each value-key pair and returns the object (iteration order is not guaranteed)
 */
var forEach = createForEach(arrayEach, baseEach);

module.exports = forEach;


/***/ }),
/* 68 */
/***/ (function(module, exports, __webpack_require__) {

var arrayMap = __webpack_require__(73),
    baseCallback = __webpack_require__(10),
    baseMap = __webpack_require__(89),
    isArray = __webpack_require__(0);

/**
 * Creates an array of values by running each element in `collection` through
 * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three
 * arguments: (value, index|key, collection).
 *
 * If a property name is provided for `iteratee` the created `_.property`
 * style callback returns the property value of the given element.
 *
 * If a value is also provided for `thisArg` the created `_.matchesProperty`
 * style callback returns `true` for elements that have a matching property
 * value, else `false`.
 *
 * If an object is provided for `iteratee` the created `_.matches` style
 * callback returns `true` for elements that have the properties of the given
 * object, else `false`.
 *
 * Many lodash methods are guarded to work as iteratees for methods like
 * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
 *
 * The guarded methods are:
 * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,
 * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,
 * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,
 * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,
 * `sum`, `uniq`, and `words`
 *
 * @static
 * @memberOf _
 * @alias collect
 * @category Collection
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function|Object|string} [iteratee=_.identity] The function invoked
 *  per iteration.
 * @param {*} [thisArg] The `this` binding of `iteratee`.
 * @returns {Array} Returns the new mapped array.
 * @example
 *
 * function timesThree(n) {
 *   return n * 3;
 * }
 *
 * _.map([1, 2], timesThree);
 * // => [3, 6]
 *
 * _.map({ 'a': 1, 'b': 2 }, timesThree);
 * // => [3, 6] (iteration order is not guaranteed)
 *
 * var users = [
 *   { 'user': 'barney' },
 *   { 'user': 'fred' }
 * ];
 *
 * // using the `_.property` callback shorthand
 * _.map(users, 'user');
 * // => ['barney', 'fred']
 */
function map(collection, iteratee, thisArg) {
  var func = isArray(collection) ? arrayMap : baseMap;
  iteratee = baseCallback(iteratee, thisArg, 3);
  return func(collection, iteratee);
}

module.exports = map;


/***/ }),
/* 69 */
/***/ (function(module, exports, __webpack_require__) {

var map = __webpack_require__(68),
    property = __webpack_require__(51);

/**
 * Gets the property value of `path` from all elements in `collection`.
 *
 * @static
 * @memberOf _
 * @category Collection
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Array|string} path The path of the property to pluck.
 * @returns {Array} Returns the property values.
 * @example
 *
 * var users = [
 *   { 'user': 'barney', 'age': 36 },
 *   { 'user': 'fred',   'age': 40 }
 * ];
 *
 * _.pluck(users, 'user');
 * // => ['barney', 'fred']
 *
 * var userIndex = _.indexBy(users, 'user');
 * _.pluck(userIndex, 'age');
 * // => [36, 40] (iteration order is not guaranteed)
 */
function pluck(collection, path) {
  return map(collection, property(path));
}

module.exports = pluck;


/***/ }),
/* 70 */
/***/ (function(module, exports, __webpack_require__) {

var arrayReduce = __webpack_require__(75),
    baseEach = __webpack_require__(9),
    createReduce = __webpack_require__(100);

/**
 * Reduces `collection` to a value which is the accumulated result of running
 * each element in `collection` through `iteratee`, where each successive
 * invocation is supplied the return value of the previous. If `accumulator`
 * is not provided the first element of `collection` is used as the initial
 * value. The `iteratee` is bound to `thisArg` and invoked with four arguments:
 * (accumulator, value, index|key, collection).
 *
 * Many lodash methods are guarded to work as iteratees for methods like
 * `_.reduce`, `_.reduceRight`, and `_.transform`.
 *
 * The guarded methods are:
 * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`,
 * and `sortByOrder`
 *
 * @static
 * @memberOf _
 * @alias foldl, inject
 * @category Collection
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 * @param {*} [accumulator] The initial value.
 * @param {*} [thisArg] The `this` binding of `iteratee`.
 * @returns {*} Returns the accumulated value.
 * @example
 *
 * _.reduce([1, 2], function(total, n) {
 *   return total + n;
 * });
 * // => 3
 *
 * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
 *   result[key] = n * 3;
 *   return result;
 * }, {});
 * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
 */
var reduce = createReduce(arrayReduce, baseEach);

module.exports = reduce;


/***/ }),
/* 71 */
/***/ (function(module, exports) {

/**
 * Copies the values of `source` to `array`.
 *
 * @private
 * @param {Array} source The array to copy values from.
 * @param {Array} [array=[]] The array to copy values to.
 * @returns {Array} Returns `array`.
 */
function arrayCopy(source, array) {
  var index = -1,
      length = source.length;

  array || (array = Array(length));
  while (++index < length) {
    array[index] = source[index];
  }
  return array;
}

module.exports = arrayCopy;


/***/ }),
/* 72 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.filter` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
      length = array.length,
      resIndex = -1,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[++resIndex] = value;
    }
  }
  return result;
}

module.exports = arrayFilter;


/***/ }),
/* 73 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.map` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the new mapped array.
 */
function arrayMap(array, iteratee) {
  var index = -1,
      length = array.length,
      result = Array(length);

  while (++index < length) {
    result[index] = iteratee(array[index], index, array);
  }
  return result;
}

module.exports = arrayMap;


/***/ }),
/* 74 */
/***/ (function(module, exports) {

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

module.exports = arrayPush;


/***/ }),
/* 75 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.reduce` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {*} [accumulator] The initial value.
 * @param {boolean} [initFromArray] Specify using the first element of `array`
 *  as the initial value.
 * @returns {*} Returns the accumulated value.
 */
function arrayReduce(array, iteratee, accumulator, initFromArray) {
  var index = -1,
      length = array.length;

  if (initFromArray && length) {
    accumulator = array[++index];
  }
  while (++index < length) {
    accumulator = iteratee(accumulator, array[index], index, array);
  }
  return accumulator;
}

module.exports = arrayReduce;


/***/ }),
/* 76 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.some` for arrays without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array.length;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

module.exports = arraySome;


/***/ }),
/* 77 */
/***/ (function(module, exports) {

/**
 * Copies properties of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy properties from.
 * @param {Array} props The property names to copy.
 * @param {Object} [object={}] The object to copy properties to.
 * @returns {Object} Returns `object`.
 */
function baseCopy(source, props, object) {
  object || (object = {});

  var index = -1,
      length = props.length;

  while (++index < length) {
    var key = props[index];
    object[key] = source[key];
  }
  return object;
}

module.exports = baseCopy;


/***/ }),
/* 78 */
/***/ (function(module, exports, __webpack_require__) {

var baseForOwnRight = __webpack_require__(84),
    createBaseEach = __webpack_require__(39);

/**
 * The base implementation of `_.forEachRight` without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array|Object|string} Returns `collection`.
 */
var baseEachRight = createBaseEach(baseForOwnRight, true);

module.exports = baseEachRight;


/***/ }),
/* 79 */
/***/ (function(module, exports, __webpack_require__) {

var baseEach = __webpack_require__(9);

/**
 * The base implementation of `_.filter` without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function baseFilter(collection, predicate) {
  var result = [];
  baseEach(collection, function(value, index, collection) {
    if (predicate(value, index, collection)) {
      result.push(value);
    }
  });
  return result;
}

module.exports = baseFilter;


/***/ }),
/* 80 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,
 * without support for callback shorthands and `this` binding, which iterates
 * over `collection` using the provided `eachFunc`.
 *
 * @private
 * @param {Array|Object|string} collection The collection to search.
 * @param {Function} predicate The function invoked per iteration.
 * @param {Function} eachFunc The function to iterate over `collection`.
 * @param {boolean} [retKey] Specify returning the key of the found element
 *  instead of the element itself.
 * @returns {*} Returns the found element or its key, else `undefined`.
 */
function baseFind(collection, predicate, eachFunc, retKey) {
  var result;
  eachFunc(collection, function(value, key, collection) {
    if (predicate(value, key, collection)) {
      result = retKey ? key : value;
      return false;
    }
  });
  return result;
}

module.exports = baseFind;


/***/ }),
/* 81 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.findIndex` and `_.findLastIndex` without
 * support for callback shorthands and `this` binding.
 *
 * @private
 * @param {Array} array The array to search.
 * @param {Function} predicate The function invoked per iteration.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function baseFindIndex(array, predicate, fromRight) {
  var length = array.length,
      index = fromRight ? length : -1;

  while ((fromRight ? index-- : ++index < length)) {
    if (predicate(array[index], index, array)) {
      return index;
    }
  }
  return -1;
}

module.exports = baseFindIndex;


/***/ }),
/* 82 */
/***/ (function(module, exports, __webpack_require__) {

var arrayPush = __webpack_require__(74),
    isArguments = __webpack_require__(8),
    isArray = __webpack_require__(0),
    isArrayLike = __webpack_require__(6),
    isObjectLike = __webpack_require__(2);

/**
 * The base implementation of `_.flatten` with added support for restricting
 * flattening and specifying the start index.
 *
 * @private
 * @param {Array} array The array to flatten.
 * @param {boolean} [isDeep] Specify a deep flatten.
 * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
 * @param {Array} [result=[]] The initial result value.
 * @returns {Array} Returns the new flattened array.
 */
function baseFlatten(array, isDeep, isStrict, result) {
  result || (result = []);

  var index = -1,
      length = array.length;

  while (++index < length) {
    var value = array[index];
    if (isObjectLike(value) && isArrayLike(value) &&
        (isStrict || isArray(value) || isArguments(value))) {
      if (isDeep) {
        // Recursively flatten arrays (susceptible to call stack limits).
        baseFlatten(value, isDeep, isStrict, result);
      } else {
        arrayPush(result, value);
      }
    } else if (!isStrict) {
      result[result.length] = value;
    }
  }
  return result;
}

module.exports = baseFlatten;


/***/ }),
/* 83 */
/***/ (function(module, exports, __webpack_require__) {

var baseFor = __webpack_require__(34),
    keys = __webpack_require__(5);

/**
 * The base implementation of `_.forOwn` without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function baseForOwn(object, iteratee) {
  return baseFor(object, iteratee, keys);
}

module.exports = baseForOwn;


/***/ }),
/* 84 */
/***/ (function(module, exports, __webpack_require__) {

var baseForRight = __webpack_require__(85),
    keys = __webpack_require__(5);

/**
 * The base implementation of `_.forOwnRight` without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function baseForOwnRight(object, iteratee) {
  return baseForRight(object, iteratee, keys);
}

module.exports = baseForOwnRight;


/***/ }),
/* 85 */
/***/ (function(module, exports, __webpack_require__) {

var createBaseFor = __webpack_require__(40);

/**
 * This function is like `baseFor` except that it iterates over properties
 * in the opposite order.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @returns {Object} Returns `object`.
 */
var baseForRight = createBaseFor(true);

module.exports = baseForRight;


/***/ }),
/* 86 */
/***/ (function(module, exports, __webpack_require__) {

var indexOfNaN = __webpack_require__(105);

/**
 * The base implementation of `_.indexOf` without support for binary searches.
 *
 * @private
 * @param {Array} array The array to search.
 * @param {*} value The value to search for.
 * @param {number} fromIndex The index to search from.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function baseIndexOf(array, value, fromIndex) {
  if (value !== value) {
    return indexOfNaN(array, fromIndex);
  }
  var index = fromIndex - 1,
      length = array.length;

  while (++index < length) {
    if (array[index] === value) {
      return index;
    }
  }
  return -1;
}

module.exports = baseIndexOf;


/***/ }),
/* 87 */
/***/ (function(module, exports, __webpack_require__) {

var equalArrays = __webpack_require__(101),
    equalByTag = __webpack_require__(102),
    equalObjects = __webpack_require__(103),
    isArray = __webpack_require__(0),
    isTypedArray = __webpack_require__(19);

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    objectTag = '[object Object]';

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objToString = objectProto.toString;

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} [customizer] The function to customize comparing objects.
 * @param {boolean} [isLoose] Specify performing partial comparisons.
 * @param {Array} [stackA=[]] Tracks traversed `value` objects.
 * @param {Array} [stackB=[]] Tracks traversed `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
  var objIsArr = isArray(object),
      othIsArr = isArray(other),
      objTag = arrayTag,
      othTag = arrayTag;

  if (!objIsArr) {
    objTag = objToString.call(object);
    if (objTag == argsTag) {
      objTag = objectTag;
    } else if (objTag != objectTag) {
      objIsArr = isTypedArray(object);
    }
  }
  if (!othIsArr) {
    othTag = objToString.call(other);
    if (othTag == argsTag) {
      othTag = objectTag;
    } else if (othTag != objectTag) {
      othIsArr = isTypedArray(other);
    }
  }
  var objIsObj = objTag == objectTag,
      othIsObj = othTag == objectTag,
      isSameTag = objTag == othTag;

  if (isSameTag && !(objIsArr || objIsObj)) {
    return equalByTag(object, other, objTag);
  }
  if (!isLoose) {
    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
    }
  }
  if (!isSameTag) {
    return false;
  }
  // Assume cyclic values are equal.
  // For more information on detecting circular references see https://es5.github.io/#JO.
  stackA || (stackA = []);
  stackB || (stackB = []);

  var length = stackA.length;
  while (length--) {
    if (stackA[length] == object) {
      return stackB[length] == other;
    }
  }
  // Add `object` and `other` to the stack of traversed objects.
  stackA.push(object);
  stackB.push(other);

  var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);

  stackA.pop();
  stackB.pop();

  return result;
}

module.exports = baseIsEqualDeep;


/***/ }),
/* 88 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsEqual = __webpack_require__(36),
    toObject = __webpack_require__(3);

/**
 * The base implementation of `_.isMatch` without support for callback
 * shorthands and `this` binding.
 *
 * @private
 * @param {Object} object The object to inspect.
 * @param {Array} matchData The propery names, values, and compare flags to match.
 * @param {Function} [customizer] The function to customize comparing objects.
 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
 */
function baseIsMatch(object, matchData, customizer) {
  var index = matchData.length,
      length = index,
      noCustomizer = !customizer;

  if (object == null) {
    return !length;
  }
  object = toObject(object);
  while (index--) {
    var data = matchData[index];
    if ((noCustomizer && data[2])
          ? data[1] !== object[data[0]]
          : !(data[0] in object)
        ) {
      return false;
    }
  }
  while (++index < length) {
    data = matchData[index];
    var key = data[0],
        objValue = object[key],
        srcValue = data[1];

    if (noCustomizer && data[2]) {
      if (objValue === undefined && !(key in object)) {
        return false;
      }
    } else {
      var result = customizer ? customizer(objValue, srcValue, key) : undefined;
      if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {
        return false;
      }
    }
  }
  return true;
}

module.exports = baseIsMatch;


/***/ }),
/* 89 */
/***/ (function(module, exports, __webpack_require__) {

var baseEach = __webpack_require__(9),
    isArrayLike = __webpack_require__(6);

/**
 * The base implementation of `_.map` without support for callback shorthands
 * and `this` binding.
 *
 * @private
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the new mapped array.
 */
function baseMap(collection, iteratee) {
  var index = -1,
      result = isArrayLike(collection) ? Array(collection.length) : [];

  baseEach(collection, function(value, key, collection) {
    result[++index] = iteratee(value, key, collection);
  });
  return result;
}

module.exports = baseMap;


/***/ }),
/* 90 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsMatch = __webpack_require__(88),
    getMatchData = __webpack_require__(104),
    toObject = __webpack_require__(3);

/**
 * The base implementation of `_.matches` which does not clone `source`.
 *
 * @private
 * @param {Object} source The object of property values to match.
 * @returns {Function} Returns the new function.
 */
function baseMatches(source) {
  var matchData = getMatchData(source);
  if (matchData.length == 1 && matchData[0][2]) {
    var key = matchData[0][0],
        value = matchData[0][1];

    return function(object) {
      if (object == null) {
        return false;
      }
      return object[key] === value && (value !== undefined || (key in toObject(object)));
    };
  }
  return function(object) {
    return baseIsMatch(object, matchData);
  };
}

module.exports = baseMatches;


/***/ }),
/* 91 */
/***/ (function(module, exports, __webpack_require__) {

var baseGet = __webpack_require__(11),
    baseIsEqual = __webpack_require__(36),
    baseSlice = __webpack_require__(38),
    isArray = __webpack_require__(0),
    isKey = __webpack_require__(18),
    isStrictComparable = __webpack_require__(44),
    last = __webpack_require__(29),
    toObject = __webpack_require__(3),
    toPath = __webpack_require__(14);

/**
 * The base implementation of `_.matchesProperty` which does not clone `srcValue`.
 *
 * @private
 * @param {string} path The path of the property to get.
 * @param {*} srcValue The value to compare.
 * @returns {Function} Returns the new function.
 */
function baseMatchesProperty(path, srcValue) {
  var isArr = isArray(path),
      isCommon = isKey(path) && isStrictComparable(srcValue),
      pathKey = (path + '');

  path = toPath(path);
  return function(object) {
    if (object == null) {
      return false;
    }
    var key = pathKey;
    object = toObject(object);
    if ((isArr || !isCommon) && !(key in object)) {
      object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
      if (object == null) {
        return false;
      }
      key = last(path);
      object = toObject(object);
    }
    return object[key] === srcValue
      ? (srcValue !== undefined || (key in object))
      : baseIsEqual(srcValue, object[key], undefined, true);
  };
}

module.exports = baseMatchesProperty;


/***/ }),
/* 92 */
/***/ (function(module, exports, __webpack_require__) {

var arrayEach = __webpack_require__(33),
    baseMergeDeep = __webpack_require__(93),
    isArray = __webpack_require__(0),
    isArrayLike = __webpack_require__(6),
    isObject = __webpack_require__(4),
    isObjectLike = __webpack_require__(2),
    isTypedArray = __webpack_require__(19),
    keys = __webpack_require__(5);

/**
 * The base implementation of `_.merge` without support for argument juggling,
 * multiple sources, and `this` binding `customizer` functions.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {Function} [customizer] The function to customize merged values.
 * @param {Array} [stackA=[]] Tracks traversed source objects.
 * @param {Array} [stackB=[]] Associates values with source counterparts.
 * @returns {Object} Returns `object`.
 */
function baseMerge(object, source, customizer, stackA, stackB) {
  if (!isObject(object)) {
    return object;
  }
  var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),
      props = isSrcArr ? undefined : keys(source);

  arrayEach(props || source, function(srcValue, key) {
    if (props) {
      key = srcValue;
      srcValue = source[key];
    }
    if (isObjectLike(srcValue)) {
      stackA || (stackA = []);
      stackB || (stackB = []);
      baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
    }
    else {
      var value = object[key],
          result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
          isCommon = result === undefined;

      if (isCommon) {
        result = srcValue;
      }
      if ((result !== undefined || (isSrcArr && !(key in object))) &&
          (isCommon || (result === result ? (result !== value) : (value === value)))) {
        object[key] = result;
      }
    }
  });
  return object;
}

module.exports = baseMerge;


/***/ }),
/* 93 */
/***/ (function(module, exports, __webpack_require__) {

var arrayCopy = __webpack_require__(71),
    isArguments = __webpack_require__(8),
    isArray = __webpack_require__(0),
    isArrayLike = __webpack_require__(6),
    isPlainObject = __webpack_require__(47),
    isTypedArray = __webpack_require__(19),
    toPlainObject = __webpack_require__(112);

/**
 * A specialized version of `baseMerge` for arrays and objects which performs
 * deep merges and tracks traversed objects enabling objects with circular
 * references to be merged.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {string} key The key of the value to merge.
 * @param {Function} mergeFunc The function to merge values.
 * @param {Function} [customizer] The function to customize merged values.
 * @param {Array} [stackA=[]] Tracks traversed source objects.
 * @param {Array} [stackB=[]] Associates values with source counterparts.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
  var length = stackA.length,
      srcValue = source[key];

  while (length--) {
    if (stackA[length] == srcValue) {
      object[key] = stackB[length];
      return;
    }
  }
  var value = object[key],
      result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
      isCommon = result === undefined;

  if (isCommon) {
    result = srcValue;
    if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
      result = isArray(value)
        ? value
        : (isArrayLike(value) ? arrayCopy(value) : []);
    }
    else if (isPlainObject(srcValue) || isArguments(srcValue)) {
      result = isArguments(value)
        ? toPlainObject(value)
        : (isPlainObject(value) ? value : {});
    }
    else {
      isCommon = false;
    }
  }
  // Add the source value to the stack of traversed objects and associate
  // it with its merged value.
  stackA.push(srcValue);
  stackB.push(result);

  if (isCommon) {
    // Recursively merge objects and arrays (susceptible to call stack limits).
    object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
  } else if (result === result ? (result !== value) : (value === value)) {
    object[key] = result;
  }
}

module.exports = baseMergeDeep;


/***/ }),
/* 94 */
/***/ (function(module, exports, __webpack_require__) {

var baseGet = __webpack_require__(11),
    toPath = __webpack_require__(14);

/**
 * A specialized version of `baseProperty` which supports deep paths.
 *
 * @private
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new function.
 */
function basePropertyDeep(path) {
  var pathKey = (path + '');
  path = toPath(path);
  return function(object) {
    return baseGet(object, path, pathKey);
  };
}

module.exports = basePropertyDeep;


/***/ }),
/* 95 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.reduce` and `_.reduceRight` without support
 * for callback shorthands and `this` binding, which iterates over `collection`
 * using the provided `eachFunc`.
 *
 * @private
 * @param {Array|Object|string} collection The collection to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {*} accumulator The initial value.
 * @param {boolean} initFromCollection Specify using the first or last element
 *  of `collection` as the initial value.
 * @param {Function} eachFunc The function to iterate over `collection`.
 * @returns {*} Returns the accumulated value.
 */
function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {
  eachFunc(collection, function(value, index, collection) {
    accumulator = initFromCollection
      ? (initFromCollection = false, value)
      : iteratee(accumulator, value, index, collection);
  });
  return accumulator;
}

module.exports = baseReduce;


/***/ }),
/* 96 */
/***/ (function(module, exports) {

/**
 * Converts `value` to a string if it's not one. An empty string is returned
 * for `null` or `undefined` values.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  return value == null ? '' : (value + '');
}

module.exports = baseToString;


/***/ }),
/* 97 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.values` and `_.valuesIn` which creates an
 * array of `object` property values corresponding to the property names
 * of `props`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array} props The property names to get values for.
 * @returns {Object} Returns the array of property values.
 */
function baseValues(object, props) {
  var index = -1,
      length = props.length,
      result = Array(length);

  while (++index < length) {
    result[index] = object[props[index]];
  }
  return result;
}

module.exports = baseValues;


/***/ }),
/* 98 */
/***/ (function(module, exports, __webpack_require__) {

var bindCallback = __webpack_require__(12),
    isIterateeCall = __webpack_require__(43),
    restParam = __webpack_require__(32);

/**
 * Creates a `_.assign`, `_.defaults`, or `_.merge` function.
 *
 * @private
 * @param {Function} assigner The function to assign values.
 * @returns {Function} Returns the new assigner function.
 */
function createAssigner(assigner) {
  return restParam(function(object, sources) {
    var index = -1,
        length = object == null ? 0 : sources.length,
        customizer = length > 2 ? sources[length - 2] : undefined,
        guard = length > 2 ? sources[2] : undefined,
        thisArg = length > 1 ? sources[length - 1] : undefined;

    if (typeof customizer == 'function') {
      customizer = bindCallback(customizer, thisArg, 5);
      length -= 2;
    } else {
      customizer = typeof thisArg == 'function' ? thisArg : undefined;
      length -= (customizer ? 1 : 0);
    }
    if (guard && isIterateeCall(sources[0], sources[1], guard)) {
      customizer = length < 3 ? undefined : customizer;
      length = 1;
    }
    while (++index < length) {
      var source = sources[index];
      if (source) {
        assigner(object, source, customizer);
      }
    }
    return object;
  });
}

module.exports = createAssigner;


/***/ }),
/* 99 */
/***/ (function(module, exports, __webpack_require__) {

var bindCallback = __webpack_require__(12),
    isArray = __webpack_require__(0);

/**
 * Creates a function for `_.forEach` or `_.forEachRight`.
 *
 * @private
 * @param {Function} arrayFunc The function to iterate over an array.
 * @param {Function} eachFunc The function to iterate over a collection.
 * @returns {Function} Returns the new each function.
 */
function createForEach(arrayFunc, eachFunc) {
  return function(collection, iteratee, thisArg) {
    return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
      ? arrayFunc(collection, iteratee)
      : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
  };
}

module.exports = createForEach;


/***/ }),
/* 100 */
/***/ (function(module, exports, __webpack_require__) {

var baseCallback = __webpack_require__(10),
    baseReduce = __webpack_require__(95),
    isArray = __webpack_require__(0);

/**
 * Creates a function for `_.reduce` or `_.reduceRight`.
 *
 * @private
 * @param {Function} arrayFunc The function to iterate over an array.
 * @param {Function} eachFunc The function to iterate over a collection.
 * @returns {Function} Returns the new each function.
 */
function createReduce(arrayFunc, eachFunc) {
  return function(collection, iteratee, accumulator, thisArg) {
    var initFromArray = arguments.length < 3;
    return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
      ? arrayFunc(collection, iteratee, accumulator, initFromArray)
      : baseReduce(collection, baseCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
  };
}

module.exports = createReduce;


/***/ }),
/* 101 */
/***/ (function(module, exports, __webpack_require__) {

var arraySome = __webpack_require__(76);

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} [customizer] The function to customize comparing arrays.
 * @param {boolean} [isLoose] Specify performing partial comparisons.
 * @param {Array} [stackA] Tracks traversed `value` objects.
 * @param {Array} [stackB] Tracks traversed `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
  var index = -1,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
    return false;
  }
  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index],
        result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;

    if (result !== undefined) {
      if (result) {
        continue;
      }
      return false;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (isLoose) {
      if (!arraySome(other, function(othValue) {
            return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
          })) {
        return false;
      }
    } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {
      return false;
    }
  }
  return true;
}

module.exports = equalArrays;


/***/ }),
/* 102 */
/***/ (function(module, exports) {

/** `Object#toString` result references. */
var boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    numberTag = '[object Number]',
    regexpTag = '[object RegExp]',
    stringTag = '[object String]';

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag) {
  switch (tag) {
    case boolTag:
    case dateTag:
      // Coerce dates and booleans to numbers, dates to milliseconds and booleans
      // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
      return +object == +other;

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case numberTag:
      // Treat `NaN` vs. `NaN` as equal.
      return (object != +object)
        ? other != +other
        : object == +other;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings primitives and string
      // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
      return object == (other + '');
  }
  return false;
}

module.exports = equalByTag;


/***/ }),
/* 103 */
/***/ (function(module, exports, __webpack_require__) {

var keys = __webpack_require__(5);

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} [customizer] The function to customize comparing values.
 * @param {boolean} [isLoose] Specify performing partial comparisons.
 * @param {Array} [stackA] Tracks traversed `value` objects.
 * @param {Array} [stackB] Tracks traversed `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
  var objProps = keys(object),
      objLength = objProps.length,
      othProps = keys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isLoose) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  var skipCtor = isLoose;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key],
        result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;

    // Recursively compare objects (susceptible to call stack limits).
    if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {
      return false;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (!skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor &&
        ('constructor' in object && 'constructor' in other) &&
        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      return false;
    }
  }
  return true;
}

module.exports = equalObjects;


/***/ }),
/* 104 */
/***/ (function(module, exports, __webpack_require__) {

var isStrictComparable = __webpack_require__(44),
    pairs = __webpack_require__(114);

/**
 * Gets the propery names, values, and compare flags of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the match data of `object`.
 */
function getMatchData(object) {
  var result = pairs(object),
      length = result.length;

  while (length--) {
    result[length][2] = isStrictComparable(result[length][1]);
  }
  return result;
}

module.exports = getMatchData;


/***/ }),
/* 105 */
/***/ (function(module, exports) {

/**
 * Gets the index at which the first occurrence of `NaN` is found in `array`.
 *
 * @private
 * @param {Array} array The array to search.
 * @param {number} fromIndex The index to search from.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {number} Returns the index of the matched `NaN`, else `-1`.
 */
function indexOfNaN(array, fromIndex, fromRight) {
  var length = array.length,
      index = fromIndex + (fromRight ? 0 : -1);

  while ((fromRight ? index-- : ++index < length)) {
    var other = array[index];
    if (other !== other) {
      return index;
    }
  }
  return -1;
}

module.exports = indexOfNaN;


/***/ }),
/* 106 */
/***/ (function(module, exports, __webpack_require__) {

var toObject = __webpack_require__(3);

/**
 * A specialized version of `_.pick` which picks `object` properties specified
 * by `props`.
 *
 * @private
 * @param {Object} object The source object.
 * @param {string[]} props The property names to pick.
 * @returns {Object} Returns the new object.
 */
function pickByArray(object, props) {
  object = toObject(object);

  var index = -1,
      length = props.length,
      result = {};

  while (++index < length) {
    var key = props[index];
    if (key in object) {
      result[key] = object[key];
    }
  }
  return result;
}

module.exports = pickByArray;


/***/ }),
/* 107 */
/***/ (function(module, exports, __webpack_require__) {

var baseForIn = __webpack_require__(35);

/**
 * A specialized version of `_.pick` which picks `object` properties `predicate`
 * returns truthy for.
 *
 * @private
 * @param {Object} object The source object.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Object} Returns the new object.
 */
function pickByCallback(object, predicate) {
  var result = {};
  baseForIn(object, function(value, key, object) {
    if (predicate(value, key, object)) {
      result[key] = value;
    }
  });
  return result;
}

module.exports = pickByCallback;


/***/ }),
/* 108 */
/***/ (function(module, exports, __webpack_require__) {

var isArguments = __webpack_require__(8),
    isArray = __webpack_require__(0),
    isIndex = __webpack_require__(13),
    isLength = __webpack_require__(7),
    keysIn = __webpack_require__(21);

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * A fallback implementation of `Object.keys` which creates an array of the
 * own enumerable property names of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function shimKeys(object) {
  var props = keysIn(object),
      propsLength = props.length,
      length = propsLength && object.length;

  var allowIndexes = !!length && isLength(length) &&
    (isArray(object) || isArguments(object));

  var index = -1,
      result = [];

  while (++index < propsLength) {
    var key = props[index];
    if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
      result.push(key);
    }
  }
  return result;
}

module.exports = shimKeys;


/***/ }),
/* 109 */
/***/ (function(module, exports, __webpack_require__) {

var isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var boolTag = '[object Boolean]';

/** Used for native method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objToString = objectProto.toString;

/**
 * Checks if `value` is classified as a boolean primitive or object.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isBoolean(false);
 * // => true
 *
 * _.isBoolean(null);
 * // => false
 */
function isBoolean(value) {
  return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag);
}

module.exports = isBoolean;


/***/ }),
/* 110 */
/***/ (function(module, exports, __webpack_require__) {

var isFunction = __webpack_require__(46),
    isObjectLike = __webpack_require__(2);

/** Used to detect host constructors (Safari > 5). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to resolve the decompiled source of functions. */
var fnToString = Function.prototype.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/**
 * Checks if `value` is a native function.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
 * @example
 *
 * _.isNative(Array.prototype.push);
 * // => true
 *
 * _.isNative(_);
 * // => false
 */
function isNative(value) {
  if (value == null) {
    return false;
  }
  if (isFunction(value)) {
    return reIsNative.test(fnToString.call(value));
  }
  return isObjectLike(value) && reIsHostCtor.test(value);
}

module.exports = isNative;


/***/ }),
/* 111 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is `null`.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
 * @example
 *
 * _.isNull(null);
 * // => true
 *
 * _.isNull(void 0);
 * // => false
 */
function isNull(value) {
  return value === null;
}

module.exports = isNull;


/***/ }),
/* 112 */
/***/ (function(module, exports, __webpack_require__) {

var baseCopy = __webpack_require__(77),
    keysIn = __webpack_require__(21);

/**
 * Converts `value` to a plain object flattening inherited enumerable
 * properties of `value` to own properties of the plain object.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {Object} Returns the converted plain object.
 * @example
 *
 * function Foo() {
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.assign({ 'a': 1 }, new Foo);
 * // => { 'a': 1, 'b': 2 }
 *
 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
 * // => { 'a': 1, 'b': 2, 'c': 3 }
 */
function toPlainObject(value) {
  return baseCopy(value, keysIn(value));
}

module.exports = toPlainObject;


/***/ }),
/* 113 */
/***/ (function(module, exports, __webpack_require__) {

var baseGet = __webpack_require__(11),
    baseSlice = __webpack_require__(38),
    isArguments = __webpack_require__(8),
    isArray = __webpack_require__(0),
    isIndex = __webpack_require__(13),
    isKey = __webpack_require__(18),
    isLength = __webpack_require__(7),
    last = __webpack_require__(29),
    toPath = __webpack_require__(14);

/** Used for native method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Checks if `path` is a direct property.
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @returns {boolean} Returns `true` if `path` is a direct property, else `false`.
 * @example
 *
 * var object = { 'a': { 'b': { 'c': 3 } } };
 *
 * _.has(object, 'a');
 * // => true
 *
 * _.has(object, 'a.b.c');
 * // => true
 *
 * _.has(object, ['a', 'b', 'c']);
 * // => true
 */
function has(object, path) {
  if (object == null) {
    return false;
  }
  var result = hasOwnProperty.call(object, path);
  if (!result && !isKey(path)) {
    path = toPath(path);
    object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
    if (object == null) {
      return false;
    }
    path = last(path);
    result = hasOwnProperty.call(object, path);
  }
  return result || (isLength(object.length) && isIndex(path, object.length) &&
    (isArray(object) || isArguments(object)));
}

module.exports = has;


/***/ }),
/* 114 */
/***/ (function(module, exports, __webpack_require__) {

var keys = __webpack_require__(5),
    toObject = __webpack_require__(3);

/**
 * Creates a two dimensional array of the key-value pairs for `object`,
 * e.g. `[[key1, value1], [key2, value2]]`.
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the new array of key-value pairs.
 * @example
 *
 * _.pairs({ 'barney': 36, 'fred': 40 });
 * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)
 */
function pairs(object) {
  object = toObject(object);

  var index = -1,
      props = keys(object),
      length = props.length,
      result = Array(length);

  while (++index < length) {
    var key = props[index];
    result[index] = [key, object[key]];
  }
  return result;
}

module.exports = pairs;


/***/ }),
/* 115 */
/***/ (function(module, exports, __webpack_require__) {

var baseFlatten = __webpack_require__(82),
    bindCallback = __webpack_require__(12),
    pickByArray = __webpack_require__(106),
    pickByCallback = __webpack_require__(107),
    restParam = __webpack_require__(32);

/**
 * Creates an object composed of the picked `object` properties. Property
 * names may be specified as individual arguments or as arrays of property
 * names. If `predicate` is provided it's invoked for each property of `object`
 * picking the properties `predicate` returns truthy for. The predicate is
 * bound to `thisArg` and invoked with three arguments: (value, key, object).
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The source object.
 * @param {Function|...(string|string[])} [predicate] The function invoked per
 *  iteration or property names to pick, specified as individual property
 *  names or arrays of property names.
 * @param {*} [thisArg] The `this` binding of `predicate`.
 * @returns {Object} Returns the new object.
 * @example
 *
 * var object = { 'user': 'fred', 'age': 40 };
 *
 * _.pick(object, 'user');
 * // => { 'user': 'fred' }
 *
 * _.pick(object, _.isString);
 * // => { 'user': 'fred' }
 */
var pick = restParam(function(object, props) {
  if (object == null) {
    return {};
  }
  return typeof props[0] == 'function'
    ? pickByCallback(object, bindCallback(props[0], props[1], 3))
    : pickByArray(object, baseFlatten(props));
});

module.exports = pick;


/***/ }),
/* 116 */
/***/ (function(module, exports, __webpack_require__) {

var baseValues = __webpack_require__(97),
    keys = __webpack_require__(5);

/**
 * Creates an array of the own enumerable property values of `object`.
 *
 * **Note:** Non-object values are coerced to objects.
 *
 * @static
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property values.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.values(new Foo);
 * // => [1, 2] (iteration order is not guaranteed)
 *
 * _.values('hi');
 * // => ['h', 'i']
 */
function values(object) {
  return baseValues(object, keys(object));
}

module.exports = values;


/***/ }),
/* 117 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * The Helicase enzyme in real life breaks the double helix and separates the DNA strands.
 * This module picks the user properties collection and the features collection and break them apart into two strands of
 * names.
 */

var chemicalReactions = __webpack_require__(54);

module.exports = {
    /**
     * Returns an object containing two strands: one containing the user properties names and the other containing
     * the features names.
     *
     * @param userProperties a dictionary with user properties
     * @param feature a dictionary with features instructions
     * @returns An object that contains user property names and features names
     */
    breakProperties: function (userProperties, feature) {
        return chemicalReactions.separateProperties(userProperties, feature);
    }
};


/***/ }),
/* 118 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * The Polymerase enzyme in real life assembles a new DNA strand on top of the existing one. During the process, it
 * check for replication errors doing proof-reading on the fly. But sometimes a random mutation occur... that's life
 * trying to evolve.
 * This module takes the primer feature instructions, does proof-reading over them to make sure no errors
 * are found and then it assembles a collection of resolved feature toggles.
 *
 * In the process, even if the instructions are considered valid, random mutations occur. Those are caused by the
 * Bucket and Throttle mutators. That's your application trying to evolve.
 */
var merge = __webpack_require__(49);

var bucketMutator = __webpack_require__(52);
var throttleMutator = __webpack_require__(53);
var genePairing = __webpack_require__(120);
var proofReader = __webpack_require__(55);

function addToFeatures(features, featureName, toggle) {
    return features.push(merge({ name: featureName }, toggle));
}

function processFeatureInstructions(featureProperties, gene) {
    var toggle = {
        type: 'toggle',
        toggle: false
    };

    if (featureProperties.toggle !== false) {
        if (throttleMutator.isThrottleValid(featureProperties.throttle)) {
            toggle.toggle = throttleMutator.mutate(featureProperties.throttle, gene);
            toggle.type = 'throttle';
        } else if (featureProperties.toggle === true) {
            toggle.toggle = true;
        }
    }

    return toggle;
}

function containsBuckets(toggle, featureInstructions) {
    return toggle.toggle && bucketMutator.containsMultivariant(featureInstructions);
}

function addBucketToFeatures(features, featureName, featureInstructions, toggle, gene) {
    var bucketName = bucketMutator.mutate(featureInstructions, gene);

    var bucketToggle = {
        toggle : toggle.toggle,
        type : 'bucket'
    };

    addToFeatures(features, featureName + "." + bucketName, bucketToggle);
}

module.exports = {
    /**
     * Returns a resolved feature toggle, with the information indicating whether it's active or not. If the
     * feature mutates to a bucket, it also can contain the corresponding feature toggle.
     *
     * @param featureName The feature name being processed
     * @param primerInstructions The primer instructions to process
     * @returns A resolved feature toggle, which may mutate to a bucket feature toggle
     * @param ancestorGenes An object containing 'genes' to inherit, this only applies to throttles and buckets
     */
    assembleFeatures: function(featureName, primerInstructions, ancestorGenes) {
        var features = [];

        if (proofReader.areInstructionsValid(primerInstructions)) {

            // Get the ancestor gene based on name to be able to copy it to the descendant
            var gene = genePairing.pairGene(ancestorGenes, featureName);

            var toggle = processFeatureInstructions(primerInstructions, gene);
            addToFeatures(features, featureName, toggle);

            if (containsBuckets(toggle, primerInstructions)) {
                addBucketToFeatures(features, featureName, primerInstructions, toggle, gene);
            }
        } else {
            addToFeatures(features, featureName, { toggle: false, type: 'toggle' });
        }
        return features;
    }
};


/***/ }),
/* 119 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * The Primase enzyme in real life prepares the strand for the replication, this is called the primer.
 * This module takes the user properties and feature properties strands, analyses it and returns a primer object
 * containing instructions regarding the features to activate or deactivate.
 */
var get = __webpack_require__(48);
var pick = __webpack_require__(115);
var merge = __webpack_require__(49);
var has = __webpack_require__(113);
var isUndefined = __webpack_require__(20);
var contains = __webpack_require__(64);

var chemicalReactions = __webpack_require__(54);
var matchReading = __webpack_require__(122);

function getFeatureProperties(feature) {
    return pick(feature, ['toggle', 'throttle', 'buckets']);
}

function mergeProperties(primer, feature) {
    var properties = getFeatureProperties(feature);
    merge(primer, properties);
}

function isFeatureDisabled(primer, root) {
    var toggle = get(primer, 'toggle');
    return root && toggle === false;
}

function containsFeatureProperties(obj) {
    return has(obj, 'toggle') || has(obj, 'throttle') || has(obj, 'buckets');
}

function pickMatchedProperties(childProperties, parentProperties) {
    return !isUndefined(childProperties) ? childProperties : parentProperties;
}

function getPropertiesNode(userProperties, featurePropertyName, feature) {
    // Explode the current node to check if there are properties
    var featureProperty = feature[featurePropertyName];

    var userPropertyValue = userProperties[featurePropertyName];
    var properties = matchReading.getMatchedProperties(userPropertyValue, featureProperty);

    return pickMatchedProperties(properties, featureProperty);
}

function bindPrimer(primerInstructions, childPrimer) {
    merge(primerInstructions, childPrimer);
}

module.exports = {
    /**
     * Returns a primer collection containing instructions to toggle on or off a feature,
     * matched against the user properties.
     *
     * @param userProperties The user properties to match the features
     * @param feature The feature being processed
     * @param propertyStrands An object with the strands containing user and features properties names
     * @param root A flag to indicate if the features tree is being processed in the root
     * @returns A collection of primer instructions matched against the user properties
     */
    preparePrimer: function(userProperties, feature, propertyStrands, root) {
        var self = this;
        var primerInstructions = {};

        var userPropertyNames = propertyStrands.userPropertyNames;
        var featurePropertyNames = propertyStrands.featurePropertyNames;

        // If are feature properties on the current node, it merges with the final result
        if (containsFeatureProperties(feature)) {
            mergeProperties(primerInstructions, feature);
        }

        if (!isFeatureDisabled(primerInstructions, root)) {
            featurePropertyNames.forEach(function (featurePropertyName) {
                if (contains(userPropertyNames, featurePropertyName)) {
                    var propertiesNode = getPropertiesNode(userProperties, featurePropertyName, feature);
                    // Process the child node
                    var childStrands = chemicalReactions.separateProperties(userProperties, propertiesNode);
                    var childPrimer = self.preparePrimer(userProperties, propertiesNode, childStrands);

                    bindPrimer(primerInstructions, childPrimer);
                }
            });
        }

        return primerInstructions;
    }
};


/***/ }),
/* 120 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var filter = __webpack_require__(30);
var find = __webpack_require__(65);
var keys = __webpack_require__(5);
var isString = __webpack_require__(15);

function findWithPartialName(featureNames, partialName) {
    return filter(featureNames, function (featureName) {
        return featureName.indexOf(partialName) === 0;
    });
}

function hasPartialName(featureNames, partialName) {
    return findWithPartialName(featureNames, partialName).length > 0;
}

function containTogglesPair(genes, featureName) {
    return hasPartialName(keys(genes.toggles), featureName);
}

function containBucketsPair(genes, featureName) {
    return hasPartialName(genes.buckets, featureName);
}

function containThrottlesPair(genes, featureName) {
    return hasPartialName(genes.throttles, featureName);
}

function getBucketNameFromFeatureName(featureName) {
    var dotIndex = featureName.indexOf('.');
    return dotIndex >= 0 ? featureName.substring(dotIndex + 1) : '';
}

function getMatchingBucket(genes, featureName) {
    var matchedFeatures = findWithPartialName(genes.buckets, featureName);
    var matched = find(matchedFeatures, function (matchedBucket) {
            return genes.toggles[matchedBucket];
        });
    return isString(matched) ? getBucketNameFromFeatureName(matched) : '';
}

module.exports = {
    pairGene: function (genes, featureName) {
        var gene = {};
        if (containTogglesPair(genes, featureName)) {
            var type = 'toggle';
            var name = genes.toggles[featureName];
            if (containBucketsPair(genes, featureName)) {
                type = 'bucket';
                name = getMatchingBucket(genes, featureName);
            } else if (containThrottlesPair(genes, featureName)) {
                type = 'throttle';
            }

            gene['toggle'] = name;
            gene['type'] = type;
        }
        return gene;
    }
};


/***/ }),
/* 121 */
/***/ (function(module, exports, __webpack_require__) {

/**
 * This is the Muton.js project - a feature toggle tool with support for feature throttling and Multivariance testing.
 *
 * Some notes on the chosen metaphor:
 * I'm perfectly aware that every developer should write readable code and choose the metaphors carefully. However, it
 * was a lot of fun writing the code this way. It was a challenge to use the cell metaphor. :)
 *
 * To make things easier, read the following resume.
 *
 * DNA replication consists on three steps:
 *  1) Opening the double helix and separation of the DNA strands
 *  2) The priming of the template strand, or laying the foundation for the new DNA
 *  3) Assembly of the new DNA segment, which includes proof-reading the DNA strand.
 *
 * Here are the enzymes responsible for each step:
 *  Step 1) is executed by the Helicase enzyme
 *  Step 2) is executed by the Primase enzyme
 *  Step 3) is executed by the Polymerase enzyme
 *
 *  That's it.
 *
 * If you want to get a little deeper, please have a look at:
 * http://www.nature.com/scitable/topicpage/cells-can-replicate-their-dna-precisely-6524830
 */

var reduce = __webpack_require__(70);
var filter = __webpack_require__(30);
var pluck = __webpack_require__(69);
var forEach = __webpack_require__(67);

var helicase = __webpack_require__(117);
var primase = __webpack_require__(119);
var polymerase = __webpack_require__(118);
var proofReading = __webpack_require__(55);

function joinToggles(features, resolvedFeatures) {
    features.toggles = reduce(resolvedFeatures, function (result, elem) {
        result[elem.name] = elem.toggle;
        return result;
    }, features.toggles);
}

function joinThrottles(features, resolvedFeatures) {
    var buckets = filter(resolvedFeatures, {type : 'bucket'});
    var names = pluck('name', buckets);

    features.buckets = features.buckets.concat(names);
}

function joinBuckets(features, resolvedFeatures) {
    var throttles = filter(resolvedFeatures, {type : 'throttle'});
    var names = pluck('name', throttles);

    features.throttles = features.throttles.concat(names);
}

function joinMutations(features, resolvedFeatures) {
    joinToggles(features, resolvedFeatures);
    joinThrottles(features, resolvedFeatures);
    joinBuckets(features, resolvedFeatures);
}

var muton = {

    /**
     * Given a list of user properties and feature instructions, it returns a collection of features toggles.
     *
     * @deprecated use getMutations or inheritMutations instead
     *
     * @param userProperties (optional) A collection of user properties
     * @param featureInstructions A collection of feature instructions which can be organized as a hierarchy of properties.
     * @returns An collection of feature toggles
     */
    getFeatureMutations: function (userProperties, featureInstructions) {
        return this.getMutations(userProperties, featureInstructions).toggles;
    },

    /**
     * Given a list of user properties and feature instructions, it returns a collection of features toggles.
     *
     * @param userProperties (optional) A collection of user properties
     * @param featureInstructions A collection of feature instructions which can be organized as a hierarchy of properties.
     * @returns {{toggles: {}, buckets: Array, throttles: Array}} An collection of feature toggles
     */
    getMutations: function (userProperties, featureInstructions) {
        return this.inheritMutations(userProperties, featureInstructions, {});
    },

    /**
     * Given a list of user properties and feature instructions, it returns a collection of features toggles. If specified,
     * it can inherit ancestor genes for buckets and throttle mutations
     *
     * @param userProperties (optional) A collection of user properties
     * @param featureInstructions A collection of feature instructions which can be organized as a hierarchy of properties.
     * @param ancestorGenes (optional) The ancestor genes, which is the output of previous mutations from Muton
     * @returns {{toggles: {}, buckets: Array, throttles: Array}} An collection of feature toggles
     */
    inheritMutations: function (userProperties, featureInstructions, ancestorGenes) {
        var features = {
            toggles: {},
            buckets: [],
            throttles: []
        };

        proofReading.checkFeatureInstructions(featureInstructions);

        forEach(featureInstructions, function (feature, featureName) {
            // Helicase will break the user properties and features apart into two different chains
            var propertyChains = helicase.breakProperties(userProperties, feature);

            // Read the chains and return a primer object that will contain a set of instructions
            var primer = primase.preparePrimer(userProperties, feature, propertyChains, true);

            // Pick the primer, proof-read the instructions and then assemble the collection of feature toggles
            var resolvedFeatures = polymerase.assembleFeatures(featureName, primer, ancestorGenes);

            // Join all the mutations
            joinMutations(features, resolvedFeatures);
        });

        return features;
    }
};

module.exports = muton;


/***/ }),
/* 122 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * This module match-reads feature properties against user properties.
 */

var findLast = __webpack_require__(66);
var regexMatcher = __webpack_require__(124);
var numericMatcher = __webpack_require__(123);

var defaultMatcher = {
    matchesPropertyValue: function(userPropertyValue, propertyKey) {
        return userPropertyValue === propertyKey;
    }
};

function pickMatcher(userPropertyValue, propertyKey) {
    if (regexMatcher.isRegex(propertyKey)) {
        return regexMatcher;
    } else if (numericMatcher.isNumber(userPropertyValue) &&
        numericMatcher.isNumericQuantifier(propertyKey)) {
        return numericMatcher;
    } else {
        return defaultMatcher;
    }
}

module.exports = {
    getMatchedProperties: function(userPropertyValue, featureProperty) {
        return findLast(featureProperty, function (propertyValue, propertyKey) {
            var matcher = pickMatcher(userPropertyValue, propertyKey);
            return matcher.matchesPropertyValue(userPropertyValue, propertyKey);
        });
    }
};


/***/ }),
/* 123 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var numberRegex = /-?\d+(\.\d{1,2})?/;
var operatorRegex = /[><]=?/;

var numericQuantifierRegex = new RegExp(operatorRegex.source + numberRegex.source);
var validExpressionRegex = new RegExp(numberRegex.source + operatorRegex.source + numberRegex.source);

function isExpressionValid(expression) {
    return validExpressionRegex.test(expression);
}

module.exports = {

    isNumber: function (value) {
        return numberRegex.test(value);
    },

    isNumericQuantifier: function (value) {
        return numericQuantifierRegex.test(value);
    },

    matchesPropertyValue: function(propertyValue, numericQuantifierStr) {
        var expression = propertyValue + numericQuantifierStr;

        if (!isExpressionValid(expression)) {
            // Just to catch eventual issues with eval
            return false;
        }

        /*jshint -W061*/
        return eval(expression);
    }
};


/***/ }),
/* 124 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var regexDelimiters = /^\/.+\/$/;

function sanitizeRegexStr(regexStr) {
    return regexStr.substring(1, regexStr.length - 1);
}

module.exports = {
    isRegex: function (value) {
        return regexDelimiters.test(value);
    },

    matchesPropertyValue: function(propertyValue, regexStr) {
        var sanitisedRegex = sanitizeRegexStr(regexStr);
        var regex = new RegExp('^' + sanitisedRegex + '$');
        return regex.test(propertyValue);
    }
};


/***/ }),
/* 125 */
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_125__;

/***/ }),
/* 126 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular__ = __webpack_require__(1);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_angular___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_angular__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__cookies__ = __webpack_require__(16);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__features_toggle__ = __webpack_require__(61);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__event_emitter__ = __webpack_require__(60);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__user_actions_events__ = __webpack_require__(62);






/* harmony default export */ __webpack_exports__["default"] = __WEBPACK_IMPORTED_MODULE_0_angular___default.a.module('TVGCommon', [__WEBPACK_IMPORTED_MODULE_1__cookies__["default"], __WEBPACK_IMPORTED_MODULE_2__features_toggle__["default"], __WEBPACK_IMPORTED_MODULE_3__event_emitter__["default"], __WEBPACK_IMPORTED_MODULE_4__user_actions_events__["default"]]).name;

/***/ })
/******/ ]);
});
vendors/angular-ui-mask/dist/mask.min.js
/*!
 * angular-ui-mask
 * https://github.com/angular-ui/ui-mask
 * Version: 1.8.4 - 2016-05-17T14:33:25.025Z
 * License: MIT
 */
!function(){"use strict";angular.module("ui.mask",[]).value("uiMaskConfig",{maskDefinitions:{9:/\d/,A:/[a-zA-Z]/,"*":/[a-zA-Z0-9]/},clearOnBlur:!0,clearOnBlurPlaceholder:!1,escChar:"\\",eventsToHandle:["input","keyup","click","focus"],addDefaultPlaceholder:!0,allowInvalidValue:!1}).provider("uiMask.Config",function(){var e={};this.maskDefinitions=function(n){return e.maskDefinitions=n},this.clearOnBlur=function(n){return e.clearOnBlur=n},this.clearOnBlurPlaceholder=function(n){return e.clearOnBlurPlaceholder=n},this.eventsToHandle=function(n){return e.eventsToHandle=n},this.addDefaultPlaceholder=function(n){return e.addDefaultPlaceholder=n},this.allowInvalidValue=function(n){return e.allowInvalidValue=n},this.$get=["uiMaskConfig",function(n){var t=n;for(var a in e)angular.isObject(e[a])&&!angular.isArray(e[a])?angular.extend(t[a],e[a]):t[a]=e[a];return t}]}).directive("uiMask",["uiMask.Config",function(e){function n(e){return e===document.activeElement&&(!document.hasFocus||document.hasFocus())&&!!(e.type||e.href||~e.tabIndex)}return{priority:100,require:"ngModel",restrict:"A",compile:function(){var t=angular.copy(e);return function(e,a,i,r){function l(e){return angular.isDefined(e)?(w(e),Z?(h(),d(),!0):f()):f()}function u(e){e&&(B=e,!Z||0===a.val().length&&angular.isDefined(i.placeholder)||a.val(m(p(a.val()))))}function o(){return l(i.uiMask)}function c(e){return Z?(j=p(e||""),R=g(j),r.$setValidity("mask",R),j.length&&(R||Q.allowInvalidValue)?m(j):void 0):e}function s(e){return Z?(j=p(e||""),R=g(j),r.$viewValue=j.length?m(j):"",r.$setValidity("mask",R),R||Q.allowInvalidValue?J?r.$viewValue:j:void 0):e}function f(){return Z=!1,v(),angular.isDefined(K)?a.attr("placeholder",K):a.removeAttr("placeholder"),angular.isDefined(W)?a.attr("maxlength",W):a.removeAttr("maxlength"),a.val(r.$modelValue),r.$viewValue=r.$modelValue,!1}function h(){j=F=p(r.$modelValue||""),H=_=m(j),R=g(j),i.maxlength&&a.attr("maxlength",2*A[A.length-1]),!K&&Q.addDefaultPlaceholder&&a.attr("placeholder",B);for(var e=r.$modelValue,n=r.$formatters.length;n--;)e=r.$formatters[n](e);r.$viewValue=e||"",r.$render()}function d(){q||(a.bind("blur",$),a.bind("mousedown mouseup",V),a.bind("keydown",M),a.bind(Q.eventsToHandle.join(" "),O),q=!0)}function v(){q&&(a.unbind("blur",$),a.unbind("mousedown",V),a.unbind("mouseup",V),a.unbind("keydown",M),a.unbind("input",O),a.unbind("keyup",O),a.unbind("click",O),a.unbind("focus",O),q=!1)}function g(e){return e.length?e.length>=T:!0}function p(e){var n,t,i="",r=a[0],l=S.slice(),u=N,o=u+C(r),c="";return e=e.toString(),n=0,t=e.length-B.length,angular.forEach(I,function(a){var i=a.position;i>=u&&o>i||(i>=u&&(i+=t),e.substring(i,i+a.value.length)===a.value&&(c+=e.slice(n,i),n=i+a.value.length))}),e=c+e.slice(n),angular.forEach(e.split(""),function(e){l.length&&l[0].test(e)&&(i+=e,l.shift())}),i}function m(e){var n="",t=A.slice();return angular.forEach(B.split(""),function(a,i){e.length&&i===t[0]?(n+=e.charAt(0)||"_",e=e.substr(1),t.shift()):n+=a}),n}function b(e){var n,t=angular.isDefined(i.uiMaskPlaceholder)?i.uiMaskPlaceholder:i.placeholder;return angular.isDefined(t)&&t[e]?t[e]:(n=angular.isDefined(i.uiMaskPlaceholderChar)&&i.uiMaskPlaceholderChar?i.uiMaskPlaceholderChar:"_","space"===n.toLowerCase()?" ":n[0])}function k(){var e,n,t=B.split("");A&&!isNaN(A[0])&&angular.forEach(A,function(e){t[e]="_"}),e=t.join(""),n=e.replace(/[_]+/g,"_").split("_"),n=n.filter(function(e){return""!==e});var a=0;return n.map(function(n){var t=e.indexOf(n,a);return a=t+1,{value:n,position:t}})}function w(e){var n=0;if(A=[],S=[],B="",angular.isString(e)){T=0;var t=!1,a=0,i=e.split(""),r=!1;angular.forEach(i,function(e,i){r?(r=!1,B+=e,n++):Q.escChar===e?r=!0:Q.maskDefinitions[e]?(A.push(n),B+=b(i-a),S.push(Q.maskDefinitions[e]),n++,t||T++,t=!1):"?"===e?(t=!0,a++):(B+=e,n++)})}A.push(A.slice().pop()+1),I=k(),Z=A.length>1?!0:!1}function $(){(Q.clearOnBlur||Q.clearOnBlurPlaceholder&&0===j.length&&i.placeholder)&&(N=0,z=0,R&&0!==j.length||(H="",a.val(""),e.$apply(function(){r.$pristine||r.$setViewValue("")}))),j!==U&&y(a[0]),U=j}function y(e){var n;angular.isFunction(window.Event)&&!e.fireEvent?(n=new Event("change",{view:window,bubbles:!0,cancelable:!1}),e.dispatchEvent(n)):"createEvent"in document?(n=document.createEvent("HTMLEvents"),n.initEvent("change",!1,!0),e.dispatchEvent(n)):e.fireEvent&&e.fireEvent("onchange")}function V(e){"mousedown"===e.type?a.bind("mouseout",E):a.unbind("mouseout",E)}function E(){z=C(this),a.unbind("mouseout",E)}function M(e){var n=8===e.which,t=D(this)-1||0;if(n){for(;t>=0;){if(x(t)){P(this,t+1);break}t--}L=-1===t}}function O(n){n=n||{};var t=n.which,i=n.type;if(16!==t&&91!==t){var l,u=a.val(),o=_,c=!1,s=p(u),f=F,h=D(this)||0,d=N||0,v=h-d,g=A[0],b=A[s.length]||A.slice().shift(),k=z||0,w=C(this)>0,$=k>0,y=u.length>o.length||k&&u.length>o.length-k,V=u.length<o.length||k&&u.length===o.length-k,E=t>=37&&40>=t&&n.shiftKey,M=37===t,O=8===t||"keyup"!==i&&V&&-1===v,S=46===t||"keyup"!==i&&V&&0===v&&!$,I=(M||O||"click"===i)&&h>g;if(z=C(this),!E&&(!w||"click"!==i&&"keyup"!==i&&"focus"!==i)){if(O&&L)return a.val(B),e.$apply(function(){r.$setViewValue("")}),void P(this,d);if("input"===i&&V&&!$&&s===f){for(;O&&h>g&&!x(h);)h--;for(;S&&b>h&&-1===A.indexOf(h);)h++;var T=A.indexOf(h);s=s.substring(0,T)+s.substring(T+1),s!==f&&(c=!0)}for(l=m(s),_=l,F=s,!c&&u.length>l.length&&(c=!0),a.val(l),c&&e.$apply(function(){r.$setViewValue(l)}),y&&g>=h&&(h=g+1),I&&h--,h=h>b?b:g>h?g:h;!x(h)&&h>g&&b>h;)h+=I?-1:1;(I&&b>h||y&&!x(d))&&h++,N=h,P(this,h)}}}function x(e){return A.indexOf(e)>-1}function D(e){if(!e)return 0;if(void 0!==e.selectionStart)return e.selectionStart;if(document.selection&&n(a[0])){e.focus();var t=document.selection.createRange();return t.moveStart("character",e.value?-e.value.length:0),t.text.length}return 0}function P(e,t){if(!e)return 0;if(0!==e.offsetWidth&&0!==e.offsetHeight)if(e.setSelectionRange)n(a[0])&&(e.focus(),e.setSelectionRange(t,t));else if(e.createTextRange){var i=e.createTextRange();i.collapse(!0),i.moveEnd("character",t),i.moveStart("character",t),i.select()}}function C(e){return e?void 0!==e.selectionStart?e.selectionEnd-e.selectionStart:document.selection?document.selection.createRange().text.length:0:0}var A,S,B,I,T,j,H,R,_,F,N,z,L,Z=!1,q=!1,K=i.placeholder,W=i.maxlength,G=r.$isEmpty;r.$isEmpty=function(e){return G(Z?p(e||""):e)};var J=!1;i.$observe("modelViewValue",function(e){"true"===e&&(J=!0)}),i.$observe("allowInvalidValue",function(e){Q.allowInvalidValue=""===e?!0:!!e,c(r.$modelValue)});var Q={};i.uiOptions?(Q=e.$eval("["+i.uiOptions+"]"),Q=angular.isObject(Q[0])?function(e,n){for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(void 0===n[t]?n[t]=angular.copy(e[t]):angular.isObject(n[t])&&!angular.isArray(n[t])&&(n[t]=angular.extend({},e[t],n[t])));return n}(t,Q[0]):t):Q=t,i.$observe("uiMask",l),angular.isDefined(i.uiMaskPlaceholder)?i.$observe("uiMaskPlaceholder",u):i.$observe("placeholder",u),angular.isDefined(i.uiMaskPlaceholderChar)&&i.$observe("uiMaskPlaceholderChar",o),r.$formatters.unshift(c),r.$parsers.unshift(s);var U=a.val();a.bind("mousedown mouseup",V),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){if(null===this)throw new TypeError;var n=Object(this),t=n.length>>>0;if(0===t)return-1;var a=0;if(arguments.length>1&&(a=Number(arguments[1]),a!==a?a=0:0!==a&&a!==1/0&&a!==-(1/0)&&(a=(a>0||-1)*Math.floor(Math.abs(a)))),a>=t)return-1;for(var i=a>=0?a:Math.max(t-Math.abs(a),0);t>i;i++)if(i in n&&n[i]===e)return i;return-1})}}}}])}();
define("uiMask", ["angular"], function(){});

../node_modules/@tvg/deposit/modules.js
/**
 * @license AngularJS v1.5.7
 * (c) 2010-2016 Google, Inc. http://angularjs.org
 * License: MIT
 */
PaypalDepositController.$inject = ['$routeParams', '$document', '$window', '$q', '$timeout', 'Utilities', 'NotificationService', 'paypalService', 'UserActionEventsService', 'ConfigurationFac', 'ApiDepositsGTMFac', '$scope', '$rootScope', '$log', 'DepositSrv'];
ApplePayDepositController.$inject = ['$routeParams', '$document', '$window', '$q', '$timeout', 'NotificationService', 'applepayService', 'ApiDepositsGTMFac', 'ApplePayFac', '$scope', '$rootScope'];
(function(window, angular) {'use strict';

/* jshint ignore:start */
// this code is in the core, but not in angular-messages.js
var isArray = angular.isArray;
var forEach = angular.forEach;
var isString = angular.isString;
var jqLite = angular.element;
/* jshint ignore:end */

/**
 * @ngdoc module
 * @name ngMessages
 * @description
 *
 * The `ngMessages` module provides enhanced support for displaying messages within templates
 * (typically within forms or when rendering message objects that return key/value data).
 * Instead of relying on JavaScript code and/or complex ng-if statements within your form template to
 * show and hide error messages specific to the state of an input field, the `ngMessages` and
 * `ngMessage` directives are designed to handle the complexity, inheritance and priority
 * sequencing based on the order of how the messages are defined in the template.
 *
 * Currently, the ngMessages module only contains the code for the `ngMessages`, `ngMessagesInclude`
 * `ngMessage` and `ngMessageExp` directives.
 *
 * # Usage
 * The `ngMessages` directive allows keys in a key/value collection to be associated with a child element
 * (or 'message') that will show or hide based on the truthiness of that key's value in the collection. A common use
 * case for `ngMessages` is to display error messages for inputs using the `$error` object exposed by the
 * {@link ngModel ngModel} directive.
 *
 * The child elements of the `ngMessages` directive are matched to the collection keys by a `ngMessage` or
 * `ngMessageExp` directive. The value of these attributes must match a key in the collection that is provided by
 * the `ngMessages` directive.
 *
 * Consider the following example, which illustrates a typical use case of `ngMessages`. Within the form `myForm` we
 * have a text input named `myField` which is bound to the scope variable `field` using the {@link ngModel ngModel}
 * directive.
 *
 * The `myField` field is a required input of type `email` with a maximum length of 15 characters.
 *
 * ```html
 * <form name="myForm">
 *   <label>
 *     Enter text:
 *     <input type="email" ng-model="field" name="myField" required maxlength="15" />
 *   </label>
 *   <div ng-messages="myForm.myField.$error" role="alert">
 *     <div ng-message="required">Please enter a value for this field.</div>
 *     <div ng-message="email">This field must be a valid email address.</div>
 *     <div ng-message="maxlength">This field can be at most 15 characters long.</div>
 *   </div>
 * </form>
 * ```
 *
 * In order to show error messages corresponding to `myField` we first create an element with an `ngMessages` attribute
 * set to the `$error` object owned by the `myField` input in our `myForm` form.
 *
 * Within this element we then create separate elements for each of the possible errors that `myField` could have.
 * The `ngMessage` attribute is used to declare which element(s) will appear for which error - for example,
 * setting `ng-message="required"` specifies that this particular element should be displayed when there
 * is no value present for the required field `myField` (because the key `required` will be `true` in the object
 * `myForm.myField.$error`).
 *
 * ### Message order
 *
 * By default, `ngMessages` will only display one message for a particular key/value collection at any time. If more
 * than one message (or error) key is currently true, then which message is shown is determined by the order of messages
 * in the HTML template code (messages declared first are prioritised). This mechanism means the developer does not have
 * to prioritise messages using custom JavaScript code.
 *
 * Given the following error object for our example (which informs us that the field `myField` currently has both the
 * `required` and `email` errors):
 *
 * ```javascript
 * <!-- keep in mind that ngModel automatically sets these error flags -->
 * myField.$error = { required : true, email: true, maxlength: false };
 * ```
 * The `required` message will be displayed to the user since it appears before the `email` message in the DOM.
 * Once the user types a single character, the `required` message will disappear (since the field now has a value)
 * but the `email` message will be visible because it is still applicable.
 *
 * ### Displaying multiple messages at the same time
 *
 * While `ngMessages` will by default only display one error element at a time, the `ng-messages-multiple` attribute can
 * be applied to the `ngMessages` container element to cause it to display all applicable error messages at once:
 *
 * ```html
 * <!-- attribute-style usage -->
 * <div ng-messages="myForm.myField.$error" ng-messages-multiple>...</div>
 *
 * <!-- element-style usage -->
 * <ng-messages for="myForm.myField.$error" multiple>...</ng-messages>
 * ```
 *
 * ## Reusing and Overriding Messages
 * In addition to prioritization, ngMessages also allows for including messages from a remote or an inline
 * template. This allows for generic collection of messages to be reused across multiple parts of an
 * application.
 *
 * ```html
 * <script type="text/ng-template" id="error-messages">
 *   <div ng-message="required">This field is required</div>
 *   <div ng-message="minlength">This field is too short</div>
 * </script>
 *
 * <div ng-messages="myForm.myField.$error" role="alert">
 *   <div ng-messages-include="error-messages"></div>
 * </div>
 * ```
 *
 * However, including generic messages may not be useful enough to match all input fields, therefore,
 * `ngMessages` provides the ability to override messages defined in the remote template by redefining
 * them within the directive container.
 *
 * ```html
 * <!-- a generic template of error messages known as "my-custom-messages" -->
 * <script type="text/ng-template" id="my-custom-messages">
 *   <div ng-message="required">This field is required</div>
 *   <div ng-message="minlength">This field is too short</div>
 * </script>
 *
 * <form name="myForm">
 *   <label>
 *     Email address
 *     <input type="email"
 *            id="email"
 *            name="myEmail"
 *            ng-model="email"
 *            minlength="5"
 *            required />
 *   </label>
 *   <!-- any ng-message elements that appear BEFORE the ng-messages-include will
 *        override the messages present in the ng-messages-include template -->
 *   <div ng-messages="myForm.myEmail.$error" role="alert">
 *     <!-- this required message has overridden the template message -->
 *     <div ng-message="required">You did not enter your email address</div>
 *
 *     <!-- this is a brand new message and will appear last in the prioritization -->
 *     <div ng-message="email">Your email address is invalid</div>
 *
 *     <!-- and here are the generic error messages -->
 *     <div ng-messages-include="my-custom-messages"></div>
 *   </div>
 * </form>
 * ```
 *
 * In the example HTML code above the message that is set on required will override the corresponding
 * required message defined within the remote template. Therefore, with particular input fields (such
 * email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
 * while more generic messages can be used to handle other, more general input errors.
 *
 * ## Dynamic Messaging
 * ngMessages also supports using expressions to dynamically change key values. Using arrays and
 * repeaters to list messages is also supported. This means that the code below will be able to
 * fully adapt itself and display the appropriate message when any of the expression data changes:
 *
 * ```html
 * <form name="myForm">
 *   <label>
 *     Email address
 *     <input type="email"
 *            name="myEmail"
 *            ng-model="email"
 *            minlength="5"
 *            required />
 *   </label>
 *   <div ng-messages="myForm.myEmail.$error" role="alert">
 *     <div ng-message="required">You did not enter your email address</div>
 *     <div ng-repeat="errorMessage in errorMessages">
 *       <!-- use ng-message-exp for a message whose key is given by an expression -->
 *       <div ng-message-exp="errorMessage.type">{{ errorMessage.text }}</div>
 *     </div>
 *   </div>
 * </form>
 * ```
 *
 * The `errorMessage.type` expression can be a string value or it can be an array so
 * that multiple errors can be associated with a single error message:
 *
 * ```html
 *   <label>
 *     Email address
 *     <input type="email"
 *            ng-model="data.email"
 *            name="myEmail"
 *            ng-minlength="5"
 *            ng-maxlength="100"
 *            required />
 *   </label>
 *   <div ng-messages="myForm.myEmail.$error" role="alert">
 *     <div ng-message-exp="'required'">You did not enter your email address</div>
 *     <div ng-message-exp="['minlength', 'maxlength']">
 *       Your email must be between 5 and 100 characters long
 *     </div>
 *   </div>
 * ```
 *
 * Feel free to use other structural directives such as ng-if and ng-switch to further control
 * what messages are active and when. Be careful, if you place ng-message on the same element
 * as these structural directives, Angular may not be able to determine if a message is active
 * or not. Therefore it is best to place the ng-message on a child element of the structural
 * directive.
 *
 * ```html
 * <div ng-messages="myForm.myEmail.$error" role="alert">
 *   <div ng-if="showRequiredError">
 *     <div ng-message="required">Please enter something</div>
 *   </div>
 * </div>
 * ```
 *
 * ## Animations
 * If the `ngAnimate` module is active within the application then the `ngMessages`, `ngMessage` and
 * `ngMessageExp` directives will trigger animations whenever any messages are added and removed from
 * the DOM by the `ngMessages` directive.
 *
 * Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
 * class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
 * messages present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
 * hook into the animations whenever these classes are added/removed.
 *
 * Let's say that our HTML code for our messages container looks like so:
 *
 * ```html
 * <div ng-messages="myMessages" class="my-messages" role="alert">
 *   <div ng-message="alert" class="some-message">...</div>
 *   <div ng-message="fail" class="some-message">...</div>
 * </div>
 * ```
 *
 * Then the CSS animation code for the message container looks like so:
 *
 * ```css
 * .my-messages {
 *   transition:1s linear all;
 * }
 * .my-messages.ng-active {
 *   // messages are visible
 * }
 * .my-messages.ng-inactive {
 *   // messages are hidden
 * }
 * ```
 *
 * Whenever an inner message is attached (becomes visible) or removed (becomes hidden) then the enter
 * and leave animation is triggered for each particular element bound to the `ngMessage` directive.
 *
 * Therefore, the CSS code for the inner messages looks like so:
 *
 * ```css
 * .some-message {
 *   transition:1s linear all;
 * }
 *
 * .some-message.ng-enter {}
 * .some-message.ng-enter.ng-enter-active {}
 *
 * .some-message.ng-leave {}
 * .some-message.ng-leave.ng-leave-active {}
 * ```
 *
 * {@link ngAnimate Click here} to learn how to use JavaScript animations or to learn more about ngAnimate.
 */
angular.module('ngMessages', [])

  /**
   * @ngdoc directive
   * @module ngMessages
   * @name ngMessages
   * @restrict AE
   *
   * @description
   * `ngMessages` is a directive that is designed to show and hide messages based on the state
   * of a key/value object that it listens on. The directive itself complements error message
   * reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
   *
   * `ngMessages` manages the state of internal messages within its container element. The internal
   * messages use the `ngMessage` directive and will be inserted/removed from the page depending
   * on if they're present within the key/value object. By default, only one message will be displayed
   * at a time and this depends on the prioritization of the messages within the template. (This can
   * be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.)
   *
   * A remote template can also be used to promote message reusability and messages can also be
   * overridden.
   *
   * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
   *
   * @usage
   * ```html
   * <!-- using attribute directives -->
   * <ANY ng-messages="expression" role="alert">
   *   <ANY ng-message="stringValue">...</ANY>
   *   <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
   *   <ANY ng-message-exp="expressionValue">...</ANY>
   * </ANY>
   *
   * <!-- or by using element directives -->
   * <ng-messages for="expression" role="alert">
   *   <ng-message when="stringValue">...</ng-message>
   *   <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
   *   <ng-message when-exp="expressionValue">...</ng-message>
   * </ng-messages>
   * ```
   *
   * @param {string} ngMessages an angular expression evaluating to a key/value object
   *                 (this is typically the $error object on an ngModel instance).
   * @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
   *
   * @example
   * <example name="ngMessages-directive" module="ngMessagesExample"
   *          deps="angular-messages.js"
   *          animations="true" fixBase="true">
   *   <file name="index.html">
   *     <form name="myForm">
   *       <label>
   *         Enter your name:
   *         <input type="text"
   *                name="myName"
   *                ng-model="name"
   *                ng-minlength="5"
   *                ng-maxlength="20"
   *                required />
   *       </label>
   *       <pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
   *
   *       <div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
   *         <div ng-message="required">You did not enter a field</div>
   *         <div ng-message="minlength">Your field is too short</div>
   *         <div ng-message="maxlength">Your field is too long</div>
   *       </div>
   *     </form>
   *   </file>
   *   <file name="script.js">
   *     angular.module('ngMessagesExample', ['ngMessages']);
   *   </file>
   * </example>
   */
  .directive('ngMessages', ['$animate', function($animate) {
    var ACTIVE_CLASS = 'ng-active';
    var INACTIVE_CLASS = 'ng-inactive';

    return {
      require: 'ngMessages',
      restrict: 'AE',
      controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
        var ctrl = this;
        var latestKey = 0;
        var nextAttachId = 0;

        this.getAttachId = function getAttachId() { return nextAttachId++; };

        var messages = this.messages = {};
        var renderLater, cachedCollection;

        this.render = function(collection) {
          collection = collection || {};

          renderLater = false;
          cachedCollection = collection;

          // this is true if the attribute is empty or if the attribute value is truthy
          var multiple = isAttrTruthy($scope, $attrs.ngMessagesMultiple) ||
                         isAttrTruthy($scope, $attrs.multiple);

          var unmatchedMessages = [];
          var matchedKeys = {};
          var messageItem = ctrl.head;
          var messageFound = false;
          var totalMessages = 0;

          // we use != instead of !== to allow for both undefined and null values
          while (messageItem != null) {
            totalMessages++;
            var messageCtrl = messageItem.message;

            var messageUsed = false;
            if (!messageFound) {
              forEach(collection, function(value, key) {
                if (!messageUsed && truthy(value) && messageCtrl.test(key)) {
                  // this is to prevent the same error name from showing up twice
                  if (matchedKeys[key]) return;
                  matchedKeys[key] = true;

                  messageUsed = true;
                  messageCtrl.attach();
                }
              });
            }

            if (messageUsed) {
              // unless we want to display multiple messages then we should
              // set a flag here to avoid displaying the next message in the list
              messageFound = !multiple;
            } else {
              unmatchedMessages.push(messageCtrl);
            }

            messageItem = messageItem.next;
          }

          forEach(unmatchedMessages, function(messageCtrl) {
            messageCtrl.detach();
          });

          unmatchedMessages.length !== totalMessages
              ? $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS)
              : $animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS);
        };

        $scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render);

        // If the element is destroyed, proactively destroy all the currently visible messages
        $element.on('$destroy', function() {
          forEach(messages, function(item) {
            item.message.detach();
          });
        });

        this.reRender = function() {
          if (!renderLater) {
            renderLater = true;
            $scope.$evalAsync(function() {
              if (renderLater) {
                cachedCollection && ctrl.render(cachedCollection);
              }
            });
          }
        };

        this.register = function(comment, messageCtrl) {
          var nextKey = latestKey.toString();
          messages[nextKey] = {
            message: messageCtrl
          };
          insertMessageNode($element[0], comment, nextKey);
          comment.$$ngMessageNode = nextKey;
          latestKey++;

          ctrl.reRender();
        };

        this.deregister = function(comment) {
          var key = comment.$$ngMessageNode;
          delete comment.$$ngMessageNode;
          removeMessageNode($element[0], comment, key);
          delete messages[key];
          ctrl.reRender();
        };

        function findPreviousMessage(parent, comment) {
          var prevNode = comment;
          var parentLookup = [];

          while (prevNode && prevNode !== parent) {
            var prevKey = prevNode.$$ngMessageNode;
            if (prevKey && prevKey.length) {
              return messages[prevKey];
            }

            // dive deeper into the DOM and examine its children for any ngMessage
            // comments that may be in an element that appears deeper in the list
            if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) === -1) {
              parentLookup.push(prevNode);
              prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
            } else if (prevNode.previousSibling) {
              prevNode = prevNode.previousSibling;
            } else {
              prevNode = prevNode.parentNode;
              parentLookup.push(prevNode);
            }
          }
        }

        function insertMessageNode(parent, comment, key) {
          var messageNode = messages[key];
          if (!ctrl.head) {
            ctrl.head = messageNode;
          } else {
            var match = findPreviousMessage(parent, comment);
            if (match) {
              messageNode.next = match.next;
              match.next = messageNode;
            } else {
              messageNode.next = ctrl.head;
              ctrl.head = messageNode;
            }
          }
        }

        function removeMessageNode(parent, comment, key) {
          var messageNode = messages[key];

          var match = findPreviousMessage(parent, comment);
          if (match) {
            match.next = messageNode.next;
          } else {
            ctrl.head = messageNode.next;
          }
        }
      }]
    };

    function isAttrTruthy(scope, attr) {
     return (isString(attr) && attr.length === 0) || //empty attribute
            truthy(scope.$eval(attr));
    }

    function truthy(val) {
      return isString(val) ? val.length : !!val;
    }
  }])

  /**
   * @ngdoc directive
   * @name ngMessagesInclude
   * @restrict AE
   * @scope
   *
   * @description
   * `ngMessagesInclude` is a directive with the purpose to import existing ngMessage template
   * code from a remote template and place the downloaded template code into the exact spot
   * that the ngMessagesInclude directive is placed within the ngMessages container. This allows
   * for a series of pre-defined messages to be reused and also allows for the developer to
   * determine what messages are overridden due to the placement of the ngMessagesInclude directive.
   *
   * @usage
   * ```html
   * <!-- using attribute directives -->
   * <ANY ng-messages="expression" role="alert">
   *   <ANY ng-messages-include="remoteTplString">...</ANY>
   * </ANY>
   *
   * <!-- or by using element directives -->
   * <ng-messages for="expression" role="alert">
   *   <ng-messages-include src="expressionValue1">...</ng-messages-include>
   * </ng-messages>
   * ```
   *
   * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
   *
   * @param {string} ngMessagesInclude|src a string value corresponding to the remote template.
   */
  .directive('ngMessagesInclude',
    ['$templateRequest', '$document', '$compile', function($templateRequest, $document, $compile) {

    return {
      restrict: 'AE',
      require: '^^ngMessages', // we only require this for validation sake
      link: function($scope, element, attrs) {
        var src = attrs.ngMessagesInclude || attrs.src;
        $templateRequest(src).then(function(html) {
          if ($scope.$$destroyed) return;

          if (isString(html) && !html.trim()) {
            // Empty template - nothing to compile
            replaceElementWithMarker(element, src);
          } else {
            // Non-empty template - compile and link
            $compile(html)($scope, function(contents) {
              element.after(contents);
              replaceElementWithMarker(element, src);
            });
          }
        });
      }
    };

    // Helpers
    function replaceElementWithMarker(element, src) {
      // A comment marker is placed for debugging purposes
      var comment = $compile.$$createComment ?
          $compile.$$createComment('ngMessagesInclude', src) :
          $document[0].createComment(' ngMessagesInclude: ' + src + ' ');
      var marker = jqLite(comment);
      element.after(marker);

      // Don't pollute the DOM anymore by keeping an empty directive element
      element.remove();
    }
  }])

  /**
   * @ngdoc directive
   * @name ngMessage
   * @restrict AE
   * @scope
   *
   * @description
   * `ngMessage` is a directive with the purpose to show and hide a particular message.
   * For `ngMessage` to operate, a parent `ngMessages` directive on a parent DOM element
   * must be situated since it determines which messages are visible based on the state
   * of the provided key/value map that `ngMessages` listens on.
   *
   * More information about using `ngMessage` can be found in the
   * {@link module:ngMessages `ngMessages` module documentation}.
   *
   * @usage
   * ```html
   * <!-- using attribute directives -->
   * <ANY ng-messages="expression" role="alert">
   *   <ANY ng-message="stringValue">...</ANY>
   *   <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
   * </ANY>
   *
   * <!-- or by using element directives -->
   * <ng-messages for="expression" role="alert">
   *   <ng-message when="stringValue">...</ng-message>
   *   <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
   * </ng-messages>
   * ```
   *
   * @param {expression} ngMessage|when a string value corresponding to the message key.
   */
  .directive('ngMessage', ngMessageDirectiveFactory())


  /**
   * @ngdoc directive
   * @name ngMessageExp
   * @restrict AE
   * @priority 1
   * @scope
   *
   * @description
   * `ngMessageExp` is a directive with the purpose to show and hide a particular message.
   * For `ngMessageExp` to operate, a parent `ngMessages` directive on a parent DOM element
   * must be situated since it determines which messages are visible based on the state
   * of the provided key/value map that `ngMessages` listens on.
   *
   * @usage
   * ```html
   * <!-- using attribute directives -->
   * <ANY ng-messages="expression">
   *   <ANY ng-message-exp="expressionValue">...</ANY>
   * </ANY>
   *
   * <!-- or by using element directives -->
   * <ng-messages for="expression">
   *   <ng-message when-exp="expressionValue">...</ng-message>
   * </ng-messages>
   * ```
   *
   * {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
   *
   * @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key.
   */
  .directive('ngMessageExp', ngMessageDirectiveFactory());

function ngMessageDirectiveFactory() {
  return ['$animate', function($animate) {
    return {
      restrict: 'AE',
      transclude: 'element',
      priority: 1, // must run before ngBind, otherwise the text is set on the comment
      terminal: true,
      require: '^^ngMessages',
      link: function(scope, element, attrs, ngMessagesCtrl, $transclude) {
        var commentNode = element[0];

        var records;
        var staticExp = attrs.ngMessage || attrs.when;
        var dynamicExp = attrs.ngMessageExp || attrs.whenExp;
        var assignRecords = function(items) {
          records = items
              ? (isArray(items)
                  ? items
                  : items.split(/[\s,]+/))
              : null;
          ngMessagesCtrl.reRender();
        };

        if (dynamicExp) {
          assignRecords(scope.$eval(dynamicExp));
          scope.$watchCollection(dynamicExp, assignRecords);
        } else {
          assignRecords(staticExp);
        }

        var currentElement, messageCtrl;
        ngMessagesCtrl.register(commentNode, messageCtrl = {
          test: function(name) {
            return contains(records, name);
          },
          attach: function() {
            if (!currentElement) {
              $transclude(function(elm, newScope) {
                $animate.enter(elm, null, element);
                currentElement = elm;

                // Each time we attach this node to a message we get a new id that we can match
                // when we are destroying the node later.
                var $$attachId = currentElement.$$attachId = ngMessagesCtrl.getAttachId();

                // in the event that the element or a parent element is destroyed
                // by another structural directive then it's time
                // to deregister the message from the controller
                currentElement.on('$destroy', function() {
                  if (currentElement && currentElement.$$attachId === $$attachId) {
                    ngMessagesCtrl.deregister(commentNode);
                    messageCtrl.detach();
                  }
                  newScope.$destroy();
                });
              });
            }
          },
          detach: function() {
            if (currentElement) {
              var elm = currentElement;
              currentElement = null;
              $animate.leave(elm);
            }
          }
        });
      }
    };
  }];

  function contains(collection, key) {
    if (collection) {
      return isArray(collection)
          ? collection.indexOf(key) >= 0
          : collection.hasOwnProperty(key);
    }
  }
}


})(window, window.angular);

angular.module('TVG.Paypal.Common', ['ngMessages', 'TVG.DMA.Common', 'TVG.Configuration']);

angular.module('TVG.Paypal.Deposits', [
  'TVG.Paypal.Common',
  'UserActionEvents'
]);

angular.module('TVG.Paypal.Withdrawals', ['TVG.Paypal.Common']);

/*
 * The Official Acronym is 'PAY'
 * Min Deposit is:
 * Max Deposit is:
 * There are fees, these are provided by the backend
 * On the CMS the tabs are defined in:
   * deposit Config Available Options
   * DepositWidthrawAvailableOptions
 * All CSS should be placed in the closest position from its direction
 * It should follow the component structure where files are coupled according to features.
 */


/**
 * Screens
 *
 *  - Input Amount
 *  - Paypal Login + Paypal Confirmation
 *  - Confirmation and Pay
 *  - Input Amount (with feedback)
 *
 */
angular.module('TVG.Paypal', [
  'TVG.Paypal.Common',
  'TVG.Paypal.Deposits',
  'TVG.Paypal.Withdrawals'
]);

/* eslint angular/no-service-method: 0 */
(function () {
  'use strict';
  PaypalService.$inject = ['ConfigurationFac', 'Utilities', '$q', '$http', '$filter', '$location', '$log', 'DepositPath', '$window', '$rootScope'];
  function PaypalService(
    ConfigurationFac,
    Utilities,
    $q,
    $http,
    $filter,
    $location,
    $log,
    DepositPath,
    $window,
    $rootScope
  ) {
    var self = this;

    /* endpoint
     * Give the endpoint resources, build the final URI.
     * @param {string} ...resources One or more resources
     * @return {string} URI
     */
    var endpoint = function (base, service, version) {
      version = version || 'v1';
      return function (/* resources */) {
        var separator = '/';
        var resources = [].slice.call(arguments, 0);
        return [base, service, version].concat(resources).join(separator);
      };
    };

    var paypalEndpoint = endpoint(ConfigurationFac.getBaseServiceUrl(), 'pay');
    var walletEndpoint = endpoint(ConfigurationFac.getBaseServiceUrl(), 'uwt');

    var checkError = function (response) {
      return $q(function (resolve, reject) {
        return reject(self.createApiError([{
          message: _.get(response, 'data.message'),
          code: response.status,
          data: response.data
        }]));
      });
    };

    /**
     * Create an API error instance
     * Try to fetch an error message from the CMS (using the error code)
     * If none is found, use the error.message as a fallback
     *
     * @param  {Array} errors [description]
     * @return {Error}     [description]
     */
    self.createApiError = function (data) {
      var apiError = new Error();
      var error = data[0] || {};
      var paypalError = self.getFromCMS(error.code);

      apiError.message = paypalError || error.message;
      apiError.code = error.code;
      apiError.data = error.data || {};
      return apiError;
    };

    /**
     * request
     * @param  {Object} data
     * @param  {string} data.url
     * @param  {string} data.method
     * @param  {Object} data.data
     *
     * @return {Promise}
     */
    self.request = function (params) {
      var defaults = {
        headers: self.addHeaders(),
        method: 'POST'
      };

      return $http(_.extend({}, defaults, params))
        .catch(function (err) {
          return checkError(err);
        })
        .then(function (response) {
          response.data = _.assign({}, response.data, { statusCode: response.status });
          return response;
        })
        .then(Utilities.prop('data'));
    };

    self.createDepositRequest = function (depositInfo) {
      return new DepositRequest(depositInfo);
    };

    self.getAccountInfo = function (accountNumber) {
      var path = 'users/' + accountNumber + '/account-info';

      return self.request({
        url: paypalEndpoint(path),
        method: 'GET'
      });
    };

    /**
     * Retrieve an authorization token for the given payment
     * @return {String} Authorization token
     */
    self.getToken = function (depositInfo, accountNumber) {
      var path = 'users/' + accountNumber + '/token';

      return self.request({
        url: paypalEndpoint(path),
        data: self.createDepositRequest(depositInfo)
      })
      .then(Utilities.prop('token'));
    };

    /**
     * Add the headers needed to perform API calls
     *
     * @return {object}: Header Object
     */
    self.addHeaders = function (options) {
      var headers = {
        'x-tvgcontext': angular.toJson(ConfigurationFac.getApplicationContext())
      };

      if (Utilities.prop('cache', options)) {
        headers = _.extend({}, {
          'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
          'Cache-Control': 'no-cache',
          Pragma: 'no-cache'
        }, headers);
      }
      return headers;
    };

    /**
     * Get labels from CMS
     * @param  {[string]} name [label Name]
     * @return {[string]}      [label]
     */
    self.getFromCMS = function (name) {
      return $filter('CMSLabels')(name, 'paypalLabels');
    };

    self.getMessage = function (key, namespace) {
      return $filter('CMSLabels')(key, namespace);
    };

    self.getBaseUrl = function (replaceState) {
      var product = ConfigurationFac.getApplicationContextItem('product');
      var location = ConfigurationFac.getApplicationContextItem('location');
      var callback = $location.search().callback && decodeURIComponent($location.search().callback);
      var path = (!replaceState && !$rootScope.fullPage && DepositPath[product])
        || $window.location.pathname;

      var qs = {
        njx: '?location=nj&product=njx',
        ios: '?product=ios&location=' + location,
        ios2: '?product=ios2&location=' + location + '&callback=' + callback,
        touch3:
          '?product=touch3&location=' + location + '&callback=' + callback,
        fdrmobile:
          '?product=fdrmobile&location=' + location + '&callback=' + callback,
        fdrios:
          '?product=fdrios&location=' + location + '&callback=' + callback,
        fdrandroid:
          '?product=fdrandroid&location=' + location + '&callback=' + callback,
        iosnative:
          '?product=iosnative&location=' + location + '&callback=' + callback,
        androidnative:
          '?product=androidnative&location=' + location + '&callback=' + callback,
        androidwrapper:
          '?product=androidwrapper&location=' + location + '&callback=' + callback,
        tvgandroid:
          '?product=tvgandroid&location=' + location + '&callback=' + callback
      };

      var finalUrl;

      if ($rootScope.fullPage && path.indexOf('/registration') > -1) {
        path = path.replace('/registration', '/deposit/deposit');
      }

      finalUrl = Utilities.supplant('{protocol}://{host}{port}{path}', {
        protocol: $location.protocol(),
        host: !replaceState && callback ? callback.split('/')[0] : $location.host(),
        port: !replaceState && callback ? '' : ':' + $location.port(),
        path: (replaceState && _.has(qs, product)) ? path.concat(qs[product]) : path
      });

      $log.info(finalUrl);

      return finalUrl;
    };

    function DepositRequest(depositInfo) {
      var originTab = depositInfo.originTab || 'Deposit';
      var callback = $location.search().callback && encodeURIComponent($location.search().callback);
      var deviceQuery = $location.search().device && '&device=' + $location.search().device;
      var tab = Utilities.returnToTab('paypal+' + originTab, $rootScope.fullPage ?
        '&wrapper=true&fullPage=true' + deviceQuery + '&userCancelled=true&callback='
        + callback : '&userCancelled=true');
      var payConfirm = Utilities.returnToTab('paypal+' + originTab, $rootScope.fullPage ?
        '&wrapper=true&fullPage=true' + deviceQuery + '&isPaymentConfirmation=true&callback='
        + callback : '&isPaymentConfirmation=true');

      this.returnUrl = depositInfo.returnUrl.concat(payConfirm);
      this.cancelUrl = depositInfo.cancelUrl.concat(tab);
      this.orderAmount = depositInfo.orderAmount;
    }

    /**
     * Get all pending deposits
     * @return {[promise]}
     */
    self.getPendingDeposits = function () {
      return self.request({
        url: paypalEndpoint('deposit/list'),
        method: 'GET'
      })
      .then(Utilities.prop('deposits'));
    };

    /**
     * Deposit money from Paypal to TVG
     *
     * @return {[type]}      [description]
     */
    self.deposit = function (data, accountNumber) {
      var path = 'users/' + accountNumber + '/deposits/' + data.token;

      var requestData = { url: paypalEndpoint(path) };

      return self.request(requestData)
        .then(function (deposit) {
          return deposit;
        });
    };

    self.getDepositStatus = function (accountNumber, depositUUID) {
      return self.request({
        url: walletEndpoint('users/' + accountNumber + '/deposits/' + depositUUID + '/status'),
        method: 'GET'
      });
    };

    /**
     * Withdraw money from TVG to Paypal
     *
     * @return {Promise}      [description]
     */
    self.withdraw = function (amount, accountNumber) {
      var postData = {
        amount: amount
      };

      return self.request({
        url: paypalEndpoint('users/' + accountNumber + '/withdrawals'),
        method: 'POST',
        data: postData
      });
    };

    /**
     * getPaymentDetails
     * @param  {String} token
     * @return {Promise<PaymentDetails, Error>}
     */
    self.getPaymentDetails = function (token) {
      return self.request({
        url: paypalEndpoint('expressCheckout', token),
        method: 'GET'
      })
      .then(function (details) {
        var responseDetails = details.getExpressCheckoutDetailsResponseDetails;
        var orderTotal = responseDetails.paymentDetails[0].orderTotal.value;
        var amount = parseFloat(orderTotal);
        var fee = responseDetails.custom || '';
        var email = responseDetails.payerInfo.payer;
        self.LastFee = parseFloat(Utilities.parseQueryString(fee).fee);
        return {
          email: email,
          fee: self.LastFee,
          token: token,
          orderAmount: (amount - self.LastFee),
          invoiceId: responseDetails.invoiceID
        };
      });
    };

    self.getDepositFee = function (amount, accountNumber) {
      var path = 'users/' + accountNumber + '/deposits/fee?amount=' + amount;

      var requestOptions = {
        url: paypalEndpoint(path),
        method: 'GET'
      };

      return self.request(requestOptions);
    };
  }

  angular
    .module('TVG.Paypal.Common')
    .service('paypalService', PaypalService);
}());

angular
  .module('TVG.Paypal.Deposits')
  .component('depositButton', {
    controller: 'depositButtonController',
    bindings: {
      onPaypalDeposit: '&',
      isDisabled: '<'
    },
    templateUrl: 'src/paypal/deposits/deposit-button/deposit-button.template.html'
  });

/* eslint angular/controller-as-vm: 0 */
(function () {
  'use strict';

  function DepositButtonController() {
    var self = this;

    self.onDeposit = function ($event) {
      self.onPaypalDeposit({ $event: $event });
    };
  }

  angular
    .module('TVG.Paypal.Deposits')
    .controller('depositButtonController', DepositButtonController);
}());

angular
  .module('TVG.Paypal.Deposits')
  .component('paypalDeposit', {
    templateUrl: 'src/paypal/deposits/deposit.template.html',
    controller: 'paypalDepositController',
    bindings: {
      minAmount: '<',
      maxAmount: '<',
      amountOptions: '<',
      depositAmount: '<',
      isPaymentConfirmation: '<',
      userCancelled: '<',
      onAmountChange: '&',
      onPaymentComplete: '&'
    }
  });

/* eslint angular/controller-as-vm: "off" */

/**
 * This controllers' use case is mostly to know when to load
 * each screen and which properties it should pass to each component
 */
function PaypalDepositController(
  $routeParams,
  $document,
  $window,
  $q,
  $timeout,
  Utilities,
  NotificationService,
  paypalService,
  UserActionEventsService,
  ConfigurationFac,
  ApiDepositsGTMFac,
  $scope,
  $rootScope,
  $log,
  DepositSrv
) {
  var SUCCESS_MODAL_LABELS = {
    title: 'Successful Deposit!',
    textTemplate: 'Your $@@@deposit_amount@@@ are now available!',
    buttonText: 'Let\'s bet!'
  };


  var successModalOnOpenCallback = function () {
    ApiDepositsGTMFac.sendGTMEvent('siteClick', {
      event: 'siteClick',
      gaEventCategory: 'Site click',
      gaEventAction: 'seen',
      gaEventLabel: undefined,
      module: 'deposit success modal',
      tag: undefined,
      microApp: undefined
    });
  };

  var successModalButtonCallback = function () {
    ApiDepositsGTMFac.sendGTMEvent('navigation', {
      event: 'navigation',
      gaEventCategory: 'Navigation',
      gaEventAction: 'Navigated To',
      gaEventLabel: SUCCESS_MODAL_LABELS.buttonText,
      module: 'deposit success modal',
      tag: undefined,
      menu: undefined,
      sport: 'Horse Racing',
      destinationUrl: 'https://www.tvg.com/'
    });

    if ($window && $window.handleNativeMessages) {
      $window.handleNativeMessages('CLOSE_DMA');
    }
  };


  var successModalCloseCallback = function () {
    ApiDepositsGTMFac.sendGTMEvent('siteClick', {
      event: 'siteClick',
      gaEventCategory: 'Site click',
      gaEventAction: 'close',
      gaEventLabel: undefined,
      module: 'deposit success modal',
      tag: undefined,
      microApp: undefined
    });
  };

  var self = this;

  self.loading = true;
  self.fees = { loading: false, isFeePaid: $window.localStorage.getItem('isFeePaid') === 'true' };
  self.accountNumber = _.get($scope, '$parent.accountDetails.accountDetails.accountNumber', '') ||
    ($rootScope.user && $rootScope.user.accountNumber);
  self.feeRequestFailed = false;

  self.$onInit = function () {
    var token = $routeParams.token;
    var messageStatusMap = {
      200: {
        type: 'success',
        namespace: 'payDepositMessages',
        key: 'scenario5'
      },
      202: {
        type: 'warning',
        namespace: 'payDepositMessages',
        key: 'scenario3b'
      },
      207: {
        type: 'warning',
        namespace: 'payDepositMessages',
        key: 'scenario3a'
      }
    };

    var getMessageForStatus = function (statusCode) {
      return messageStatusMap[statusCode] || {
        type: 'error',
        key: 'scenario1',
        namespace: 'payDepositMessages'
      };
    };

    if (self.isPaymentConfirmation) {
      UserActionEventsService.emit('paypalSubmitDeposit');

      return paypalService.deposit({ token: token }, self.accountNumber)
        .then(function (response) {
          var messageForCode = getMessageForStatus(response.statusCode);
          var fromOption = _.get($scope, '$parent.fromOption.tla', '');

          if ($rootScope.activeFeatures.isDMAInjectDepositSuccessModalEnabled) {
            if ($window.ReactInjector) {
              $window.ReactInjector.renderDepositSuccess(
                    document.getElementById('injected-modal'),// eslint-disable-line
                {
                  title: SUCCESS_MODAL_LABELS.title,
                  text: SUCCESS_MODAL_LABELS.textTemplate.replace(
                    '@@@deposit_amount@@@',
                    response && response.amount),
                  buttonText: SUCCESS_MODAL_LABELS.buttonText,
                  sharedState: { isOpen: true },
                  buttonCallback: successModalButtonCallback,
                  closeCallback: successModalCloseCallback,
                  onOpenCallback: successModalOnOpenCallback
                }
              );
            }
          }

          UserActionEventsService.emit('depositSuccessPayPal', {
            amount: undefined,
            fee: undefined,
            defaultAmount: undefined,
            isFeePaid: self.fees.isFeePaid
          });

          switch (response.statusCode) {
            case 202:
              NotificationService[messageForCode.type](
                null,
                paypalService.getMessage(
                  messageForCode.key,
                  messageForCode.namespace
                )
              );

              // deposit in progress, start back off request on deposit status
              Utilities.backOff(function (next, stop) {
                paypalService
                  .getDepositStatus(self.accountNumber, response.transactionUUID)
                  .then(function (res) {
                    if (res.status === 'FINISH_DEPOSIT_SUCCESS' ||
                      $window.FINISH_DEPOSIT_SUCCESS) {
                      // deposit is finished, show success message
                      stop(messageStatusMap[200]);
                    } else if (res.status === 'FINISH_DEPOSIT_ERROR' ||
                      $window.FINISH_DEPOSIT_ERROR) {
                      // deposit error, show warning message
                      stop(messageStatusMap[207]);
                    } else {
                      // continue to try
                      next();
                    }
                  });
              }, 10000)
                .then(function (msg) {
                  // the backOff ended, show the message
                  NotificationService[msg.type](
                    null,
                    paypalService.getMessage(msg.key, msg.namespace)
                  );
                })
                .catch(function () {
                  //eslint-disable-next-line
                  console.log($scope,$rootScope, self);
                  // timeout on the backOff, show error
                  NotificationService.warning(
                    null,
                    paypalService.getMessage('scenario3c', 'payDepositMessages')
                  );
                })
                .finally(function () {
                  delete $window.FINISH_DEPOSIT_ERROR;
                  delete $window.FINISH_DEPOSIT_SUCCESS;
                });
              break;
            case 207:
              if (response[1] &&
                _.get(response[1], 'body.exception') === 'PAY_TOTE_DEPOSIT_FAILED') {
                // tote error, show warning
                NotificationService.warning(null,
                  paypalService.getMessage(
                    messageStatusMap[207].key,
                    messageStatusMap[207].namespace
                  )
                );
              }
              break;
            default:
              // any other case, fetch the message for the status code from the code map and display it
              // (the code will end up here almost every time for success case)
              if ($rootScope.activeFeatures &&
                $rootScope.activeFeatures.showDepositSuccessModal &&
                fromOption !== 'registration' &&
                response.statusCode === 200) {
                $timeout(function () {
                  DepositSrv.getSuccessDepositModal(false);
                }, 100);
              } else {
                NotificationService[messageForCode.type](
                  null,
                  paypalService.getMessage(
                    messageForCode.key,
                    messageForCode.namespace
                  )
                );
              }
          }

          if (response.balance) {
            $rootScope.$emit('accountBalance_changed', parseFloat(response.balance));
          }
        })
        .then(self.notifyOnPaymentComplete)
        .catch(function (err) {
          var errorMessage =
            paypalService.getMessage(err.data.exception, 'payDepositExceptions') ||
            paypalService.getMessage('generic', 'payDepositExceptions');

          UserActionEventsService.emit('depositErrorPayPal', {
            amount: undefined,
            fee: undefined,
            message: errorMessage
          });

          // big error trying to make the deposit, show exception message
          NotificationService.error(
            null,
            errorMessage
          );
        })
        .finally(function () {
          self.resetURL();
          self.getEmail();
        });
    }

    if (self.userCancelled) {
      UserActionEventsService.emit('paypalCancelDeposit');
      self.resetURL();
      self.getEmail();
    } else {
      self.getEmail();
    }
  };

  self.$postLink = function () {
    if (self.depositAmount) {
      self.paypalDeposits.$setSubmitted();
      if (self.depositAmount >= self.minAmount &&
          self.depositAmount <= self.maxAmount) {
        self.fetchFees(self.depositAmount);
      }
    }
  };

  // Event Handlers
  self.handleOnAmountChange = function ($event) {
    self.fees = {};
    self.depositAmount = $event.amount;
    self.fetchFees($event.amount);
    self.onAmountChange({ $event: $event.amount });
  };

  self.notifyOnPaymentComplete = function () {
    if (self.onPaymentComplete) {
      self.onPaymentComplete({ $event: {} });
    }
  };

  self.handlePaymentConfirmationFailure = function (error) {
    UserActionEventsService.emit('depositErrorPayPal', error);

    switch (error.message) {
      case 'BACKOFF_TIMEOUT':
        NotificationService.warning(
          null,
          paypalService.getFromCMS('processingTimeout')
        );
        break;
      case 'PAYMENT_FAILED':
        NotificationService.error(
          paypalService.getFromCMS('error'),
          paypalService.getFromCMS('processingError')
        );
        break;
      default:
        NotificationService.error(
          paypalService.getFromCMS('error'),
          (
            paypalService.getFromCMS(error.status || error.code) ||
            paypalService.getFromCMS('defaultError')
          )
        );
    }
  };

  // Public methods

  /**
   * [deposit description]
   * @param  {String} payerId
   * @param  {Object} options
   * @param  {String} options.token
   * @param  {Number} options.amount
   * @return {Promise<Any, Error>}
   */
  self.depositPayment = _.curry(function (payerId, options) {
    var data = angular.extend({}, { payerId: payerId }, options);

    return paypalService.deposit(data)
      .then(Utilities.tap(function (params) {
        UserActionEventsService.emit('depositSuccessPayPal', {
          amount: params.amount - params.fee,
          fee: params.fee,
          defaultAmount: self.amountOptions.indexOf(params.amount) !== -1
        });
      }));
  });


  /**
   * Get users email
   * @return {[type]} [description]
   */
  self.getEmail = function () {
    paypalService.getAccountInfo(
      self.accountNumber
    ).then(function (response) {
      if (response) {
        self.email = response.email;
      }
      self.loading = false;
    }).catch(function () {
      self.loading = false;
    });
  };

  /**
   * [waitForConfirmation description]
   * @param  {Object} options
   * @param  {Number} options.timeout
   * @param  {Number} options.depositId
   * @return {Promise}         [description]
   */
  self.waitForConfirmation = function (options) {
    var getDeposit = _.curry(function (depositId, pendingDeposits) {
      pendingDeposits = pendingDeposits || [];
      return pendingDeposits.filter(function (deposit) {
        return deposit.depositId === options.depositId;
      });
    });

    options = _.assign({}, options, { timeout: 20000 });

    return Utilities.backOff(function (next, stop) {
      return paypalService.getPendingDeposits()
        .then(getDeposit(options.depositId))
        .then(function (deposits) {
          if (!deposits.length) {
            stop(deposits);
          } else if (deposits[0].status === 'Failed') {
            stop(new Error('PAYMENT_FAILED'));
          } else {
            next();
          }
        })
        .catch(stop);
    }, options.timeout)
    .then(Utilities.tap(function () {
      NotificationService.success(
        paypalService.getFromCMS('success'),
        paypalService.getFromCMS('transactionSuccessful')
      );
    }));
  };

  self.fetchFees = function (amount) {
    self.fees.loading = true;

    // stop if no amount is inserted
    // (amount is undefined if the value is not valid)
    if (!amount) {
      return $q.reject(paypalService.getFromCMS('invalid'));
    }

    self.feeRequestFailed = false;
    NotificationService.clearBanner();

    return paypalService.getDepositFee(
      amount,
      self.accountNumber
    )
      .then(function (data) {
        var feeTotalAmount = parseFloat(data.feeTotalAmount || 0);
        var feeAmount = parseFloat(data.feeAmount || 0);
        var feeRefundAmount = parseFloat(data.feeRefundAmount || 0);

        var feeValues = {
          netAmount: amount,
          fee: feeTotalAmount,
          feeAmount: feeAmount,
          feeRefundAmount: feeRefundAmount,
          transactionTotal: amount + feeTotalAmount
        };

        self.fees = _.assign({}, self.fees, feeValues);
        return self.fees;
      })
      .then(Utilities.tap(function (fees) {
        $window.localStorage.setItem('isFeePaid', fees.feeAmount > 0);
        UserActionEventsService.emit('amountChange', {
          params: self.defaultParams,
          amount: amount,
          fee: fees.fee,
          feeAmount: fees.feeAmount,
          feeRefundAmount: fees.feeRefundAmount,
          defaultAmount: self.amountOptions.indexOf(amount) !== -1
        });
      }))
      .catch(function () {
        self.feeRequestFailed = true;

        NotificationService.error(
          paypalService.getFromCMS('error'),
          paypalService.getFromCMS('feesError')
        );
      })
      .finally(function () {
        self.fees.loading = false;
      });
  };
  /**
   * Reset all values from the form
   * @param {[boolean]} changeScreen [should the screen be changed ?]
   * @param {[boolean]} resetAmount  [should we reset the amount]
   */
  self.resetURL = function () {
    $log.info(paypalService.getBaseUrl(true));

    return $timeout(function () {
      var device = $rootScope.brazeDevice ||
      (new URLSearchParams($window.location.search)).get('device');

      $window.history.replaceState(null,
        $document.title,
        $rootScope.fullPage ? paypalService.getBaseUrl(true)
          + '&wrapper=true&device=' + device +
          '&fullPage=' + $rootScope.fullPage : paypalService.getBaseUrl(true)
      );
    }, 0);
  };

  self.shouldDisablePaypalButton = function () {
    var min = self.minAmount;
    var max = self.maxAmount;
    var amount = self.depositAmount || 0;
    var isCalculatingFees = !!self.fees.loading;

    return (isCalculatingFees || amount < min || amount > max || self.feeRequestFailed);
  };

  /**
   * Replace variable of CMS Messages
   * @param {[ApiError]} error
   * @return {[string]} CMSMessage
   */
  self.replaceVariableCMS = function (error, CMSMessage) {
    var limit;
    var floatRegex = new RegExp(/\d*\.\d*/g);
    var message = CMSMessage;
    var isRGLimitsExceededException = 119407;
    if (error.code === isRGLimitsExceededException) {
      limit = Number(error.message.match(floatRegex)[0]).toFixed(2);
      message = CMSMessage.replace('[limit]', limit);
    }
    return message;
  };

  /**
   * Makes the first call to the API so the user can login
   * and agree to pay in the paypal website
   * @return redirect
   */
  self.makePaypalDeposit = function (event) {
    var baseUrl = paypalService.getBaseUrl(false);
    var errorMessage = paypalService.getFromCMS('error');
    var requestData;

    requestData = {
      returnUrl: baseUrl,
      cancelUrl: baseUrl
    };

    if (event) { event.preventDefault(); }

    self.paypalDeposits.$submitted = true;
    self.disabled = true;

    UserActionEventsService.emit('depositAttemptPayPal', {
      amount: self.depositAmount,
      fee: self.fees.fee,
      defaultAmount: self.amountOptions.indexOf(self.depositAmount) !== -1
    });

    if (self.paypalDeposits.$valid && !self.feeRequestFailed) {
      requestData.orderAmount = self.depositAmount;

      self.loading = true;

      paypalService.getToken(requestData, self.accountNumber)
        .then(function (response) {
          UserActionEventsService.emit('paypalDepositRedirect', {
            amount: self.depositAmount,
            fee: self.fees.fee
          });

          return response;
        })
        .then(function (token) {
          var url = ConfigurationFac.getPaypal('baseURL') + '&token=' + token;
          if (ConfigurationFac.getApplicationContextItem('wrapper') &&
            !_.get($rootScope.activeFeatures, 'enableDepositOnSinglePage', false) &&
            !$window.location.pathname.match(/\/registration\/.*/g)) {
            $window.parent.postMessage({
              type: 'paypal_redirect',
              payload: url
            }, '*');
          } else {
            $window.location = url;
          }
        })
        .catch(function (error) {
          var message;
          self.loading = false;
          self.depositAmount = null;
          self.paypalDeposits.$setPristine();
          message = self.replaceVariableCMS(error.data,
               paypalService.getMessage(error.data.exception, 'payDepositExceptions')
            || paypalService.getMessage('generic', 'payDepositExceptions'));
          NotificationService.error(
            null,
            message
          );
        });
    } else {
      NotificationService.error(
        errorMessage,
        paypalService.getFromCMS('defaultError')
      );
    }

    $scope.$on('$destroy', function () {
      var eventHandlers = _.keys(UserActionEventsService.eventHandlers);
      eventHandlers.map(function (eventName) {
        return UserActionEventsService.off(eventName);
      });
    });
  };
}

angular
  .module('TVG.Paypal.Deposits')
  .controller('paypalDepositController', PaypalDepositController);

angular
  .module('TVG.Paypal.Deposits')
  .component('selectAmount', {
    controller: 'selectAmountController',
    bindings: {
      form: '=',
      amount: '<',
      amounts: '<',
      minAmount: '<',
      maxAmount: '<',
      onAmountChange: '&'
    },
    templateUrl: 'src/paypal/deposits/select-amount/select-amount.template.html'
  });

/* eslint angular/controller-as-vm: "off" */
(function () {
  'use strict';

  SelectAmountController.$inject = ['UserActionEventsService', '$timeout'];
  function SelectAmountController(UserActionEventsService, $timeout) {
    var self = this;

    self.change = function (amount) {
      if (self.form.$error) {
        $timeout(function () {
          UserActionEventsService.emit('payPalFill', self.form.$error);
        }, 200);
      }
      self.amount = amount;
      if (self.onAmountChange) {
        self.onAmountChange({ $event: { amount: amount } });
      }
    };
  }

  angular
    .module('TVG.Paypal.Deposits')
    .controller('selectAmountController', SelectAmountController);
}());

angular
  .module('TVG.Paypal.Deposits')
  .component('totalCost', {
    bindings: {
      data: '<',
      email: '<'
    },
    templateUrl: 'src/paypal/deposits/total-cost/total-cost.template.html'
  });

angular.module('TVG.MoneyPak',
  [
    'TVG.DMA.Common',
    'TVG.Configuration',
    'ui.mask',
    'UserActionEvents'
  ]);

 angular
  .module('TVG.MoneyPak')
  .component('moneypak', {
    controller: 'MoneyPakController',
    templateUrl: 'src/moneypak/moneypak.template.html'
  });

(function () {
  'use strict';

  MoneyPakController.$inject = ['ModalDialogService', 'MoneyPakService', 'NotificationService', 'UserActionEventsService', 'ApiDepositsGTMFac', '$window', '$rootScope', '$scope', '$filter', 'Utilities', 'DepositSrv', '$timeout'];
  function MoneyPakController(
    ModalDialogService,
    MoneyPakService,
    NotificationService,
    UserActionEventsService,
    ApiDepositsGTMFac,
    $window,
    $rootScope,
    $scope,
    $filter,
    Utilities,
    DepositSrv,
    $timeout
  ) {
    var vm = this;
    var modalTitle;
    var modalBody;

    var isNative = false;

    var mpakDepositMessagesMock = {
      scenario1: 'Oops, something went wrong.',
      scenario2: 'Oops, something went wrong',
      scenario3a:
        'Almost done, your deposit of {depositAmount} is taking a ' +
        'little longer to reach your TVG account than normal',
      scenario3b:
        'Success! Your deposit of {depositAmount} is being ' +
        'processed and your balance will update in a moment.',
      scenario3c:
        'Almost done, your deposit of {depositAmount} is taking ' +
        'a little longer to reach your TVG account than normal.',
      scenario4:
        'Almost done, your deposit of {depositAmount} is taking ' +
        'a little longer to reach your TVG account than normal.',
      scenario5:
        'Success! Your deposit of {depositAmount} is now available ' +
        'for wagering.'
    };

    var SUCCESS_MODAL_LABELS = {
      title: 'Successful Deposit!',
      textTemplate: 'Your $@@@deposit_amount@@@ are now available!',
      buttonText: 'Let\'s bet!'
    };

    var successModalOnOpenCallback = function () {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        event: 'siteClick',
        gaEventCategory: 'Site click',
        gaEventAction: 'seen',
        gaEventLabel: undefined,
        module: 'deposit success modal',
        tag: undefined,
        microApp: undefined
      });
    };

    var successModalButtonCallback = function () {
      ApiDepositsGTMFac.sendGTMEvent('navigation', {
        event: 'navigation',
        gaEventCategory: 'Navigation',
        gaEventAction: 'Navigated To',
        gaEventLabel: SUCCESS_MODAL_LABELS.buttonText,
        module: 'deposit success modal',
        tag: undefined,
        menu: undefined,
        sport: 'Horse Racing',
        destinationUrl: 'https://www.tvg.com/'
      });

      if ($window && $window.handleNativeMessages) {
        $window.handleNativeMessages('CLOSE_DMA');
      }
    };


    var successModalCloseCallback = function () {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        event: 'siteClick',
        gaEventCategory: 'Site click',
        gaEventAction: 'close',
        gaEventLabel: undefined,
        module: 'deposit success modal',
        tag: undefined,
        microApp: undefined
      });
    };

    if ($rootScope.product) {
      isNative = $rootScope.product.indexOf('native') !== -1;
    }

    function handleAction() {
      if (!vm.moneyPakDepositForm.$valid) {
        return false;
      }

      NotificationService.clearBanner();

      return true;
    }
    function getAccountId() {
      return (DepositSrv && DepositSrv.accountId) ||
        ($scope.$parent.accountDetails &&
          $scope.$parent.accountDetails.accountDetails &&
          $scope.$parent.accountDetails.accountDetails.accountNumber);
    }

    function makeMoneypakDeposit() {
      vm.loading = true;

      function _initiateDepositStatusPoller(data, successCb, errorCb) {
        Utilities.depositStatusPoller(
          function () {
            vm.activePoller = true;
            return DepositSrv.getDepositStatus(data.headers('Location'))
              .then(function (response) {
                return response.status;
              })
              .catch(errorCb);
          },
          10000,
          2000
        )
          .then(successCb)
          .catch(errorCb)
          .finally(function () {
            vm.activePoller = false;
          });
      }

      function _mpakSuccessPollerCb(messages, data, success) {
        if (success) {
          handleDepositSuccess(
            data.data,
            Utilities.supplant(messages.scenario5, {
              depositAmount: $filter('currency')(data.data.amount)
            })
          );
        } else {
          handleDepositError(
            data.data,
            Utilities.supplant(messages.scenario3a, {
              depositAmount: $filter('currency')(data.data.amount)
            }),
            'warning'
          );
        }
      }

      function _mpakErrorPollerCb(messages, data) {
        NotificationService.warning(
          'Deposit Poller',
          Utilities.supplant(messages.scenario3c, {
            depositAmount: $filter('currency')(data.data.amount)
          }),
          null,
          null,
          true
        );
      }

      function handleDepositSuccess(response, messageToDisplay, type) {
        var fromOption = _.get($scope, '$parent.fromOption.tla', '');
        if (type === 'success' || !type) {
          vm.responsibleGamingDelay = true;
          $timeout(function () {
            vm.responsibleGamingDelay = false;
          }, parseInt($filter('CMSValue')('debounceAfterDeposit'), 10) || 0);

          if ($rootScope.activeFeatures &&
            $rootScope.activeFeatures.showDepositSuccessModal &&
            fromOption !== 'registration'
          ) {
            DepositSrv.getSuccessDepositModal(false);
          } else {
            NotificationService.success(null, messageToDisplay, null, null, true);
          }
        } else if (type === 'warning') {
          NotificationService.warning(null, messageToDisplay, null, null, true);
        } else if (type === 'error') {
          NotificationService.error(null, messageToDisplay, null, null, true);
        }
        UserActionEventsService.emit('depositSuccessMoneyPak', response.amount, !!response.feePaid);

        if (isNative) {
          if ($window && $window.handleNativeMessages) {
            $window.handleNativeMessages('UPDATE_BALANCE');
          }
        }

        if ($rootScope.activeFeatures.isDMAInjectDepositSuccessModalEnabled) {
          if ($window.ReactInjector) {
            $window.ReactInjector.renderDepositSuccess(
                document.getElementById('injected-modal'),// eslint-disable-line
              {
                title: SUCCESS_MODAL_LABELS.title,
                text: SUCCESS_MODAL_LABELS.textTemplate.replace(
                  '@@@deposit_amount@@@',
                  response && response.amount),
                buttonText: SUCCESS_MODAL_LABELS.buttonText,
                sharedState: { isOpen: true },
                buttonCallback: successModalButtonCallback,
                closeCallback: successModalCloseCallback,
                onOpenCallback: successModalOnOpenCallback
              }
            );
          }
        }


        vm.mpakNumber = '';
        vm.moneyPakDepositForm.$setPristine();
        vm.moneyPakDepositForm.$setUntouched();
      }

      function handleDepositError(response, messageToDisplay, type) {
        if (type === 'error' || !type) {
          NotificationService.error(null, messageToDisplay, null, null, true);
        } else if (type === 'warning') {
          NotificationService.warning(null, messageToDisplay, null, null, true);
        } else if (type === 'success') {
          NotificationService.success(null, messageToDisplay, null, null, true);
        }
        UserActionEventsService.emit('depositErrorMoneyPak', messageToDisplay);
      }
      //eslint-disable-next-line
      return MoneyPakService.depositNewFlow(
        { cardNumber: vm.mpakNumber },
        getAccountId()
      )
        .then(function (data) {
          var statusCode = data.status;
          var messages = {};
          var messagesObj = $filter('CMSValue')('mpakDepositMessages');
          if ($scope.isRGAvailable) {
            vm.updateRGLimits(+data.data.amount);
          }
          try {
            messages = angular.fromJson(messagesObj);
          } catch (err) {
            // Prevent test failure
          }

          switch (statusCode) {
            case 200:
              if (data.data && data.data.balance) {
                $rootScope.$emit('accountBalance_changed', data.data.balance);
              }
              handleDepositSuccess(
                data.data,
                Utilities.supplant(
                  messages.scenario5 || mpakDepositMessagesMock.scenario5,
                  {
                    depositAmount: $filter('currency')(data.data.amount)
                  }
                )
              );
              break;
            case 202:
              NotificationService.warning(
                'Poller!',
                Utilities.supplant(
                  messages.scenario3b || mpakDepositMessagesMock.scenario3b,
                  {
                    depositAmount: $filter('currency')(data.data.amount)
                  }
                ),
                null,
                null,
                true
              );
              _initiateDepositStatusPoller(
                data,
                // eslint-disable-next-line
                _mpakSuccessPollerCb.bind(this, messages, data),
                // eslint-disable-next-line
                _mpakErrorPollerCb.bind(this, messages, data)
              );
              break;
            case 207:
              //eslint-disable-next-line
              var mpakDeposit = data.data.filter(function(item) {
                return item.id === 'MPAK_WITHDRAWAL';
              });
              //eslint-disable-next-line
              var amount = "";
              if (
                mpakDeposit[0] &&
                mpakDeposit[0].body &&
                mpakDeposit[0].body.amount
              ) {
                amount = mpakDeposit[0].body.amount;
              }

              NotificationService.warning(
                'Poller!',
                Utilities.supplant(
                  messages.scenario3a || mpakDepositMessagesMock.scenario3a,
                  {
                    depositAmount: $filter('currency')(amount)
                  }
                ),
                null,
                null,
                true
              );

              break;
            default:
              break;
          }
          DepositSrv._setHasMadeInitialDeposit(true);
          DepositSrv.updateCustomerStatus();
        })
        .catch(function (error) {
          var messagesObjExceptions = $filter('CMSValue')(
            'mpakDepositExceptions'
          );
          var mpakDepositExceptions = {};
          var statusCode = error.status;
          var genericMessage =
            'An error occurred while processing your deposit.';
          var errorMessage = 'error';
          //eslint-disable-next-line
          console.log(error);

          try {
            mpakDepositExceptions = angular.fromJson(messagesObjExceptions);
          } catch (err) {
            // Prevent test failure
          }

          if (
            $scope.isRGAvailable &&
            error.data &&
            error.data.code === 112703
          ) {
            sessionStorage.setItem('IS_SUSPENDED', 'true');
            $window.location = '/';
            // STOP HERE!!!
            // THIS IS A PRECISELY PLACED HAMMER 🔨
            if ($rootScope.layout === 'desktop') {
              $window.mediator.dispatch('TVG_LOGIN:DO_LOGOUT', {});
            }
          }

          switch (statusCode) {
            case 422:
              errorMessage =
                error.data &&
                error.data.message &&
                mpakDepositExceptions &&
                mpakDepositExceptions[error.data.message]
                  ? mpakDepositExceptions[error.data.message]
                  : genericMessage;
              NotificationService.error(
                'Poller!',
                errorMessage,
                null,
                null,
                true
              );

              UserActionEventsService.emit(
                'depositErrorMoneyPak',
                errorMessage
              );
              break;
            default:
              errorMessage = mpakDepositExceptions.generic || genericMessage;
              NotificationService.error(
                'Poller!',
                errorMessage,
                null,
                null,
                true
              );
              UserActionEventsService.emit(
                'depositErrorMoneyPak',
                errorMessage
              );
              break;
          }
        })
        .finally(function () {
          vm.loading = false;
        });
    }
    function checkRGLimitReached() {
      $scope.rgLimitReached = $scope.rgMoneypakAvailableDepositAmount === 0;
      return $scope.rgLimitReached;
    }

    function alertRGLimit(limitAmount) {
      if (!!limitAmount) {
        $scope.messageWithRemainingAmount = angular.fromJson(
          $filter('CMSValue')('moneyPakLabels').replace(
            '#AMOUNT_REMAINING',
            '$' + limitAmount.toLocaleString()
          )
        ).DMARGLimitRemaining;
      }
    }

    vm.getRGLimits = function () {
      var paymentOptionsResponse = MoneyPakService.getDepositOptions({}, getAccountId());
      paymentOptionsResponse.then(function (response) {
        $scope.rgMoneypakAvailableDepositAmount = response.data.remainingDepositLimit;
        checkRGLimitReached();
        alertRGLimit($scope.rgMoneypakAvailableDepositAmount);
      }).catch(function () {
        // ERROR SCENARIO
      });
    };

    vm.updateRGLimits = function (depositedValue) {
      if (!!$scope.rgMoneypakAvailableDepositAmount) {
        $scope.rgMoneypakAvailableDepositAmount -= depositedValue;
      }
      checkRGLimitReached();
      alertRGLimit($scope.rgMoneypakAvailableDepositAmount);
    };

    vm.$onInit = function () {
      vm.loading = false;
      vm.makingDeposit = false;
      vm.mpakNumber = '';

      $scope.isRGAvailable = angular.isDefined(
        $rootScope.activeFeatures.isRGAvailableOnDMA
      )
        ? $rootScope.activeFeatures.isRGAvailableOnDMA
        : false;

      $scope.isFDRApp = angular.isDefined($rootScope.isFdrApp)
        ? $rootScope.isFdrApp
        : false;
      modalTitle = MoneyPakService.getLabelFromCMS('faqTitle') || '';
      modalBody = MoneyPakService.getValueFromCMS('moneyPakFaqTemplate') || '';
      if ($scope.isRGAvailable) {
        vm.getRGLimits();
      }
    };

    vm.openModal = function (event) {
      if (event) {
        event.preventDefault();
      }
      UserActionEventsService.emit('moneyPakFAQ');
      return ModalDialogService.openLarge(modalTitle, modalBody);
    };

    vm.update = function (value) {
      vm.mpakNumber = value;
    };

    vm.handleFormSubmit = function () {
      UserActionEventsService.emit('depositAttemptMoneyPak', vm.mpakNumber);
      return handleAction() && makeMoneypakDeposit();
    };

    $scope.$on('$destroy', function () {
      var eventHandlers = _.keys(UserActionEventsService.eventHandlers);
      eventHandlers.map(function (eventName) {
        return UserActionEventsService.off(eventName);
      });
    });
  }

  angular
    .module('TVG.MoneyPak')
    .controller('MoneyPakController', MoneyPakController);
}());

(function () {
  'use strict';

  MoneyPakService.$inject = ['ConfigurationFac', '$filter', '$http', '$q', 'Utilities'];
  function MoneyPakService(ConfigurationFac, $filter, $http, $q, Utilities) {
    var self = {};

    var moneypakEndpoint = function (params) {
      return ConfigurationFac.getBaseServiceUrl().concat('/mpak/v1/' + params);
    };

    var moneypakEndpointNewFlow = function (accountId) {
      return ConfigurationFac.getBaseServiceUrl().concat(
        '/mpak/v1/users/' + accountId + '/deposit'
      );
    };

    var depositOptionsURL = function (accountId) {
      return ConfigurationFac.getBaseServiceUrl().concat(
        '/uwt/v1/users/' + accountId + '/limits/responsible-gaming'
      );
    };

    /**
     * checkTransaction
     * Check if the transaction failed, although the request did not return
     * any error status code.
     *
     * @param  {$httpResponse} response the response object from the $http call
     * @return {Promise}
     */
    var checkTransaction = function (response) {
      return $q(function (resolve, reject) {
        var errors = Utilities.prop('data.errors', response);
        if (errors) {
          return reject(self.createApiError(errors));
        }

        return resolve(response);
      });
    };

    var checkError = function (response) {
      return $q(function (resolve, reject) {
        return reject(
          self.createApiError([
            {
              message: response.data,
              code: response.status
            }
          ])
        );
      });
    };

    /**
     * Create an API error instance
     * Try to fetch an error message from the CMS (using the error code)
     * If none is found, use the error.message as a fallback
     *
     * @param  {Array} data [description]
     * @return {Error}     [description]
     */
    self.createApiError = function (data) {
      var apiError = new Error();
      var error = (data && data[0]) || {};
      var moneyPakError = self.getLabelFromCMS(error.code);

      apiError.message = moneyPakError || error.message;
      apiError.code = error.code;
      return apiError;
    };

    self.request = function (params) {
      return $http({
        url: moneypakEndpoint(params.url),
        method: params.method,
        data: params.body,
        headers: self.addHeaders()
      })
        .catch(checkError)
        .then(checkTransaction)
        .then(Utilities.prop('data.response'));
    };

    self.requestNewFlow = function (params, accountId) {
      return $http({
        url: moneypakEndpointNewFlow(accountId),
        method: params.method,
        data: params.body,
        headers: self.addHeaders()
      });
    };

    self.requestDepositOptions = function (params, accountId) {
      return $http({
        url: depositOptionsURL(accountId),
        method: params.method,
        data: params.body,
        headers: self.addHeaders()
      });
    };

    /**
     * Add the headers needed to perform API calls
     *
     * @return {object}: Header Object
     */
    self.addHeaders = function (options) {
      var headers = {
        'x-tvgcontext': angular.toJson(ConfigurationFac.getApplicationContext())
      };

      if (Utilities.prop('cache', options)) {
        headers = angular.extend(
          {},
          {
            'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
            'Cache-Control': 'no-cache',
            Pragma: 'no-cache'
          },
          headers
        );
      }
      return headers;
    };

    /**
     * Get labels from CMS
     * @param  {string} name label Name
     * @return {string}      label
     */
    self.getLabelFromCMS = function (name) {
      return $filter('CMSLabels')(name, 'moneyPakLabels');
    };

    /**
     * Get value from CMS
     * @param  {string} name value Name
     * @return {string}      CMS value
     */
    self.getValueFromCMS = function (name) {
      return $filter('CMSValue')(name);
    };

    self.deposit = function (data) {
      var maxTime = self.getLabelFromCMS(
        'checkDepositStatusIntervalDurationInMilliseconds'
      );

      return self
        .request({
          url: 'deposit',
          method: 'POST',
          body: data
        })
        .then(function (response) {
          if (response.errors) {
            return $q.reject(response);
          }

          return Utilities.backOff(function (next, stop) {
            return self
              .getDepositState(response.depositId)
              .then(function (depositData) {
                if (depositData.status === 'Completed') {
                  stop(depositData);
                } else {
                  next();
                }
              });
          }, maxTime).catch(function (error) {
            var newError = error;
            if (newError.message === 'BACKOFF_TIMEOUT') {
              newError.code = '9';
            }
            return $q.reject(newError);
          });
        });
    };

    self.depositNewFlow = function (data, accountId) {
      return self.requestNewFlow(
        {
          method: 'POST',
          body: data
        },
        accountId
      );
    };

    self.getDepositState = function (depositId) {
      return self.request({
        url: 'deposit/' + depositId,
        method: 'GET'
      });
    };

    self.getDepositOptions = function (data, accountId) {
      return self.requestDepositOptions(
        {
          method: 'GET'
        },
        accountId
      );
    };

    return self;
  }

  angular.module('TVG.MoneyPak').factory('MoneyPakService', MoneyPakService);
}());

angular.module('TVG.MoneyPak')
  .component('limitsTable', {
    bindings: {
      contentObj: '<'
    },
    controller: 'LimitsTableController as vm',
    templateUrl: 'src/moneypak/limits-table/limits-table.template.html'
  });

(function () {
  'use strict';

  LimitsTableController.$inject = ['$log'];
  function LimitsTableController($log) {
    var vm = this;

    vm.$onInit = function () {
      try {
        vm.content = angular.fromJson(vm.contentObj);
      } catch (e) {
        vm.content = [];

        $log.error('LimitsTableController - error parsing JSON "' + vm.contentObj +
          '": "' + e.message + '"');
      }
    };
  }

  angular.module('TVG.MoneyPak')
    .controller('LimitsTableController', LimitsTableController);
}());

angular.module('TVG.MoneyPak')
  .component('moneypakActivationNumberInput', {
    bindings: {
      mpakNumber: '<',
      form: '<',
      onUpdate: '&'
    },
    controller: 'MoneyPakActivationNumberController',
    templateUrl: 'src/moneypak/moneypak-activation-number-input/moneypak-activation-number-input.template.html'
  });

(function () {
  'use strict';

  MoneyPakActivationNumberController.$inject = ['UserActionEventsService'];
  function MoneyPakActivationNumberController(UserActionEventsService) {
    var vm = this;
    vm.firstTime = true;

    vm.update = function () {
      if (vm.form.$error) {
        UserActionEventsService.emit('moneyPakFill', vm.form.$error);
      }
      if (vm.mpakNumber) {
        vm.onUpdate({ value: vm.mpakNumber });
      }
    };

    vm.startDeposit = function () {
      if (vm.firstTime) {
        UserActionEventsService.emit('moneyPakStart');
        vm.firstTime = false;
      }
    };

    vm.openTooltip = function () {
      UserActionEventsService.emit('moneyPakTooltip');
    };

    vm.$onChanges = function (changesObj) {
      vm.mpakNumber = _.get(changesObj, 'mpakNumber.currentValue');
    };
  }

  angular
    .module('TVG.MoneyPak')
    .controller('MoneyPakActivationNumberController', MoneyPakActivationNumberController);
}());

(function () {
  'use strict';

  DMATogglesRun.$inject = ['DmaTvg4FeatureTogglesSvc', 'DMAFeatureTogglesHashContainerSvc'];
  angular.module('TVG.DMAToggles', []);
  angular.module('TVG.Deposit', [
    'TVG.Content',
    'TVG.DMAToggles',
    'TVG.Paypal.Deposits',
    'TVG.ApplePay.Deposits',
    'TVG.MoneyPak',
    'ui.bootstrap',
    'angular.filter',
    'TVG.DMA.Common',
    'UserActionEvents',
  ]);
  angular.module('TVG.Withdraw', [
    'TVG.Content',
    'TVG.Deposit',
    'TVG.DMAToggles',
    'TVG.Paypal.Withdrawals',
    'TVG.DMA.Common'
  ]);
  angular.module('TVG.Transfer', [
    'TVG.Content',
    'TVG.DMAToggles',
    'TVG.DMA.Common'
  ]);
  angular.module('TVG.ManagePaymentMethods', [
    'TVG.Deposit',
    'TVG.Content',
    'TVG.DMAToggles',
    'TVG.DMA.Common'
  ]);

  angular.module('TVG.DMAToggles').run(DMATogglesRun);

  function DMATogglesRun(
          DmaTvg4FeatureTogglesSvc,
          DMAFeatureTogglesHashContainerSvc) {
    DMAFeatureTogglesHashContainerSvc.registerAsDefault(DmaTvg4FeatureTogglesSvc);
  }
}());

angular.module('TVG.Deposit').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('src/templates/deposit/deposit-error.html',
    "<div class=\"handler-error-container\"><span class=\"image\"></span><h1 class=\"title\">Error!</h1><div class=\"message-container\"><h2><strong>This method of payment doesn't seem to be going through.</strong></h2><p class=\"customer_service\" ng-bind-html=\"('depositsErrorDefault'| CMSValue : null) | trust\"></p></div></div>"
  );


  $templateCache.put('src/templates/deposit/deposit-success-modal.html',
    "<div class=\"tvg-dialog dma-redesign sightline-redirect-modal\"><div class=\"tvg-dialog-dma-redesign-header\"><span class=\"tvg-dialog-dma-redesign-title\" style=\"text-transform: uppercase; display: block; margin-top: 3px;\" ng-bind=\"('depositLabelSuccessTitleModal' | CMSLabels: 'dmaManagementLabels' | trust)\" data-qa-label=\"depositSuccessTitleModal\"></span> <a href class=\"tvg-dialog-dma-redesign-close-icon\" ng-click=\"$close()\" data-qa-label=\"depositSuccessCloseModal\"><i class=\"tvg-icon-close\"></i></a></div><div class=\"tvg-dialog-dma-redesign-body\" style=\"padding: 16px;\"><div style=\"margin-bottom: 10px\"><span class=\"depositSuccessLabel\" ng-class=\"{depositSuccessLabelACH: !isACH}\" ng-bind=\"('depositLabelSuccessTextModal' | CMSLabels: 'dmaManagementLabels' | trust)\"></span> <span ng-if=\"isACH\" ng-bind=\"('depositLabelACHTextModal' | CMSLabels: 'dmaManagementLabels' | trust)\"></span></div><div><button class=\"proceed-btn\" ng-click=\"betNow($close)\" data-qa-label=\"depositSuccessBetNowButton\" ng-bind=\"('depositSuccessBetNowButton' | CMSLabels: 'dmaManagementLabels' | trust)\"></button></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/deposit-success.html',
    "<div class=\"handler-success-container\"><span class=\"image\"></span><h1 class=\"title\">Success!</h1><div class=\"message-container\"><h2><strong>Your transaction was successful.</strong></h2><p class=\"message\">{{'globalDepositSuccess' | CMSValue : {depositamount:(depositData.requestedAmount | currency), availabledate:depositData.depositAvailableDate} }}</p></div></div>"
  );


  $templateCache.put('src/templates/deposit/deposit.html',
    "<div class=\"tvg-deposit\" ng-controller=\"DepositController\" ng-class=\"{loading: data.loading, 'njx-deposit': njxIntegration}\"><div ng-show=\"!data.showingFallback\"><welcome-dialog-fdr ng-if=\"$root.isFdrApp && !data.loading && $root.newUser && !data.errorLoadingData\"></welcome-dialog-fdr><dw-info-dialog ng-if=\"data.errorLoadingData && !data.loading && !$root.isFdrApp\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\">{{'depositInitialDataErrorMessage' | CMSValue : null}}</dw-info-dialog><dw-info-dialog-fdr ng-if=\"data.errorLoadingData && !data.loading && $root.isFdrApp\" heading-text=\"Something went wrong\" button-text=\"Refresh Page\" button-action=\"location.reload()\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\">{{'depositInitialDataErrorMessage' | CMSValue : null}}</dw-info-dialog-fdr><dw-info-dialog ng-if=\"data.errorDepositRestrictions && !data.loading\" ng-bind-html=\"'error-deposit-restrictions' | CMSLabels: 'error-deposit-restrictions' | trust\"></dw-info-dialog><form id=\"sightline__user-form\" ng-if=\"displays.isSightlineIframeVisible() || isAddingFunds\" action=\"{{data.slnIframeURL}}\" name=\"sightline__user-form\" target=\"sightline__iframe\" method=\"post\" autocomplete=\"off\"><input id=\"{{key}}\" type=\"hidden\" ng-repeat=\"(key, val) in sglUser\" name=\"{{key}}\" value=\"{{val}}\"></form><form id=\"cardsForm_id\" ng-show=\"!data.errorLoadingData && !data.loading && !data.errorDepositRestrictions\" class=\"deposit-form\" name=\"depositFrm\" ng-submit=\"events.makeDeposit(depositFrm)\" ng-class=\"{loading: !!(data.makingDeposit || data.fetchingInfo || data.activePoller)}\" novalidate><deposit-type-selector></deposit-type-selector><div class=\"methods-wrapper\" ng-switch on=\"data.selectedPayOption.ftype\"><!-- GreenDot eCash--><div ng-switch-when=\"ECSH\"><div ng-include=\"'src/templates/deposit/types/greendot_ecash.html'\"></div></div><!-- GreenDot MoneyPak--><div ng-switch-when=\"MPAK\"><moneypak ng-if=\"!displays.isTVG3()\"></moneypak><div class=\"disclaimer mpak-disclaimer\" ng-if=\"displays.isTVG3()\" ng-bind-html=\"'tvg3Message' | CMSLabels: 'moneyPakLabels'\"></div></div><!-- Sightline --><div ng-switch-when=\"SLN\" ng-class=\"{'loading': !$root.sightlineLoaded && !$root.sightlineFlowVersion}\"><react-sightline></react-sightline></div><!-- Pay Near Me--><div ng-switch-when=\"PNM\"><div ng-include=\"'src/templates/deposit/types/payNearMe/paynearme.html'\"></div></div><div ng-switch-when=\"PAY\"><paypal-deposit ng-if=\"!displays.isTVG3() && !njxIntegration\" min-amount=\"::PaypalDepositConfig.min\" max-amount=\"::PaypalDepositConfig.max\" amount-options=\"::data.availableAmountOptions\" deposit-amount=\"depositDataModel.amount\" is-payment-confirmation=\"::fromOption.isPaymentConfirmation\" user-cancelled=\"::fromOption.userCancelled\" on-payment-complete=\"events.handleBalanceUpdate($event)\" on-amount-change=\"events.handlePaypalAmountChange($event)\"></paypal-deposit><div class=\"disclaimer paypal-disclaimer\" ng-if=\"displays.isTVG3() && !njxIntegration\" ng-bind-html=\"'tvg3Message' | CMSLabels: 'paypalLabels'\"></div><div class=\"disclaimer paypal-disclaimer\" ng-if=\"njxIntegration\">Coming Soon</div></div><!-- Apple Pay--><div ng-switch-when=\"APPL\"><applepay-deposit ng-if=\"!displays.isTVG3()\" min-amount=\"depositDataModel.min\" max-amount=\"depositDataModel.max\" amount-options=\"::data.availableAmountOptions\" ng-init=\"events.setDepositTypeLimits(data.selectedPayOption.ftype)\" deposit-amount=\"depositDataModel.amount\" on-payment-complete=\"events.handleBalanceUpdate($event)\"></applepay-deposit></div><!-- Other payment methods --><div ng-switch-when=\"OTHER\"><div qa-label=\"otherPayment\" class=\"other-payments\" ng-bind-html=\"('depositsOtherPayments'| CMSValue : null ) | trust\"></div></div><!-- Other--><div ng-switch-default><div class=\"alert-box error clearfix expired-card-error\" qa-label=\"expiredCardMessage\" ng-if=\"events.anyCardsExpired()\"><i class=\"tvg-icon-error\"></i><div class=\"content\">It seems your card has expired please update your credit card info.</div></div><ach-description-text ng-if=\"data.selectedPayOption.ftype=='IBC'\"></ach-description-text><card-description-text ng-if=\"data.selectedPayOption.ftype=='CC'\"></card-description-text><section-title class=\"first-title\" qalabel=\"depositAmountTitle\" title=\"{{'deposit-amount-title' | CMSLabels: 'dmaDepositLabels'}}\" index=\"1\"></section-title><deposit-amount-input ng-if=\"(depositDataModel.isAvailable != false) || events.existsOnFile()\"></deposit-amount-input><section-title class=\"cards-section-title\" qalabel=\"accountSectionTitle\" title=\"{{ displays.toggleTitles() | CMSLabels: 'dmaDepositLabels' | trust }}\" index=\"2\"></section-title><toggle-new-onfile ng-if=\"((depositDataModel.isAvailable != false || events.existsOnFile()) &&\n" +
    "                          data.selectedPayOption.ftype!='IBC')\"><toggle-option qa-label=\"cardsOnFileButton\" ng-show=\"data.depositSection==='NEW' && data.selectedPayOption.onFile.length > 0\" ng-click=\"depositFrm.cardCvn.$setPristine();\n" +
    "                              events.toggleNewStoredMethods('STORED');\n" +
    "                              events.clearCVN();\n" +
    "                              events.resetAllModels()\" ng-class=\"{selected: data.depositSection=='STORED'}\" ng-bind-html=\"'deposit-list-cards' | CMSLabels: 'dmaDepositLabels' | trust\"></toggle-option><toggle-option qa-label=\"addNewCardButton\" ng-show=\"data.depositSection==='STORED'\" ng-click=\"depositFrm.cardCvn.$setPristine();\n" +
    "                              events.toggleNewStoredMethods('NEW');\n" +
    "                              events.clearCVN();\n" +
    "                              events.resetAllModels()\" ng-class=\"{selected: data.depositSection=='NEW'}\" ng-bind-html=\"'deposit-new-card' | CMSLabels: 'dmaDepositLabels' | trust\"></toggle-option></toggle-new-onfile><toggle-new-onfile ng-if=\"(depositDataModel.isAvailable != false || events.existsOnFile()) &&\n" +
    "                          data.selectedPayOption.onFile.length &&\n" +
    "                          data.selectedPayOption.ftype=='IBC' &&\n" +
    "                          data.selectedPayOption.bothACHAndIBCAvailable == true &&\n" +
    "                          !data.achDepositLimitExceeded || displays.unableToFetchBankAccounts()\"><toggle-option qa-label=\"accountsOnFile\" ng-show=\"data.depositSection==='NEW'\" ng-click=\"depositFrm.cardCvn.$setPristine();\n" +
    "                              events.toggleNewStoredMethods('STORED');\n" +
    "                              events.clearCVN();\n" +
    "                              events.resetAllModels()\" ng-bind-html=\"'deposit-list-accounts' | CMSLabels: 'dmaDepositLabels' | trust\"></toggle-option><toggle-option qa-label=\"addNewAccount\" ng-show=\"data.depositSection==='STORED'\" ng-click=\"depositFrm.cardCvn.$setPristine();\n" +
    "                              events.toggleNewStoredMethods('NEW');\n" +
    "                              events.clearCVN();\n" +
    "                              events.resetAllModels()\" ng-bind-html=\"'deposit-new-account' | CMSLabels: 'dmaDepositLabels' | trust\"></toggle-option></toggle-new-onfile><div ng-if=\"displays.isDepositFormVisible()\"><div qa-label=\"depositFormSection\" ng-if=\"data.selectedPayOption.ftype=='IBC' && !data.achDepositLimitExceeded\"><div ng-if=\"displays.isIBCValidVisible()\"><div ng-if=\"!events.existsOnFile()\" ng-init=\"events.setDepositTypeLimits(data.selectedPayOption.ftype)\"></div><div class=\"form-fields\" ng-repeat=\"field in data.forms[data.depositSection][data.selectedPayOption.ftype]\"><div ng-include=\"'src/templates/deposit/fields/'+field+'.html'\"></div></div></div><div class=\"deposit-card-options\" ng-if=\"data.depositSection === 'STORED' && events.existsOnFile()\" qa-label=\"accountsOnFileSection\"><label ng-bind-html=\"'deposit-betcash-cards-subtitle' | CMSLabels: 'dmaDepositLabels' | trust\" class=\"form-header\"></label><ul qa-label=\"bankAccountsList\" ng-init=\"depositDataModel.selectedOnFile = data.selectedPayOption.onFile[data.selectedCard];\n" +
    "                                         events.selectOnFileChanged(depositDataModel.selectedOnFile)\"><li ng-repeat=\"card in data.selectedPayOption.onFile track by card.achId\" class=\"card\" qa-label=\"betcash-card-onfile\"><label ng-class=\"{'active': depositDataModel.selectedOnFile === card ||\n" +
    "                                        ((card.ftype === 'IBC'|| card.ftype === 'ACH') && depositDataModel.selectedOnFile.achId === card.achId)}\"><strong ng-bind=\"::($root.isFdrApp ? card.bankName.toLowerCase() : card.bankName)\"></strong><div>*****{{(events.slicedCard(card.bankAccNumber))}}</div><input type=\"radio\" ng-model=\"depositDataModel.selectedOnFile\" ng-change=\"events.registerAccountSelectionOnGTM(card.bankName)\" ng-value=\"card\"></label></li></ul></div></div><div ng-if=\"displays.isIBCInvalidVisible()\"><div><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositBetCashPendingMessageText' | CMSValue : null}}</dw-info-dialog></div></div><div ng-if=\"data.depositSection === 'NEW' && data.selectedPayOption.ftype=='CC'\"><div class=\"form-fields\" ng-repeat=\"field in data.forms[data.depositSection][data.selectedPayOption.ftype]\"><div ng-include=\"'src/templates/deposit/fields/'+field+'.html'\"></div></div></div><div class=\"deposit-card-options\" ng-if=\" data.selectedPayOption.ftype === 'CC' && data.depositSection === 'STORED' && !displays.unableToFetchCardsOnFile()\"><label class=\"form-header\" qa-label=\"preAuthorizedCards\" ng-bind-html=\"'depositAchOnFileCardsSelectionLabel' | CMSValue : null\"></label><ul qa-label=\"cardsList\" ng-init=\"depositDataModel.selectedOnFile = data.selectedPayOption.onFile[data.selectedCard]; events.selectOnFileChanged(depositDataModel.selectedOnFile)\"><li qa-label=\"ccCardsOnFile\" ng-repeat=\"card in data.selectedPayOption.onFile track by card.id\" class=\"card\"><label qa-label=\"cardInfo\" ng-class=\"{'active': depositDataModel.selectedOnFile === card ||\n" +
    "                                    (card.ftype === 'CC' && depositDataModel.selectedOnFile.id === card.id) }\"><strong ng-bind=\"::card.typeName + ' Card'\"></strong><div><span ng-if=\"card.isExpired\" class=\"expired-card-label\">{{'expired-card' | CMSLabels: 'dmaDepositLabels'}} </span><span ng-bind=\"::card.cardNumberExt\"></span> (<span ng-bind=\"::card.expirationDate\"></span>)</div><input qa-label=\"cardSelection\" type=\"radio\" ng-model=\"depositDataModel.selectedOnFile\" ng-change=\"events.changeCard(depositDataModel.selectedOnFile)\" ng-value=\"card\"></label></li></ul><div ng-if=\"data.selectedPayOption.ftype === 'CC' && data.depositSection === 'STORED'\" ng-include=\"'src/templates/deposit/fields/card-verification-number.html'\"></div></div><div ng-if=\"depositDataModel.isPending == true\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositBetCashPendingMessageText' | CMSValue : null}}</dw-info-dialog></div><div ng-if=\"displays.isNotIBCValidVisible()\"><section-title title=\"Review and Authorize\" qalabel=\"reviewTitle\" index=\"{{ displays.hasThreeTitles() ? 3 : 4 }}\"></section-title><deposit-total-cost ng-if=\"displays.isPendingNotCalculatingVisible()\"></deposit-total-cost><div class=\"form-fields terms-conditions\" qa-label=\"terms-conditions\" ng-if=\"data.depositSection=='NEW' && data.selectedPayOption.ftype=='IBC'\"><span class=\"terms-subtitle\">By selecting {{'depositExecuteButton' | CMSValue : null}} I accept <span class=\"link-text\" qa-label=\"termsAndCondsLink\" ng-click=\"events.openTerms()\">terms and conditions</span> {{'depositAuthorizationAgreement' | CMSValue : null}}</span></div><div ng-if=\"depositDataModel.isPending != true\" class=\"field\"><button qa-label=\"submit-button\" class=\"submit add-funds\" ng-disabled=\"(data.disabledCard || data.makingDeposit || data.fetchingInfo || data.activePoller || data.fee.calculatingFees || !depositDataModel.depositTypeId || events.anyCardsExpired() || data.responsibleGamingDelay)\" type=\"submit\"><i class=\"tvg-icon tvg-icon-lock\"></i> <strong ng-bind=\"'depositExecuteButton' | CMSValue : null\"></strong></button><div ng-if=\"!notifyErrors\" qa-label=\"invalidFormMessage\" ng-show=\"data.showInvalidFormMessage\" ng-class=\"{show: data.showInvalidFormMessage}\" class=\"js-error-label error-label fade-msg text-centered tvg-tooltip-ctn general-form-error\"><p qa-label=\"incompleteFormErrorMessage\" ng-bind-html=\"'deposit-authorize-error-message' | CMSLabels: 'dmaDepositLabels' | trust\"></p></div></div></div></div><div ng-if=\"displays.isIBCValidExceededVisible()\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositsBetcashPeriodLimitExceeded' | CMSValue : null}}</dw-info-dialog></div><div ng-if=\"displays.unableToFetchBankAccounts()\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositsBetcashUnableToFetchBankAccounts' | CMSValue : null}}</dw-info-dialog></div><div ng-if=\"displays.unableToFetchCardsOnFile()\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositsCCUnableToFetchCardsOnFile' | CMSValue : null}}</dw-info-dialog></div><div ng-if=\"depositDataModel.isAvailable == false && !events.existsOnFile()\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositsBetcashPeriodLimitExceeded' | CMSValue : null}}</dw-info-dialog></div></div></div></form></div><dw-info-dialog ng-if=\"!data.loading && !$root.isFdrApp && data.showingFallback\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\">{{'depositNoPaymentMethodsAvailable' | CMSValue : null}}</dw-info-dialog></div>"
  );


  $templateCache.put('src/templates/deposit/fields/account-pin-pwd.html',
    "<div class=\"field\" qa-label=\"pin-password\"><div class=\"field-label\"><label qa-label=\"tvgPinPassLabel\" for=\"pinPass\" ng-bind=\"'depositPasswordPinLabel' | CMSValue : null\"></label></div><div class=\"field-input\"><span class=\"input-container\"><input name=\"fakepassword\" type=\"password\" style=\"position: absolute; left: -9999px;\" tabindex=\"-1\"> <input qa-label=\"tvgPinPassInput\" name=\"pinPass\" id=\"pinPass\" type=\"password\" autocomplete=\"off\" ng-model=\"depositDataModel.pinPass\" ng-blur=\"events.completedFieldAndBlursAway('TVG Password/PIN', depositFrm.pinPass)\" ng-required=\"true\" ng-model-options=\"{ updateOn: 'blur', debounce: { 'blur': 0 } }\"></span></div><div class=\"field-tooltip\"><div class=\"tvg-tooltip-ctn error-tooltip\" ng-if=\"data.showIBCInvalidPinOrPasswordMessage || (depositFrm.pinPass.$invalid && (depositFrm.pinPass.$touched || depositFrm.$submitted))\" ng-init=\"events.newAccountFieldError('TVG Password/PIN', 'depositInvalidPasswordPinText' | CMSValue)\"><p ng-bind=\"'depositInvalidPasswordPinText' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/ach-description-text.html',
    "<div class=\"disclaimer\" ng-bind-html=\"'depositRoutingNumberInfo' | CMSLabels: 'dmaDepositLabels' | trust\" qa-label=\"betcash-intro-disclaimer\"></div>"
  );


  $templateCache.put('src/templates/deposit/fields/applepay-description-text.html',
    "<div class=\"disclaimer\" qa-label=\"applepay-intro-disclaimer\" ng-bind-html=\"(('applepayDebitInformation' | CMSLabels: 'dmaDepositLabels' | trust))\"><span ng-if=\"$root.isFdrApp\">{{'depositCardsAccepted' | CMSLabels: 'dmaDepositLabels'}}</span></div>"
  );


  $templateCache.put('src/templates/deposit/fields/bank-account-number.html',
    "<div class=\"field\" qa-label=\"bank-account-number\" ng-class=\"{ focused: bankNumberFocus && !(depositFrm.accountNumber.$invalid && (depositFrm.accountNumber.$touched || depositFrm.$submitted))}\"><div class=\"field-label\"><label qa-label=\"accountNumberLabel\" for=\"accountNumber\" ng-bind=\"'depositCheckingAccountNumber' | CMSValue : null\" ng-class=\"{errorLabel: depositFrm.accountNumber.$invalid && (depositFrm.accountNumber.$touched || depositFrm.$submitted)}\"></label></div><div class=\"field-input\"><span class=\"input-container\"><input qa-label=\"accountNumberInput\" name=\"accountNumber\" id=\"accountNumber\" ng-model=\"depositDataModel.accountNumber\" ng-focus=\"bankNumberFocus = true\" ng-blur=\"events.completedFieldAndBlursAway('Account Number', depositFrm.accountNumber); bankNumberFocus = false\" ng-pattern=\"data.numberPattern\" ng-model-options=\"{ updateOn: 'blur', debounce: { 'blur': 0 } }\" ng-required=\"true\" minlength=\"3\" autocomplete=\"off\" ng-keypress=\"events.onlyNumbers($event)\" type=\"tel\"></span></div><div class=\"field-tooltip\"><div class=\"tvg-tooltip-ctn error-tooltip\" ng-if=\"depositFrm.accountNumber.$invalid && (depositFrm.accountNumber.$touched || depositFrm.$submitted)\" ng-init=\"events.newAccountFieldError('Account Number', 'depositCheckingAccountNumberInvalid' | CMSValue)\"><p qa-label=\"checkingAccountNumberInvalidMessage\" ng-bind=\"'depositCheckingAccountNumberInvalid' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/bank-name.html',
    "<div class=\"field\" qa-label=\"bank-name\" ng-class=\"{ focused: bankNameFocus && !(depositFrm.bankName.$invalid && data.errorBankName) }\"><div class=\"field-label\"><label qa-label=\"bankNameLabel\" for=\"bankName\" ng-bind=\"'depositBankNameLabel' | CMSValue : null\" ng-class=\"{errorLabel: depositFrm.bankName.$invalid && data.errorBankName}\"></label></div><div class=\"field-input\"><span class=\"input-container\"><input name=\"bankName\" id=\"bankName\" ng-model=\"depositDataModel.bankName\" ng-class=\"{'bank-name-input-invalid': depositFrm.bankName.$invalid && data.errorBankName}\" ng-blur=\"events.completedFieldAndBlursAway('Bank Name', depositFrm.bankName); bankNameFocus = false\" ng-focus=\"bankNameFocus = true\" ng-disabled=\"data.bankNameDisabled\" ng-model-options=\"{ updateOn: 'blur', debounce: { 'blur': 0 } }\" ng-required=\"depositFrm.routingNumber.$valid\" type=\"text\"></span></div><div class=\"field-tooltip\"><div class=\"tvg-tooltip-ctn\" ng-class=\"{'error-tooltip': data.errorBankName}\" ng-if=\"depositFrm.bankName.$invalid\" ng-init=\"events.newAccountFieldError('Bank Name', 'depositCheckingBankNameInvalid' | CMSValue)\"><p qa-label=\"checkingBankNameInvalidMessage\" ng-bind=\"'depositCheckingBankNameInvalid' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/bank-routing-number.html',
    "<div class=\"field\" qa-label=\"bank-routing-number\" ng-class=\"{focused: bankRoutingFocus && !(depositFrm.routingNumber.$invalid && (depositFrm.routingNumber.$touched || depositFrm.$submitted))}\"><div class=\"field-label\"><label qa-label=\"bankRoutingNumber\" for=\"routingNumber\" ng-bind=\"'depositRoutingNumberLabel' | CMSValue : null\" ng-class=\"{errorLabel: depositFrm.routingNumber.$invalid && (depositFrm.routingNumber.$touched || depositFrm.$submitted)}\"></label></div><div class=\"field-input field-input-banking-number\"><span class=\"input-container\"><input qa-label=\"bankRoutingNumberInput\" name=\"routingNumber\" id=\"routingNumber\" ng-model=\"depositDataModel.routingNumber\" ng-change=\"events.routingNumberOnChange(depositDataModel.routingNumber)\" ng-model-options=\"{ updateOn: 'blur', debounce: { 'blur': 0 } }\" ng-pattern=\"data.numberPattern\" ng-focus=\"bankRoutingFocus = true\" ng-blur=\"events.completedFieldAndBlursAway('Routing Number', depositFrm.routingNumber); bankRoutingFocus = false\" ng-required=\"true\" ng-keypress=\"events.onlyNumbers($event)\" minlength=\"9\" maxlength=\"9\" autocomplete=\"off\" type=\"tel\"></span><additional-info><span qa-label=\"bankRoutingNumberHelperImage\" class=\"card-imgs routing\"></span></additional-info></div><div class=\"field-tooltip\"><div class=\"tvg-tooltip-ctn error-tooltip\" ng-if=\"depositFrm.routingNumber.$invalid && (depositFrm.routingNumber.$touched || depositFrm.$submitted)\" ng-init=\"events.newAccountFieldError('Routing Number', 'depositRoutingNumberInvalid' | CMSValue)\"><p qa-label=\"bankRoutingNumberInvalidMessage\" ng-bind=\"'depositRoutingNumberInvalid' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/card-description-text.html',
    "<div class=\"disclaimer\" qa-label=\"credit-debit-card-intro-disclaimer\">{{'depositCreditDebitInformation' | CMSValue: 'dmaDepositLabels' | trust}} <span ng-if=\"$root.isFdrApp\">{{'depositCardsAccepted' | CMSLabels: 'dmaDepositLabels'}}</span></div>"
  );


  $templateCache.put('src/templates/deposit/fields/card-exp-date-and-cvn.html',
    "<div><div class=\"field\" qa-label=\"card-expiration-date\"><div class=\"field-label\"><label qa-label=\"cardExpirationDateLabel\" for=\"cardExpirationMonth\" ng-bind=\"'depositNewCardExpirationDateLabel' | CMSValue : null\" ng-class=\"{errorLabel: (depositFrm.cardExpMonth.$invalid && depositFrm.cardExpMonth.$touched) || (depositFrm.cardExpYr.$invalid && depositFrm.cardExpYr.$touched), focused: (expMonthFocused || expYearFocused) && !((depositFrm.cardExpMonth.$invalid && depositFrm.cardExpMonth.$touched) || (depositFrm.cardExpYr.$invalid && depositFrm.cardExpYr.$touched))}\"></label></div><div class=\"field-input card-exp\"><span class=\"input-container\"><input qa-label=\"cardExpirationMonthInput\" id=\"cardExpirationMonth\" class=\"tiny\" name=\"cardExpMonth\" ng-focus=\"expMonthFocused = true\" placeholder=\"MM\" ng-required=\"true\" pattern=\"(12|([0][1-9])|([1][0-2]|([1-9])))\" minlength=\"1\" maxlength=\"2\" tvg-limit-to=\"2\" type=\"number\" ng-blur=\"events.FieldFilled(depositFrm.cardExpMonth); expMonthFocused = false \" ng-keypress=\"events.onlyNumbers($event)\" ng-model=\"depositDataModel.expirationMonth\"> <span>/</span> <input qa-label=\"cardExpirationYearInput\" id=\"cardExpirationYear\" class=\"tiny\" name=\"cardExpYr\" ng-focus=\"expYearFocused = true\" placeholder=\"YY\" ng-required=\"true\" min=\"{{data.expirationDateValues.min}}\" max=\"{{data.expirationDateValues.max}}\" minlength=\"2\" maxlength=\"2\" tvg-limit-to=\"2\" ng-blur=\"events.FieldFilled(depositFrm.cardExpYr); expYearFocused = false\" type=\"number\" ng-keypress=\"events.onlyNumbers($event)\" pattern=\"\\d*\" ng-model=\"depositDataModel.expirationYear\"></span></div><div class=\"field-tooltip card-exp\"><div qa-label=\"invalidMonthMessage\" class=\"tvg-tooltip-ctn error-tooltip\" ng-if=\"depositFrm.cardExpMonth.$invalid && (depositFrm.cardExpMonth.$touched || depositFrm.$submitted)\"><p ng-bind=\"('depositNewCardExpirationDateMonthInvalid' | CMSValue : null)\"></p></div><div qa-label=\"invalidYearMessage\" class=\"tvg-tooltip-ctn error-tooltip error-tooltip-year\" ng-if=\"depositFrm.cardExpYr.$invalid && depositFrm.cardExpYr.$touched && !(depositFrm.cardExpMonth.$invalid && (depositFrm.cardExpMonth.$touched || depositFrm.$submitted))\"><p ng-bind=\"('depositNewCardExpirationDateYearInvalid' | CMSValue : {startYear:currentYear, endYear:(currentYear +50)})\"></p></div></div></div><div class=\"field field-cvv\" ng-class=\"{focused: ccvFocused && !(depositFrm.cardCvn.$invalid && (depositFrm.cardCvn.$touched || depositFrm.$submitted))}\"><div class=\"field-label\"><label qa-label=\"ccCvvLabel\" for=\"cardCvv\" ng-bind=\"'depositCardVerificationNumberLabel' | CMSValue : null\" ng-class=\"{errorLabel: depositFrm.cardCvn.$invalid && (depositFrm.cardCvn.$touched || depositFrm.$submitted)}\"></label></div><div qa-label=\"securityNumberSection\" class=\"field-input cardCvn\"><span class=\"input-container\"><input qa-label=\"ccCvvInput\" id=\"cardCvv\" class=\"small\" name=\"cardCvn\" ng-required=\"true\" maxlength=\"3\" minlength=\"3\" tvg-limit-to=\"3\" ng-pattern=\"data.numberPattern\" ng-focus=\"ccvFocused = true\" ng-model=\"depositDataModel.cardSecurityNumber\" ng-model-options=\"{ updateOn: 'blur', debounce: { blur: 0 } }\" type=\"tel\" ng-blur=\"events.FieldFilled(depositFrm.cardCvn, 'new'); ccvFocused = false\" ng-keypress=\"events.onlyNumbers($event)\" pattern=\"\\d*\"><additional-info><span qa-label=\"ccCvvImage\" class=\"card-imgs cvv\"></span></additional-info></span></div><div class=\"field-tooltip cardCvn\"><div class=\"tvg-tooltip-ctn error-tooltip\" ng-if=\"depositFrm.cardCvn.$invalid && (depositFrm.cardCvn.$touched || depositFrm.$submitted)\"><p qa-label=\"ccInvalidCvvErrorMessage\" ng-bind=\"'depositNewCardCvnInvalid' | CMSValue : null\"></p></div></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/card-number-input.html',
    "<div class=\"field\" qa-label=\"card-number\" ng-class=\"{focused: bankNameFocus && !(depositFrm.cardNumber.$invalid && (depositFrm.cardNumber.$touched || depositFrm.$submitted))}\"><div class=\"field-label\"><label qa-label=\"cardNumberLabel\" for=\"cardNumber\" ng-bind=\"'depositNewCardNumberLabel' | CMSValue : null\" ng-class=\"{ errorLabel: depositFrm.cardNumber.$invalid && (depositFrm.cardNumber.$touched || depositFrm.$submitted)}\"></label></div><div class=\"field-input\"><span class=\"input-container\"><input qa-label=\"cardNumberInput\" autocomplete=\"cc-number\" class=\"cardNumber\" id=\"cardNumber\" name=\"cardNumber\" ng-required=\"true\" maxlength=\"16\" minlength=\"16\" tvg-limit-to=\"16\" type=\"tel\" ng-focus=\"bankNameFocus = true\" ng-blur=\"events.FieldFilled(depositFrm.cardNumber); bankNameFocus = false\" ng-pattern=\"!data.editCardForm ? data.numberPattern : ''\" ng-keypress=\"events.onlyNumbers($event)\" ng-keyup=\"events.scrollOnkeyPress($event)\" ng-model=\"depositDataModel.cardNumber\" ng-model-options=\"{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }\" ng-readonly=\"data.editCardForm\" ng-disabled=\"data.editCardForm\"></span></div><div class=\"field-tooltip\"><div class=\"tvg-tooltip-ctn error-tooltip\" ng-if=\"depositFrm.cardNumber.$invalid && (depositFrm.cardNumber.$touched || depositFrm.$submitted)\"><p qa-label=\"invalidCardNumberMessage\" ng-bind=\"'depositNewCardNumberInvalid' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/card-type-selector.html',
    "<div class=\"field\" qa-label=\"card-type\"><div class=\"field-label\"><label qa-label=\"ccCardTypeLabel\" ng-bind=\"'depositNewCardTypeLabel' | CMSValue : null\"></label></div><div><span class=\"input-container minw270\"><toggle-options class=\"cards\"><button type=\"button\" class=\"card-type-button\" qa-label=\"type-{{card.name}}\" ng-repeat=\"card in data.selectedPayOption.subTypes track by $index\" ng-click=\"events.subTypeCardChanged(card)\" ng-class=\"{selected: depositDataModel.selectedCardType.name == card.name}\">{{card.name}}</button></toggle-options><span class=\"cc-img-cards\"><span class=\"visa-icon\"></span> <span class=\"mastercard-icon\"></span></span></span></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/card-verification-number.html',
    "<section-title title=\"{{('cvv-section-title' | CMSLabels: 'dmaDepositLabels')}}\" index=\"3\" qalabel=\"securityNumberTitle\"></section-title><div qa-label=\"securityNumberSection\" class=\"field cardCvn-ctn\"><div class=\"field-label\"><label qa-label=\"ccCvvLabel\" ng-class=\"{errorLabel: depositFrm.cardCvn.$invalid && (depositFrm.cardCvn.$touched || depositFrm.$submitted)}\" for=\"cardCvn\" ng-bind=\"'depositCardVerificationNumberLabel' | CMSValue : null\"></label></div><div class=\"field-input cardCvn\"><span class=\"input-container\"><input qa-label=\"ccCvvInput\" git id=\"cardCvn\" name=\"cardCvn\" ng-required=\"true\" maxlength=\"3\" minlength=\"3\" ng-pattern=\"data.numberPattern\" ng-blur=\"events.FieldFilled(depositFrm.cardCvn, 'added')\" ng-model=\"depositDataModel.cardSecurityNumber\" ng-model-options=\"{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }\" type=\"text\" pattern=\"\\d*\"></span><additional-info><span qa-label=\"ccCvvImage\" class=\"card-imgs cvv\"></span></additional-info></div><div class=\"field-tooltip cardCvn\"><div class=\"tvg-tooltip-ctn error-tooltip\" ng-if=\"depositFrm.cardCvn.$invalid && (depositFrm.cardCvn.$touched || depositFrm.$submitted)\"><p qa-label=\"ccInvalidCvvErrorMessage\" ng-bind=\"'depositNewCardCvnInvalid' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/deposit-amount-input.html',
    "<div class=\"dma-amount-ctn\" qa-label=\"deposit-amount\"><div class=\"dma-amount-table\"><div class=\"row\"><span class=\"cell w155\"><toggle-options><button ng-repeat=\"amountOption in data.availableAmountOptions track by $index\" ng-class=\"{selected: depositDataModel.amount == amountOption}\" class=\"amount-button\" type=\"button\" qa-label=\"amount-button-{{amountOption}}\" ng-click=\"events.handleDefaultAmountButtonClick(amountOption)\">${{amountOption}}</button></toggle-options></span><span class=\"cell minw30 amount-divider\">or <span class=\"amount-dollar-label\">$</span></span> <span class=\"cell align-right amount-input-ctn\"><input qa-label=\"amount-input\" money-formater class=\"amount\" name=\"amount\" type=\"number\" placeholder=\"Other amount\" ng-min=\"{{depositDataModel.min||0}}\" ng-max=\"{{events.getMax()}}\" num-length=\"5\" step=\"any\" ng-model=\"depositDataModel.amount\" ng-model-options=\"{ updateOn: 'default blur', debounce: { default: 1000, blur: 0 }}\" ng-required=\"true\" ng-change=\"events.handleAmountInputChange()\" ng-blur=\"events.handleAmountInputBlur(); inputIsNowFocused = false\" restrict-chars ng-focus=\"inputIsNowFocused = true\" ng-class=\"{\n" +
    "                        inputIsInvalid: $root.isFdrApp && depositFrm.amount.$invalid && depositFrm.$submitted,\n" +
    "                        inputIsFocused:\n" +
    "                            ($root.isFdrApp && !depositFrm.amount.$invalid && !!inputIsNowFocused)\n" +
    "                            || (!$depositFrm.amount.$dirty && !!inputIsNowFocused)\n" +
    "                    }\"></span></div></div><div class=\"row non-table amount-errors-ctn\"><div ng-init=\"events.sendOtherAmountErrorToGTM('Minimum', 'min')\" qa-label=\"error-minimum\" ng-if=\"depositFrm.amount.$error.min && depositDataModel.min > 0 && !depositDataModel.maxOverflow\" class=\"js-error-label error-label minimum\" ng-class=\"{invalidAmount: depositFrm.amount.$invalid && (depositFrm.amount.$touched || depositFrm.$submitted)}\">Minimum {{(depositDataModel.min) | currency}}</div><div ng-init=\"events.sendOtherAmountErrorToGTM('Maximum', 'max')\" qa-label=\"error-maximum\" ng-if=\"depositFrm.amount.$error.max && depositDataModel.max > 0 &&\n" +
    "            !depositDataModel.maxOverflow && !depositFrm.amount.$error.min && (!events.isSightlinePayment() || (events.isSightlinePayment() && !depositDataModel.sightlineNoBalance && !events.isSightlineInvalid()))\" class=\"js-error-label error-label maximum\" ng-class=\"{invalidAmount: depositFrm.amount.$invalid && (depositFrm.amount.$touched || depositFrm.$submitted)}\">Maximum {{(events.getMax()) | currency}}</div><div ng-init=\"events.sendOtherAmountErrorToGTM('Maximum amount reached')\" ng-if=\"depositFrm.amount.$error.max && ((depositDataModel.max == 0 || depositDataModel.maxOverflow) && !events.isSightlinePayment())\" qa-label=\"error-maximum-amount\" class=\"js-error-label error-label maximum\" ng-class=\"{invalidAmount: depositFrm.amount.$invalid && (depositFrm.amount.$touched || depositFrm.$submitted)}\">Maximum amount reached</div><div ng-init=\"events.sendOtherAmountErrorToGTM('Maximum amount reached')\" ng-if=\"(depositFrm.amount.$error.max || depositFrm.amount.$error.min) && events.isSightlinePayment() && (!!depositDataModel.sightlineNoBalance || events.isSightlineInvalid()) \" qa-label=\"error-maximum-amount\" class=\"js-error-label error-label maximum\" ng-class=\"{invalidAmount: depositFrm.amount.$invalid && (depositFrm.amount.$touched || depositFrm.$submitted)}\">The amount entered is greater than your available balance.</div><div ng-init=\"events.sendOtherAmountErrorToGTM('Required Field')\" qa-label=\"error-required\" ng-if=\"!depositFrm.amount.$error.max && !depositFrm.amount.$error.min && depositFrm.amount.$invalid && (depositFrm.amount.$touched || depositFrm.$submitted)\" class=\"js-error-label error-label\">Required Field</div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/deposit-total-cost.html',
    "<label ng-if=\"data.fee.calculatingFees && !$root.isFdrApp\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label> <label ng-if=\"data.retryFetchingFees && !$root.isFdrApp\" ng-click=\"events.updateTotalCosts(depositDataModel, true)\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees-error' | CMSLabels: 'dmaDepositLabels' | trust\"></label><ul qa-label=\"deposit-summary\" class=\"deposit__summary\"><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('deposit-summary-amount' | CMSLabels: 'dmaDepositLabels') + ' ' +\n" +
    "                      ((data.fee.netAmount | currency: '$') || '$--') | trust )\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-fee\" ng-bind-html=\"(('deposit-summary-fee' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                      ((data.fee.fee | currency: '$') || '$--') | trust ) + ('</span>')\" ng-class=\"{ 'red bold': displays.sightlineBalanceExceeded()}\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-discount\" ng-bind-html=\"(('deposit-summary-discount' | CMSLabels: 'dmaDepositLabels' | trust) + ' ' +\n" +
    "                      ((data.fee.feeDiscount | currency: '$') || '$--') | trust )\"></li><li><strong qa-label=\"deposit-summary-total\" ng-bind-html=\"(('deposit-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                              ((data.fee.transactionTotal | currency: '$') || '$--') | trust ) + ('</span>')\" ng-class=\"{ red: displays.sightlineBalanceExceeded()}\"></strong></li></ul><label ng-if=\"data.fee.calculatingFees && $root.isFdrApp\" class=\"activity-info fee fee-calculating\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label> <label ng-if=\"data.retryFetchingFees && $root.isFdrApp\" ng-click=\"events.updateTotalCosts(depositDataModel, true)\" class=\"activity-info fee fee-error\" ng-bind-html=\"'deposit-summary-calculation-fees-error' | CMSLabels: 'dmaDepositLabels' | trust\"></label>"
  );


  $templateCache.put('src/templates/deposit/fields/deposit-type-selector.html',
    "<deposit-options-container class=\"dma-nav dma-nav-tabs\" qa-label=\"deposit-options\"><deposit-option ng-repeat=\"option in data.depositOptions track by $index\" ng-click=\"events.selectOption(option)\" ng-class=\"{selected:data.selectedPayOption.ftype === option.ftype}\"><span><p ng-class=\"{bold:data.selectedPayOption.ftype === option.ftype}\" qa-label=\"{{::option.ftype}}\">{{option.name}}</p></span></deposit-option></deposit-options-container>"
  );


  $templateCache.put('src/templates/deposit/fields/driver-license-number.html',
    "<div class=\"field\" qa-label=\"driver-license-number\" ng-class=\"{focused: driverLicenceNumber && !(depositFrm.licenseNumber.$invalid && (depositFrm.licenseNumber.$touched || depositFrm.$submitted))}\"><div class=\"field-label\"><label qa-label=\"driverLicenceLabel\" for=\"licenseNumber\" ng-bind=\"'depositDriverLicenseNumberLabel' | CMSValue : null\" ng-class=\"{errorLabel: depositFrm.licenseNumber.$invalid && (depositFrm.licenseNumber.$touched || depositFrm.$submitted)}\"></label></div><div class=\"field-input\"><span class=\"input-container\"><!-- Avoid Chrome autofill --> <input name=\"fakeusername\" type=\"text\" style=\"position: absolute; left: -9999px;\" tabindex=\"-1\"> <input qa-label=\"driverLicenceInput\" name=\"licenseNumber\" id=\"licenseNumber\" ng-model=\"depositDataModel.licenseNumber\" ng-focus=\"driverLicenceNumber = true\" ng-blur=\"events.completedFieldAndBlursAway('Driver License Number', depositFrm.licenseNumber); driverLicenceNumber = false\" pattern=\"^[a-zA-Z0-9]+(-?[a-zA-Z0-9])*$\" ng-model-options=\"{ updateOn: 'blur', debounce: { 'blur': 0 } }\" ng-required=\"true\" minlength=\"3\" autocomplete=\"off\" type=\"text\"></span></div><div class=\"field-tooltip\"><div class=\"tvg-tooltip-ctn error-tooltip\" qa-label=\"invalidLicenseNr\" ng-if=\"depositFrm.licenseNumber.$invalid && (depositFrm.licenseNumber.$touched || depositFrm.$submitted)\" ng-init=\"events.newAccountFieldError('Driver License Number', 'depositDriverLicenseNumberInvalid' | CMSValue)\"><p ng-bind=\"'depositDriverLicenseNumberInvalid' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/driver-license-state.html',
    "<div class=\"field\" qa-label=\"driver-license-state\"><div class=\"field-label\"><label qa-label=\"driverLicenceStateLabel\" for=\"licenseState\" ng-bind=\"'depositDriverLicenseStateLabel' | CMSValue : null\" ng-class=\"{errorLabel: depositFrm.licenseState.$invalid && depositFrm.$submitted, focused: stateSelectedOptionFocused}\"></label></div><div class=\"field-input\"><span class=\"input-container\"><select-container qa-label=\"dlStateContainer\" class=\"others\" ng-class=\"{'focused': stateSelectedOptionFocused, 'select-error': depositFrm.$submitted && depositFrm.licenseState.$invalid}\"><select qa-label=\"driverLicenceStateSelect\" class=\"card\" id=\"licenseState\" name=\"licenseState\" ng-model=\"depositDataModel.stateSelectedOption\" ng-focus=\"stateSelectedOptionFocused = true\" ng-blur=\"stateSelectedOptionFocused = false\" ng-options=\"state.name for state in data.states\" ng-required=\"true\"><option value=\"\" disabled=\"disabled\">-- Please select a state --</option></select> <span qa-label=\"driverLicenceStateInputContent\" ng-bind=\"depositDataModel.stateSelectedOption.name || ('depositDriverLicenseStateLabel' | CMSValue : null)\"></span></select-container></span></div><div class=\"field-tooltip\"><div class=\"tvg-tooltip-ctn error-tooltip\" qa-label=\"invalidLicenseState\" ng-if=\"depositFrm.licenseState.$invalid && depositFrm.$submitted\" ng-init=\"events.newAccountFieldError('Driver License State', 'depositDriverLicenseInvalid' | CMSValue)\"><p ng-bind=\"'depositDriverLicenseStateInvalid' | CMSValue : null\"></p></div></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/quick-deposit-default.html',
    "<div class=\"field\" qa-label=\"quick-deposit-default\"><div class=\"field-label\"><label for=\"quickDefaultMethod\" qa-label=\"quick-deposit-default-label\" ng-bind=\"'depositDataModelDepositDefault' | CMSValue : null\"></label></div><div class=\"field-input quick-default-select\"><span class=\"input-container\"><select-container class=\"deposits-default-payment-container\"><select qa-label=\"quick-deposit-default-select\" class=\"deposits-default-payment\" id=\"quickDefaultMethod\" name=\"quickDefaultMethod\" ng-model=\"depositDataModel.isDefaultPayment\" ng-options=\"options.value as options.name for options in data.defaultPaymentValues\" ng-change=\"events.defaultPaymentChanged(depositDataModel.isDefaultPayment)\"></select> <span ng-bind=\"depositDataModel.isDefaultPayment ? 'Yes' : 'No'\"></span></select-container></span></div></div>"
  );


  $templateCache.put('src/templates/deposit/fields/quick-deposit-selector.html',
    "<div class=\"field\"><span class=\"input-container quick-deposit-selector\"><ul class=\"deposit-card-options quick-deposit-options\" qa-label=\"quick-deposit-options\"><li class=\"quick-deposit-options--title\" ng-repeat=\"(key, card) in data.depositOptions | orderBy:['isDefaultPayment', '-lastUsedDate'] track by $index\" ng-class=\"{'sightline-card-ctn': key === 'TVG Prepaid Card' && data.depositOptions.length > 1 }\" ng-if=\"(card.ftype === 'APPL' && displays.isApplePayInQuickDepositEnabled()) || card.ftype !== 'APPL'\" qa-label=\"payment-type-cards-list\"><span ng-bind=\"key\"></span><div class=\"card\" qa-label=\"quick-deposit-card\"><label ng-class=\"{\n" +
    "                                        'disabled': events.isSLNDeclinedCard(card),\n" +
    "                                        'expired': card.isExpired, 'active': depositDataModel.selectedOnFile === card ||\n" +
    "                                        ((card.ftype === 'IBC'|| card.ftype === 'ACH') && depositDataModel.selectedOnFile.achId === card.achId) ||\n" +
    "                                        ((card.ftype === 'CC') && depositDataModel.selectedOnFile.id === card.id), 'option-with-image': displays.getCardImage(card) !== '' }\"><div class=\"card-icon\" ng-class=\"displays.getCardImage(card)\"></div><div ng-if=\"card.ftype === 'APPL'\" class=\"card-icon\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 165.5 106\"><defs/><path d=\"M150.7 0H13.1a71 71 0 00-4.5.3A10.5 10.5 0 003 3.1 10 10 0 00.3 8.6 20.6 20.6 0 000 13v79.7a70.3 70.3 0 00.3 4.6 10.5 10.5 0 002.8 5.5 9.9 9.9 0 005.5 2.8 21 21 0 004.5.3H152.4a79.7 79.7 0 004.5-.3 10.5 10.5 0 005.5-2.8 10 10 0 002.8-5.5 20.6 20.6 0 00.3-4.6v-78-1.7a63 63 0 00-.3-4.5 10.4 10.4 0 00-2.8-5.5A10 10 0 00157 .3a20.8 20.8 0 00-4.5-.3h-1.7z\"/><path fill=\"#FFF\" d=\"M150.7 3.5h1.7a67.4 67.4 0 014 .3 6.4 6.4 0 015.4 5.4 17.6 17.6 0 01.2 4v79.6a59.7 59.7 0 01-.3 4 6.9 6.9 0 01-1.8 3.6 6.4 6.4 0 01-3.6 1.8 18 18 0 01-4 .2H13.2a75 75 0 01-3.9-.2 7 7 0 01-3.6-1.8 6.4 6.4 0 01-1.8-3.6 17.5 17.5 0 01-.3-4V13.1a66.6 66.6 0 01.3-3.9 7 7 0 011.8-3.6 6.4 6.4 0 013.6-1.8 17.6 17.6 0 014-.3h137.5\"/><path d=\"M45.2 35.6a9.2 9.2 0 002.1-6.5 9.2 9.2 0 00-8.2 9.4c2.3.2 4.6-1.1 6-2.9M47.3 39c-3.4-.2-6.3 1.9-7.9 1.9-1.6 0-4-1.8-6.8-1.8a10 10 0 00-8.4 5.2c-3.7 6.2-1 15.5 2.5 20.6 1.8 2.6 3.8 5.3 6.6 5.2 2.5 0 3.5-1.6 6.7-1.6 3.1 0 4 1.6 6.7 1.6 2.9 0 4.6-2.5 6.3-5 2-3 2.8-5.7 2.9-5.9 0 0-5.5-2-5.5-8.3 0-5.2 4.2-7.7 4.4-7.8a9.7 9.7 0 00-7.5-4.1M76.7 32c7.4 0 12.5 5 12.5 12.4S84 56.9 76.5 56.9h-8v13h-6v-38h14.2zm-8.3 20h6.8c5 0 8-2.8 8-7.6s-3-7.5-8-7.5h-6.8v15zM90.7 62c0-4.9 3.7-7.8 10.3-8.2l7.6-.4v-2.2c0-3-2.1-4.9-5.6-4.9-3.3 0-5.3 1.6-5.8 4h-5.4c.4-5 4.6-8.6 11.4-8.6 6.7 0 11 3.6 11 9v19.1h-5.4v-4.5h-.2c-1.6 3-5 5-8.7 5-5.4 0-9.2-3.4-9.2-8.3zm17.9-2.5v-2.2l-6.8.4c-3.4.3-5.3 1.8-5.3 4.1 0 2.4 2 4 5 4 4 0 7-2.7 7-6.3zM119.3 80v-4.6l1.9.1c2.6 0 4-1.1 4.9-4l.5-1.6-10-27.7h6.2l7 22.5 7-22.5h6l-10.3 29c-2.4 6.8-5.1 9-10.8 9l-2.4-.2z\"/></svg></div><div ng-class=\"(displays.getCardImage(card) !== '' || card.ftype === 'APPL') && 'card-data-container'\"><strong ng-if=\"card.ftype === 'APPL'\" class=\"center-applepay\" qa-label=\"applepay-card-type\" ng-bind=\"('quickDepositName' | CMSLabels: 'applepayLabels' | trust)\"></strong> <strong ng-if=\"card.ftype === 'CC'\" qa-label=\"cc-card-type\" ng-bind=\"::card.typeName + ' Card'\"></strong> <strong ng-if=\"card.ftype === 'IBC' || card.ftype === 'ACH'\" qa-label=\"bc-bank-name\" ng-bind=\"::$root.isFdrApp ? card.bankName.toLowerCase() : card.bankName\"></strong> <strong ng-if=\"card.ftype === 'SLN'\" qa-label=\"slp-card-label\" ng-bind=\"::displays.getSLPLabel(card)\"></strong><div ng-if=\"card.ftype === 'ACH' || card.ftype === 'IBC'\" qa-label=\"bc-bank-acc-number\">****{{(events.slicedCard(card.bankAccNumber))}}</div><div ng-if=\"card.ftype === 'CC' || card.ftype === 'SLN'\"><span ng-if=\"card.isExpired\" class=\"expired-card-label\" qa-label=\"cc-expired-label\">{{'expired-card' | CMSLabels: 'dmaDepositLabels'}} </span><span ng-bind=\"::card.cardNumberExt\" qa-label=\"cc-card-number\"></span> (<span ng-bind=\"::card.expirationDate\" qa-label=\"cc-card-date\"></span>) <span ng-if=\"card.ftype === 'SLN'\" qa-label=\"cc-card-date\">through TVG Pre Paid Card</span></div><input type=\"radio\" ng-if=\"!events.isSLNDeclinedCard(card)\" ng-model=\"depositDataModel.selectedOnFile\" ng-click=\"events.selectAccount(card)\" ng-change=\"events.selectOnFileChanged(depositDataModel.selectedOnFile)\" ng-value=\"card\" qa-label=\"card-radio\"></div></label></div></li><li class=\"card paypal-add-funds\" ng-if=\"displays.isPaypalInQuickDepositEnabled()\" qa-label=\"quick-deposit-paypal-card\"><label qa-label=\"paypal-add-funds\" ng-click=\"events.addQuickDepositFunds('PAY')\"><div class=\"card-icon paypal-card\" ng-if=\"displays.getCardImage('PAYPAL') !== ''\"></div><div ng-class=\"displays.getCardImage('PAYPAL') !== '' && 'card-data-container'\"><strong>PayPal</strong><div>Deposit With PayPal</div></div></label></li></ul></span></div>"
  );


  $templateCache.put('src/templates/deposit/quick-deposit.html',
    "<div class=\"tvg-deposit quick-deposit\" ng-controller=\"DepositController\" ng-init=\"data.isQuickDeposit=true\" ng-class=\"{loading: data.loading}\" qa-label=\"quick-deposit-modal\"><div class=\"alert-box error clearfix\" ng-if=\"events.anyCardsExpired()\" qa-label=\"expiredCardMessage\"><i class=\"tvg-icon-error\"></i><div class=\"content\" qa-label=\"credit-card-expired-message\">It seems your card has expired please update your credit card info.</div></div><div class=\"alert-box warning clearfix\" ng-if=\"displays.isDepositLoaded() && events.allCardsDeclined()\" qa-label=\"declinedCardMessage\"><i class=\"tvg-icon-warning\"></i><div class=\"content ng-scope\" qa-label=\"credit-card-declined-message\"><!-- Show only in betSlip --><p ng-if=\"events.isBetslip() || events.isIos()\" class=\"d-inline\" ng-bind=\"('betSlipAllCardDeclinedWarning' | CMSLabels: 'cardErrorRedirect' | trust)\" qa-label=\"credit-card-declined-message-body\"></p><!-- Default template--><p ng-if=\"!events.isBetslip() && !events.isIos()\" class=\"d-inline\" ng-bind=\"('dmaAllCardDeclinedWarning' | CMSLabels: 'cardErrorRedirect' | trust)\" qa-label=\"credit-card-declined-message-body\"></p><p ng-if=\"!events.isBetslip() && !events.isIos()\" class=\"d-inline fake-link\" ng-click=\"events.goToFullDeposit()\" ng-bind=\"('dmaAllCardDeclinedWarningLink' | CMSLabels: 'cardErrorRedirect' | trust)\" qa-label=\"credit-card-declined-message-link\"></p></div></div><dw-info-dialog ng-bind=\"'depositInitialDataErrorMessage' | CMSValue : null\" ng-if=\"!data.loading && (displays.isAllRequestCardsFailed() || !displays.isDepositLoaded()) && !$root.isFdrApp\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\" qa-label=\"quick-deposit-error-message\"></dw-info-dialog><dw-info-dialog-fdr ng-if=\"!data.loading && (displays.isAllRequestCardsFailed() || !displays.isDepositLoaded()) && $root.isFdrApp\" heading-text=\"Something went wrong\" button-text=\"Refresh Page\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\" button-action=\"location.reload()\">{{'depositInitialDataErrorMessage' | CMSValue : null}}</dw-info-dialog-fdr><div id=\"inject-no-payment-methods\" ng-if=\"!$root.isFdrApp && !data.depositOptions.length && !events.isBetslip() && !events.isIos() && !displays.isAllRequestCardsFailed() && displays.isDMAInjectNoPaymentQuickDepositEnabled()\"></div><dw-info-dialog ng-if=\"!$root.isFdrApp && displays.isDepositLoaded() && !data.depositOptions.length && !events.isBetslip() && !events.isIos() && !displays.isAllRequestCardsFailed() && !displays.isDMAInjectNoPaymentQuickDepositEnabled()\" action=\"events.goToFullDeposit\" action-text=\"Add New Deposit Options\" qa-label=\"quick-deposit-no-options\">You Don't Have Any Deposit Options On File.</dw-info-dialog><dw-info-dialog-fdr ng-if=\"$root.isFdrApp && displays.isDepositLoaded() && !data.depositOptions.length && !events.isBetslip() && !events.isIos() && !displays.isAllRequestCardsFailed()\" button-action=\"events.goToFullDeposit\" heading-text=\"No Results\" button-text=\"Add New Deposit Options\" qa-label=\"quick-deposit-no-options\" class=\"quick-deposit-no-options\">You don't have any deposit options on file.</dw-info-dialog-fdr><dw-info-dialog ng-if=\"displays.isDepositLoaded() && !data.depositOptions.length && (events.isBetslip() || events.isIos()) && !displays.isAllRequestCardsFailed()\" qa-label=\"quick-deposit-no-options\">You Don't Have Any Deposit Options On File. {{'quickDepositNoRedirect' | CMSValue : null}}</dw-info-dialog><form ng-show=\"displays.isDepositLoaded() && data.depositOptions.length\" class=\"deposit-form\" name=\"depositFrm\" ng-submit=\"depositDataModel.selectedOnFile.ftype ==='APPL' ?\n" +
    "            events.onApplePayDeposit() :\n" +
    "            events.makeDeposit(depositFrm)\" ng-class=\"{loading: (data.makingDeposit || data.fetchingInfo || data.activePoller)}\" novalidate qa-label=\"quick-deposit-form\"><section-title index=\"1\" title=\"{{'deposit-amount-title' | CMSLabels: 'dmaDepositLabels'}}\" qalabel=\"depositAmountTitle\" class=\"first-title\"></section-title><deposit-amount-input></deposit-amount-input><div class=\"alert-box warning clearfix\" ng-if=\"displays.isBetcashLimitExceeded()\"><i class=\"tvg-icon-error\"></i><div class=\"content\" qa-label=\"no-further-deposits-message\">No further BetCash deposits are permitted for this period.</div></div><div class=\"link-text\" ng-click=\"events.goToFullDeposit()\" ng-if=\"displays.isAddNewDepositOptionsVisible()\" qa-label=\"link-to-deposits\">Add New Deposit Options</div><div ng-if=\"depositDataModel.isAvailable != false\"><div ng-if=\"depositDataModel.isPending == true\"><dw-info-dialog ng-bind=\"'depositBetCashPendingMessageText' | CMSValue : null\" live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\" qa-label=\"betcash-pending-message\"></dw-info-dialog></div><section-title index=\"2\" title=\"{{'select-quick-deposit-account-title' | CMSLabels: 'dmaDepositLabels'}}\" qalabel=\"quickDepositAccountTitle\" class=\"first-title\"></section-title><quick-deposit-selector></quick-deposit-selector><quick-deposit-default></quick-deposit-default><div ng-if=\"data.showAchDepositLimitExceeded\"><dw-info-dialog ng-bind=\"'depositsBetcashPeriodLimitExceeded' | CMSValue : null\" live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\" qa-label=\"betcash-period-exceed-message\"></dw-info-dialog></div><div ng-if=\"!data.showAchDepositLimitExceeded\"><div ng-repeat=\"field in data.forms[depositDataModel.selectedOnFile.ftype || depositDataModel.selectedOnFile]\"><div ng-include=\"'src/templates/deposit/fields/' + field + '.html'\" data-qa-label=\"{{field + '-section'}}\" ng-class=\"{cardCvv: field === 'card-verification-number'}\"></div></div><div class=\"sightline sightline--quick-deposit clearfix\" ng-if=\"depositDataModel.selectedOnFile.ftype === 'SLN'\"><div class=\"sightline--quick-deposit__error alert-box error clearfix\" ng-if=\"quickDepositSightlineError\"><i class=\"tvg-icon-error\"></i><div class=\"content\" qa-label=\"slp-error-message\">We're having some troubles with TVG Pre Paid Card right now. Please try again.</div></div></div><section-title ng-if=\"!$root.isFdrApp\" index=\"{{ depositDataModel.selectedOnFile.ftype === 'CC' || depositDataModel.selectedCardType.type === 'SLN'? '4' : '3' }}\" qalabel=\"reviewTitle\" title=\"{{'review-and-authorize-title' | CMSLabels: 'dmaDepositLabels'}}\"></section-title><deposit-total-cost ng-if=\"!data.calculatingFees && depositDataModel.isPending != true && !quickDepositSightlineError && !$root.isFdrApp\"></deposit-total-cost><div class=\"field l100 vertical-spacing\" ng-if=\"depositDataModel.isAvailable != false && depositDataModel.isPending != true && depositDataModel.selectedOnFile.ftype !=='APPL'\"><button class=\"submit yellow add-funds\" ng-class=\"{disabled: depositFrm.amount.$invalid}\" ng-disabled=\"data.disabledCard || displays.allCardsDeclined() || displays.disableQuickDepositButton() || events.anyCardsExpired() || displays.isBetcashLimitExceeded() || data.responsibleGamingDelay\" type=\"submit\" qa-label=\"authorize-button\"><i class=\"tvg-icon tvg-icon-lock\"></i> <strong>{{'depositExecuteButton' | CMSValue : null}}</strong></button></div><div class=\"field l100 vertical-spacing\" ng-if=\"depositDataModel.selectedOnFile.ftype ==='APPL'\"><button qa-label=\"applepayButton\" type=\"submit\" ng-disabled=\"events.shouldDisableApplePayButton()\" class=\"applepay-deposit__button pa_0\" qa-label=\"authorize-button\" ng-bind-html=\"(('depositButton' | CMSLabels: 'applepayLabels' | trust))\"></button></div></div></div></form><div ng-if=\"displays.isDepositLoaded() && depositDataModel.isAvailable == false\"><dw-info-dialog ng-bind=\"'depositsBetcashPeriodLimitExceeded' | CMSValue : null\" live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\" qa-label=\"betcash-period-exceed-message\"></dw-info-dialog></div></div>"
  );


  $templateCache.put('src/templates/deposit/types/payNearMe/locations-modal.html',
    "<tvg-dma-modal class=\"paynearme__modal\" title=\"Nearest Location For Cash Deposit\" body=\"{{locationsTemplate}}\" close=\"closeLocationsModal()\"></tvg-dma-modal>"
  );


  $templateCache.put('src/templates/deposit/types/payNearMe/paynearme.html',
    "<div qa-label=\"pnm-container\" class=\"payNearMe__container\" ng-controller=\"PayNearMeCtrl as pnmCtrl\" ng-class=\"{'loading' : data.loading}\"><div class=\"before-notification\"></div><div ng-if=\"!data.showPnmIframe && !data.loading\"><section-title qalabel=\"pnmFundTitle\" title=\"Fund your account with a cash deposit at 7-Eleven or Family Dollar!\" index=\"1\"></section-title><p qa-label=\"pnmDisclaimer\" class=\"paynearme__container__info\" ng-bind-html=\"'payNearMeText' | CMSLabels: 'dmaPayNearMeLabels' | trust\"></p><p qa-label=\"pnmFaqsLabel\">Click below to get your PayNearMe PayCode. For more information, check out our <a qa-label=\"pnmFaqsLink\" ng-click=\"events.toggleFaq()\" class=\"colored__label\">PayNearMe FAQ.</a></p><button qa-label=\"pnmEnrollButton\" class=\"submit\" type=\"button\" ng-click=\"events.createPayNearMeId()\">Get PayNearMe PayCode</button><p qa-label=\"pnmNotAuthorizedStates\" ng-bind-html=\"'unauthorizedStates' | CMSLabels: 'dmaPayNearMeLabels' | trust\"></p><div qa-label=\"pnmLogo\" class=\"container-fluid paynearme__logos\"><img ng-src=\"{{data.payNearMeLogoUrl}}\"><div class=\"right__container\"><span qa-label=\"pnmFundYourAccLabel\">Fund your account with cash at</span><div class=\"paynearme__stores\"><img qa-label=\"pnm711Logo\" ng-src=\"{{data.sevenElevenLogoUrl}}\"> <span>&</span> <img qa-label=\"pnmFamilyDollarLogo\" ng-src=\"{{data.familyDollarLogoUrl}}\"></div></div></div></div><div ng-if=\"data.showPnmIframe\"><iframe qa-label=\"pnmIframe\" class=\"iframe__container\" ng-src=\"{{data.orderTrackingUrl}}\"></iframe></div></div>"
  );


  $templateCache.put('src/templates/deposit/types/sightline/enrollment.html',
    "<div class=\"sightline-enrollment__content\" ng-class=\"{'loading' : data.sightlineLoading}\"><section ng-show=\"!data.sightlineLoading\"><div class=\"alert-box blue clearfix no-padding\"><span class=\"bold show-mobile title\">How does it work ?</span> <i class=\"tvg-icon-info\"></i><div qa-label=\"sightlineEnrollmentTutorial\" class=\"content\" ng-bind-html=\"('sightlineEnrollmentTutorial'| CMSValue : null) | trust\"></div></div><div class=\"sightline-enrollment__faq tvg-icon-arrow-right\" ng-click=\"$root.isFdrApp ? events.openModals('sightlineFaqTitle', 'sightlineFaqTemplate') : null\"><span qa-label=\"sightlineFaq\">Please refer to the <a qa-label=\"sightlineFaqLink\" href=\"\" ng-click=\"!$root.isFdrApp ? events.openModals('sightlineFaqTitle', 'sightlineFaqTemplate') : null\">FAQ </a>if you have any questions about your Pre Paid Card.</span></div><div class=\"sightline-enrollment__block\"><h2 qa-label=\"sightlineHeader\" class=\"sightline-enrollment__title\">Register</h2><div class=\"flex-center\"><label qa-label=\"sightlineTermsAndCondsLabel\" class=\"checkbox blue\"><input qa-label=\"sightline-accept-terms\" type=\"checkbox\" id=\"sightline-accepted-terms\" name=\"sightline-accepted-terms\" ng-required=\"true\" ng-attr-tabindex=\"1\" ng-model=\"data.areTermsAccepted\" ng-change=\"events.toggleSightlineTerms(data.areTermsAccepted)\"> <span><i qa-label=\"sightlineCheckbox\" class=\"tvg-icon-check blue\"></i></span></label> <label for=\"sightline-accepted-terms\" class=\"inline-checkbox\"><b ng-if=\"!$root.isFdrApp\">I agree with the TVG Pre Paid Card</b> <b ng-if=\"$root.isFdrApp\">I agree with the FanDuel Pre Paid Card</b> <a qa-label=\"sightlineTerms\" target=\"_blank\" href=\"https://betfair.mycardplace.com/cholder/showContent.action?page=TVGTERMS\" class=\"external-link\">Terms and Conditions </a><b>and</b> <a qa-label=\"sightlinePrivacy\" href=\"\" class=\"external-link\" ng-click=\"events.openModals('sightlinePrivacyTitle', 'sightlinePrivacyTemplate')\">Privacy Disclosure </a>.</label></div></div><button qa-label=\"sightlineEnrollButton\" type=\"button\" class=\"btn submit-btn\" ng-disabled=\"!data.areTermsAccepted || data.isEnrollingCard\" ng-click=\"events.enrolCard()\"><i class=\"tvg-icon tvg-icon-lock\"></i> Enroll</button></section></div>"
  );


  $templateCache.put('src/templates/deposit/types/sightline/sightline.html',
    "<section qa-label=\"sln-container\" class=\"sightline_ctn\" ng-class=\"{'sightline_ctn--loading': data.sightlineLoading, 'loading': data.sightlineLoading}\"><section class=\"sightline-enrollment__content\" ng-if=\"firstTimeAddFunds\"><div qa-label=\"alert-box\" class=\"alert-box clearfix success\"><i class=\"tvg-icon-success\"></i><div qa-label=\"alert-box-content\" class=\"content\"><span class=\"bold\">Congratulations!</span> Your Pre Paid account has been approved!</div></div><h2 qa-label=\"sightlineHeader\" class=\"sightline-enrollment__title\">Fund your Card</h2></section><div class=\"sightline__newuser\" ng-if=\"isNewUser === true || isAddingFunds\"><iframe qa-label=\"slnIframe\" ng-src=\"\" ng-if=\"isAddingFunds\" name=\"sightline__iframe\" ng-show=\"loadSightlineiFrame\" class=\"sightline__iframe\"></iframe><sightline-enrollment ng-controller=\"SightlineController\" qa-label=\"sln-api-enrollment\" ng-if=\"!isAddingFunds\" ng-class=\"{'loading': data.isEnrollingCard}\"></sightline-enrollment></div><div class=\"sightline_ctn__content\" ng-if=\"isNewUser === false && !isAddingFunds\"><div class=\"sightline\"><section-title qalabel=\"prePaidCardTitle\" class=\"first-title\" title=\"Pre Paid card funds\" index=\"1\"></section-title><div class=\"flex align-center balance-wrapper\"><button qa-label=\"slnAddFunds\" type=\"button\" class=\"sightline__add-funds button__add-funds\" ng-click=\"events.addSightlineFunds()\">Fund Card</button><p class=\"sightline-balance\" qa-label=\"slnBalanceLabel\">Pre Paid Card balance: <span qa-label=\"slnBalance\" class=\"bold balance\">${{sightlineBalance}}</span></p></div></div><section-title qalabel=\"depositAmountTitle\" title=\"{{'deposit-amount-title' | CMSLabels: 'dmaDepositLabels'}}\" index=\"2\"></section-title><deposit-amount-input qa-label=\"deposit-amount-input\" ng-if=\"(depositDataModel.isAvailable != false) || events.existsOnFile()\"></deposit-amount-input><section-title qalabel=\"reviewTitle\" title=\"Review and Authorize\" index=\"3\"></section-title><deposit-total-cost></deposit-total-cost><div ng-if=\"depositDataModel.isPending != true\" class=\"field\"><button qa-label=\"submit-deposit\" class=\"submit authorize-deposit\" ng-disabled=\"data.makingDeposit || data.activePoller || data.responsibleGamingDelay\" type=\"submit\"><i class=\"tvg-icon tvg-icon-lock\"></i> <strong>{{'depositExecuteButton' | CMSValue : null}}</strong></button><div ng-if=\"!notifyErrors\" ng-show=\"data.showInvalidFormMessage\" ng-class=\"{show: data.showInvalidFormMessage}\" class=\"js-error-label error-label fade-msg text-centered tvg-tooltip-ctn general-form-error\"><p qa-label=\"incompleteFormErrorMessage\" ng-bind-html=\"'deposit-authorize-error-message' | CMSLabels: 'dmaDepositLabels' | trust\"></p></div></div></div></section>"
  );


  $templateCache.put('src/templates/deposit/utils/modal-content-directive.html',
    "<div class=\"modal-header\" qa-label=\"deposits-modal-header\"><span qa-label=\"deposits-modal-title\" class=\"modal-title\" ng-bind=\"::title\"></span> <i qa-label=\"deposits-modal-close\" class=\"icons__item\" ng-click=\"close()\">&#215;</i></div><div qa-label=\"deposits-modal-content\" class=\"modal-body\" ng-bind-html=\"::body | trust\"></div>"
  );


  $templateCache.put('src/templates/additional-info.html',
    "<span class=\"question-mark\" click-outside=\"events.closeInfo()\" ng-click=\"events.toggleInfo()\" qa-label=\"helperButton\"></span><div class=\"additionalContainer\" ng-class=\"{expanded: data.infoState}\"><div class=\"info-container\"><div class=\"additionalMessage\"><div ng-transclude></div></div></div></div>"
  );


  $templateCache.put('src/templates/banner.html',
    "<div qa-label=\"alert-box\" class=\"alert-box clearfix\" ng-class=\"vm.type\"><i class=\"tvg-icon-{{vm.type}}\"></i><alert-content qa-label=\"alert-box-content\" class=\"content\"></alert-content><div class=\"btn-group\" ng-if=\"vm.isConfirmBanner()\"><button class=\"btn btn-sm btn-primary ok\" ng-click=\"vm.close(true)\">OK</button> <button class=\"btn btn-sm btn-default cancel\" ng-click=\"vm.close()\">Cancel</button></div><i qa-label=\"alert-box-close\" class=\"tvg-icon-times close-button\" ng-click=\"vm.close()\"></i></div>"
  );


  $templateCache.put('src/templates/ccp_sightline_redirect.html',
    "<div class=\"tvg-dialog dma-redesign sightline-redirect-modal\"><div class=\"tvg-dialog-dma-redesign-header\"><span class=\"tvg-dialog-dma-redesign-title\" style=\"text-transform: uppercase; display: block; margin-top: 3px;\" ng-bind=\"('sightlineCcpRedirectTitle' | CMSLabels: 'dmaManagementLabels' | trust)\" data-qa-label=\"slpRedirectTitle\"></span> <a href class=\"tvg-dialog-dma-redesign-close-icon\" ng-click=\"$close()\" data-qa-label=\"slpRedirectClose\"><i class=\"tvg-icon-close\"></i></a></div><div class=\"tvg-dialog-dma-redesign-body\" style=\"padding: 16px;\"><div style=\"margin-bottom: 20px\"><p style=\"display: inline\" ng-bind=\"('sightlineCcpRedirectText' | CMSLabels: 'dmaManagementLabels' | trust)\" data-qa-label=\"slpRedirectInfo\"></p>.</div><div class=\"sightline-enrollment__content\" style=\"margin-bottom: 10px\"><label class=\"checkbox blue\" style=\"line-height: 14px; margin-right: 10px;\"><input type=\"checkbox\" style=\"margin-right: 10px\" id=\"sightline-redirect-terms\" name=\"sightline-redirect-terms\" ng-required=\"true\" ng-attr-tabindex=\"1\" ng-model=\"areTermsAccepted\" data-qa-label=\"slpRedirectCheckbox\"> <span><i class=\"tvg-icon-check blue\"></i></span></label> <label for=\"sightline-redirect-terms\" class=\"inline-checkbox\" style=\"line-height: 14px\" data-qa-label=\"slpRedirectTermsText\"><span ng-bind=\"('sightlineCcpRedirectTerms' | CMSLabels: 'dmaManagementLabels' | trust)\"></span> <button ng-click=\"openTermsConditions($event)\" class=\"external-link link\" data-qa-label=\"slpRedirectTermsLink\">Terms and Conditions</button> <span>and</span> <button ng-click=\"openPrivacyPolicy($event)\" class=\"link\" data-qa-label=\"slpRedirectPrivacyButton\">Privacy Disclosure</button></label></div><div><button class=\"proceed-btn\" ng-disabled=\"!areTermsAccepted\" ng-click=\"proceed($close)\" data-qa-label=\"slpRedirectConfirmButton\" ng-bind=\"('sightlineCcpRedirectButtonLabel' | CMSLabels: 'dmaManagementLabels' | trust)\"></button></div><div qa-label=\"slpRedirectFees\" class=\"tvg-dialog-dma-redesign-fees\" ng-bind-html=\"'sightlineCcpRedirectFees'| CMSValue : null\"></div></div></div>"
  );


  $templateCache.put('src/templates/ccp_visa_sightline_redirect.html',
    "<div class=\"tvg-dialog dma-redesign sightline-redirect-modal\" style=\"max-width: 390px !important;\"><div class=\"tvg-dialog-dma-redesign-header\"><span class=\"tvg-dialog-dma-redesign-title\" style=\"text-transform: uppercase; display: block; margin-top: 3px;\" ng-bind=\"('modalTitle' | CMSLabels: 'cardErrorRedirect' | trust)\" data-qa-label=\"slpVisaRedirectTitle\"></span> <a href class=\"tvg-dialog-dma-redesign-close-icon\" ng-click=\"$close()\" data-qa-label=\"slpRedirectClose\"><i class=\"tvg-icon-close\"></i></a></div><div class=\"tvg-dialog-dma-redesign-body card-declined-body\"><p data-qa-label=\"slpVisaRedirectDescription\" ng-bind=\"('modalDescription' | CMSLabels: 'cardErrorRedirect' | trust)\" class=\"card-declined-description\"></p><div class=\"card-declined-option-list\"><button ng-click=\"changeType('CC')\" ng-class=\"{'selected': type === 'CC'}\" class=\"card-declined-option\" data-qa-label=\"slpAnotherCardButton\"><span class=\"card-declined-option-circle\"><svg ng-if=\"type === 'CC'\" width=\"18\" height=\"13\" data-qa-label=\"slpAnotherCardButtonIcon\" viewBox=\"0 0 18 13\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#3574D4\" d=\"M1 1V0.25C0.585786 0.25 0.25 0.585786 0.25 1L1 1ZM16.6863 1H17.4363C17.4363 0.585786 17.1005 0.25 16.6863 0.25V1ZM16.6863 12V12.75C17.1005 12.75 17.4363 12.4142 17.4363 12H16.6863ZM1 12H0.25C0.25 12.4142 0.585786 12.75 1 12.75L1 12ZM1 1.75H16.6863V0.25H1V1.75ZM15.9363 1V12H17.4363V1H15.9363ZM16.6863 11.25H1V12.75H16.6863V11.25ZM1.75 12V1H0.25V12H1.75ZM1 5.95588L17 5.95588V4.45588L1 4.45588L1 5.95588ZM2.5686 9.19119H8.84311V7.69119H2.5686V9.19119Z\"/></svg> <svg ng-if=\"type !== 'CC'\" width=\"18\" height=\"13\" data-qa-label=\"slpAnotherCardButtonIcon\" viewBox=\"0 0 18 13\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#668FB8\" d=\"M1 1V0.25C0.585786 0.25 0.25 0.585786 0.25 1L1 1ZM16.6863 1H17.4363C17.4363 0.585786 17.1005 0.25 16.6863 0.25V1ZM16.6863 12V12.75C17.1005 12.75 17.4363 12.4142 17.4363 12H16.6863ZM1 12H0.25C0.25 12.4142 0.585786 12.75 1 12.75L1 12ZM1 1.75H16.6863V0.25H1V1.75ZM15.9363 1V12H17.4363V1H15.9363ZM16.6863 11.25H1V12.75H16.6863V11.25ZM1.75 12V1H0.25V12H1.75ZM1 5.95588L17 5.95588V4.45588L1 4.45588L1 5.95588ZM2.5686 9.19119H8.84311V7.69119H2.5686V9.19119Z\"/></svg> </span><span ng-bind=\"('AnotherCard' | CMSLabels: 'cardErrorRedirect' | trust)\"></span></button> <button ng-if=\"depositOptions.includes('IBC')\" ng-click=\"changeType('IBC')\" ng-class=\"{'selected': type === 'IBC'}\" class=\"card-declined-option\" data-qa-label=\"slpBetCashButton\"><span class=\"card-declined-option-circle\"><svg ng-if=\"type === 'IBC'\" width=\"18\" height=\"13\" data-qa-label=\"slpBetCashButtonIcon\" viewBox=\"0 0 18 13\" fill=\"\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#3574D4\" d=\"M1 1V0.25C0.585786 0.25 0.25 0.585786 0.25 1L1 1ZM16.6863 1H17.4363C17.4363 0.585786 17.1005 0.25 16.6863 0.25V1ZM16.6863 12V12.75C17.1005 12.75 17.4363 12.4142 17.4363 12H16.6863ZM1 12H0.25C0.25 12.4142 0.585786 12.75 1 12.75L1 12ZM1 1.75H16.6863V0.25H1V1.75ZM15.9363 1V12H17.4363V1H15.9363ZM16.6863 11.25H1V12.75H16.6863V11.25ZM1.75 12V1H0.25V12H1.75ZM2.5686 9.19119H8.84311V7.69119H2.5686V9.19119ZM2.5686 5.19119H12.8431V3.69119H2.5686V5.19119Z\"/></svg> <svg ng-if=\"type !== 'IBC'\" width=\"18\" height=\"13\" data-qa-label=\"slpBetCashButtonIcon\" viewBox=\"0 0 18 13\" fill=\"#3574D4\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#668FB8\" d=\"M1 1V0.25C0.585786 0.25 0.25 0.585786 0.25 1L1 1ZM16.6863 1H17.4363C17.4363 0.585786 17.1005 0.25 16.6863 0.25V1ZM16.6863 12V12.75C17.1005 12.75 17.4363 12.4142 17.4363 12H16.6863ZM1 12H0.25C0.25 12.4142 0.585786 12.75 1 12.75L1 12ZM1 1.75H16.6863V0.25H1V1.75ZM15.9363 1V12H17.4363V1H15.9363ZM16.6863 11.25H1V12.75H16.6863V11.25ZM1.75 12V1H0.25V12H1.75ZM2.5686 9.19119H8.84311V7.69119H2.5686V9.19119ZM2.5686 5.19119H12.8431V3.69119H2.5686V5.19119Z\"/></svg> </span><span class=\"card-declined-option-text\" ng-bind=\"('eCheck' | CMSLabels: 'cardErrorRedirect' | trust)\"></span></button> <button ng-if=\"depositOptions.includes('PAY')\" ng-click=\"changeType('PAY')\" ng-class=\"{'selected': type === 'PAY'}\" class=\"card-declined-option\" data-qa-label=\"slpPayPalButton\"><span class=\"card-declined-option-circle\"><svg ng-if=\"type === 'PAY'\" width=\"14\" height=\"16\" data-qa-label=\"slpPayPalButtonIcon\" viewBox=\"0 0 14 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#3574D4\" d=\"M6.57264 8.55129C8.9534 8.52313 10.7497 7.5757 11.5069 5.37098C12.2677 3.22963 12.074 1.25029 9.95722 0.429627C8.58719 -0.102178 8.13636 0.0281341 2.7724 0.0281341C2.42372 0.0281341 2.12084 0.285252 2.06795 0.623342L0.00413528 13.7216C-0.0310731 13.9787 0.162607 14.2111 0.430246 14.2111H3.05764C3.12809 14.2111 3.15271 14.1865 3.1633 14.1231C3.30768 13.232 3.79729 10.0798 3.92052 9.40362C4.12486 8.30476 5.0441 8.57602 6.57264 8.55129Z\"/><path fill=\"#3574D4\" d=\"M12.5741 4.33554C12.5107 4.28974 12.486 4.2721 12.4684 4.38127C12.398 4.78283 12.2888 5.17373 12.1585 5.56471C10.7532 9.57269 6.85786 9.22404 4.95599 9.22404C4.74113 9.22404 4.60026 9.34029 4.57206 9.55509C3.77613 14.4999 3.61762 15.5319 3.61762 15.5319C3.58238 15.7819 3.74088 15.9862 3.99095 15.9862H6.22741C6.53029 15.9862 6.78036 15.7643 6.84026 15.4615C6.86488 15.2712 6.80154 15.6763 7.34741 12.2459C7.50939 11.4711 7.85102 11.5521 8.37932 11.5521C10.88 11.5521 12.8311 10.5378 13.4122 7.59693C13.6412 6.37123 13.5743 5.08217 12.5741 4.33554Z\"/></svg> <svg ng-if=\"type !== 'PAY'\" width=\"14\" height=\"16\" data-qa-label=\"slpPayPalButtonIcon\" viewBox=\"0 0 14 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#668FB8\" d=\"M6.57264 8.55129C8.9534 8.52313 10.7497 7.5757 11.5069 5.37098C12.2677 3.22963 12.074 1.25029 9.95722 0.429627C8.58719 -0.102178 8.13636 0.0281341 2.7724 0.0281341C2.42372 0.0281341 2.12084 0.285252 2.06795 0.623342L0.00413528 13.7216C-0.0310731 13.9787 0.162607 14.2111 0.430246 14.2111H3.05764C3.12809 14.2111 3.15271 14.1865 3.1633 14.1231C3.30768 13.232 3.79729 10.0798 3.92052 9.40362C4.12486 8.30476 5.0441 8.57602 6.57264 8.55129Z\"/><path fill=\"#668FB8\" d=\"M12.5741 4.33554C12.5107 4.28974 12.486 4.2721 12.4684 4.38127C12.398 4.78283 12.2888 5.17373 12.1585 5.56471C10.7532 9.57269 6.85786 9.22404 4.95599 9.22404C4.74113 9.22404 4.60026 9.34029 4.57206 9.55509C3.77613 14.4999 3.61762 15.5319 3.61762 15.5319C3.58238 15.7819 3.74088 15.9862 3.99095 15.9862H6.22741C6.53029 15.9862 6.78036 15.7643 6.84026 15.4615C6.86488 15.2712 6.80154 15.6763 7.34741 12.2459C7.50939 11.4711 7.85102 11.5521 8.37932 11.5521C10.88 11.5521 12.8311 10.5378 13.4122 7.59693C13.6412 6.37123 13.5743 5.08217 12.5741 4.33554Z\"/></svg> </span><span ng-bind=\"('Paypal' | CMSLabels: 'cardErrorRedirect' | trust)\"></span></button></div><hr style=\"margin-bottom: 16px;\"><div ng-if=\"type === 'CC'\" data-qa-label=\"slpCardDeclinedDescription\"><p style=\"margin-bottom: 16px;\" class=\"card-declined-description\" ng-bind=\"('otherCardDescription' | CMSLabels: 'cardErrorRedirect' | trust)\"></p><h3 class=\"card-declined-sub-title\" ng-bind=\"('otherCardTitle' | CMSLabels: 'cardErrorRedirect' | trust)\"></h3><ul class=\"card-declined-cards-list\"><li ng-repeat=\"cardItem in cardList track by $index\">{{ cardItem }}</li></ul></div><div ng-if=\"type === 'IBC'\" data-qa-label=\"slpCardDeclinedDescription\"><h3 class=\"card-declined-sub-title\" ng-bind=\"('eCheckTitle' | CMSLabels: 'cardErrorRedirect' | trust)\"></h3><ul class=\"card-declined-cards-list\"><li ng-bind=\"('eCheckDescription' | CMSLabels: 'cardErrorRedirect' | trust)\"></li></ul></div><div ng-if=\"type === 'PAY'\" data-qa-label=\"slpCardDeclinedDescription\"><h3 class=\"card-declined-sub-title\" ng-bind=\"('paypalTitle1' | CMSLabels: 'cardErrorRedirect' | trust)\"></h3><ul class=\"card-declined-cards-list\"><li ng-bind=\"('paypalDescription1' | CMSLabels: 'cardErrorRedirect' | trust)\"></li></ul><h3 class=\"card-declined-sub-title\" style=\"margin-top: 8px !important;\" ng-bind=\"('paypalTitle2' | CMSLabels: 'cardErrorRedirect' | trust)\"></h3><ul class=\"card-declined-cards-list\"><li ng-bind=\"('paypalDescription2' | CMSLabels: 'cardErrorRedirect' | trust)\"></li></ul></div><div class=\"card-declined-button\"><button ng-if=\"type === 'CC'\" ng-bind=\"('modalButtonOtherCard' | CMSLabels: 'cardErrorRedirect' | trust)\" ng-click=\"redirectTo($close)\" data-qa-label=\"slpCardDeclinedSubmitButton\"></button> <button ng-if=\"type === 'IBC'\" ng-bind=\"('modalButtonEcheck' | CMSLabels: 'cardErrorRedirect' | trust)\" ng-click=\"redirectTo($close, 'IBC')\" data-qa-label=\"slpCardDeclinedSubmitButton\"></button> <button ng-if=\"type === 'PAY'\" ng-bind=\"('modalButtonPaypal' | CMSLabels: 'cardErrorRedirect' | trust)\" ng-click=\"redirectTo($close, 'PAY')\" data-qa-label=\"slpCardDeclinedSubmitButton\"></button></div></div></div>"
  );


  $templateCache.put('src/templates/customer-info.html',
    "<span ng-bind-html=\"data.htmlContent\"></span>"
  );


  $templateCache.put('src/templates/customer-options.html',
    "<tvg-collapse class=\"support\" ng-repeat=\"option in data.optionsConfig\" ng-attr-title=\"{{option.name}}\"><span ng-repeat=\"itemOption in option.values\"><a ng-if=\"itemOption.url.lastIndexOf('cms:') !== 0 && itemOption.onclick\" onclick=\"window.webkit && window.webkit.messageHandlers['OPEN_EXTERNAL_APP'].postMessage({\n" +
    "                        type: 'OPEN_EXTERNAL_APP',\n" +
    "                        payload: { openExternalApp: ''+window.location.protocol+'/' + window.location.host + '/redirectengine?type=messageus'}\n" +
    "                    })\" class=\"{{itemOption.class}}\">{{itemOption.name}}</a> <a ng-if=\"itemOption.url.lastIndexOf('cms:') !== 0 && itemOption.url\" class=\"{{itemOption.class}}\" href=\"{{itemOption.url}}\" target=\"_blank\">{{itemOption.name}}</a> <a ng-if=\"itemOption.url.lastIndexOf('cms:') === 0\" class=\"{{itemOption.class}}\" ng-click=\"$emit('more_info', itemOption.url.substr(4,itemOption.url.length-4))\" target=\"_blank\">{{itemOption.name}}</a></span></tvg-collapse>"
  );


  $templateCache.put('src/templates/dw-info-dialog-fdr.html',
    "<div class=\"container\"><div class=\"info-icon\" qa-label=\"info-icon\"></div><h2 qa-label=\"heading-text\">{{ headingText }}</h2><div class=\"text\" ng-transclude qa-label=\"dialog-text\"></div><div ng-if=\"actionUrl && !livePerson\"><a class=\"text-green\" href=\"tel:1-888-752-9884\" qa-label=\"dialog-action-url\">{{ actionText }}</a></div><div ng-if=\"action && !livePerson\"><span class=\"support-phone\" ng-click=\"action()\" qa-label=\"dialog-action\">{{ actionText }}</span></div><div ng-if=\"livePerson\" ng-bind-html=\"livePerson\"></div><button ng-click=\"buttonAction()\" qa-label=\"button-action\">{{ buttonText }}</button></div>"
  );


  $templateCache.put('src/templates/dw-info-dialog.html',
    "<div class=\"container\"><div class=\"square\"><div class=\"text\" ng-transclude qa-label=\"dialog-text\"></div></div><div ng-if=\"actionUrl && !livePerson\"><a class=\"text-green\" href=\"{{actionUrl}}\" qa-label=\"dialog-action-url\">{{actionText}}</a></div><div ng-if=\"action && !livePerson\"><span class=\"clickable text-green\" ng-click=\"action()\" qa-label=\"dialog-action\">{{actionText}}</span></div><div ng-if=\"livePerson\" ng-bind-html=\"livePerson | trust\"></div></div>"
  );


  $templateCache.put('src/templates/dw-info-message.html',
    "<div class=\"info-container\"><h4 qa-label=\"dw-info-title\">{{title}}</h4><p qa-label=\"dw-info-message\">{{message}}</p></div>"
  );


  $templateCache.put('src/templates/footer-links.html',
    "<div class=\"footer-links\"><div><span class=\"link\">Privacy Policy</span> | <span class=\"link\">Terms & conditions</span></div><div><span class=\"link\">Wager responsibly</span> | <span class=\"link\">Contact us</span></div></div>"
  );


  $templateCache.put('src/templates/modal-window.html',
    "<div modal-render=\"{{$isRendered}}\" tabindex=\"-1\" role=\"dialog\" class=\"tvgmodal fade in\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\"><div class=\"tvgmodal-dismiss no-click-feedback\" ng-click=\"close($event)\"></div><div class=\"tvgmodal-dialog\"><div class=\"tvgmodal-content\" ng-transclude></div></div></div>"
  );


  $templateCache.put('src/templates/notification_delete_card.html',
    "<div class=\"tvg-dialog-filter\"></div><div class=\"tvg-dialog dma-redesign dialog-{{type}}\"><div class=\"tvg-dialog-dma-redesign-header\"><span class=\"tvg-dialog-dma-redesign-title\" ng-bind=\"('removeCardTitle' | CMSLabels: 'dmaManagementLabels' | trust)\"></span> <a href class=\"tvg-dialog-dma-redesign-close-icon\" ng-click=\"$close()\"><i class=\"tvg-icon-close\"></i></a></div><div class=\"tvg-dialog-dma-redesign-body\"><div class=\"tvg-dialog-dma-redesign-warning\"><i class=\"tvg-dialog-dma-redesign-warning-icon tvg-icon-info\"></i> <span class=\"tvg-dialog-dma-redesign-warning-message\" ng-bind=\"('removeCardMessage' | CMSLabels: 'dmaManagementLabels' | trust)\"></span></div><div class=\"tvg-dialog-dma-redesign-card\"><div class=\"tvg-dialog-dma-card-icon\"></div><ul><li><strong ng-bind=\"selectedCard.typeName + ' Card'\"></strong></li><li>{{\"xxxx-xxxx-xxxx-\" + selectedCard.cardNumber}}</li><li>Expires {{selectedCard.expirationDate}}</li></ul></div><div><a href class=\"tvg-dma-button__secondary tvg-dialog-dma-redesign-button__cancel\" ng-click=\"$close()\">Cancel</a> <a href class=\"tvg-dma-button__delete tvg-dialog-dma-redesign-button__confirm\" ng-click=\"$close(selectedCard)\">Delete</a></div></div></div>"
  );


  $templateCache.put('src/templates/notification_edit_card.html',
    "<div class=\"tvg-dialog-filter\"></div><div class=\"tvg-dialog dma-redesign\"><div class=\"tvg-dialog-dma-redesign-header\"><span class=\"tvg-dialog-dma-redesign-title\" ng-bind=\"('editCardTitle' | CMSLabels: 'dmaManagementLabels' | trust)\"></span> <a href class=\"tvg-dialog-dma-redesign-close-icon\" ng-click=\"$close()\"><i class=\"tvg-icon-close\"></i></a></div><div class=\"tvg-dialog-dma-redesign-body\"><div class=\"tvg-dialog-dma-redesign-warning\" ng-if=\"message\"><i class=\"tvg-dialog-dma-redesign-warning-icon tvg-icon-info\"></i> <span class=\"tvg-dialog-dma-redesign-warning-message\" ng-bind-html=\"message\"></span></div><div class=\"tvg-dialog-dma-redesign-card\"><div class=\"tvg-dialog-dma-card-icon\"></div><ul><li><strong ng-bind=\"selectedCard.typeName + ' Card'\"></strong></li><li>{{\"xxxx-xxxx-xxxx-\" + selectedCard.cardNumber}}</li></ul></div><form name=\"editCardRedesignForm\"><p>Expiry Date</p><input class=\"tiny\" name=\"cardExpMonth\" placeholder=\"MM\" ng-required=\"true\" min=\"1\" max=\"12\" minlength=\"1\" maxlength=\"2\" type=\"number\" pattern=\"\\d*\" ng-model=\"selectedCard.expirationMonth\"> <span>/</span> <input id=\"cardExpirationYear\" class=\"tiny\" name=\"cardExpYr\" placeholder=\"YY\" ng-required=\"true\" minlength=\"2\" maxlength=\"2\" type=\"number\" pattern=\"\\d*\" ng-model=\"selectedCard.expirationYear\"></form><div><a href class=\"tvg-dma-button__secondary tvg-dialog-dma-redesign-button__cancel\" ng-click=\"$close()\">Cancel</a> <a href class=\"tvg-dma-button__primary tvg-dialog-dma-redesign-button__confirm\" ng-click=\"editCardRedesignForm.$valid && $close(selectedCard)\">Save</a></div></div></div>"
  );


  $templateCache.put('src/templates/section-title.html',
    "<div qa-label=\"{{qalabel || sectionTitle}}\" class=\"section-title\"><span ng-bind=\"index\"></span> <span ng-if=\"index\">-</span> <span ng-bind=\"title\"></span></div>"
  );


  $templateCache.put('src/templates/toggle-component.html',
    "<span class=\"checkinput\"><input id=\"chk-store-card\" type=\"checkbox\" ng-model=\"savein\"> <span class=\"thumb\"></span> </span><label class=\"chk-store-card-text\"><h3 class=\"title\">{{title}}</h3><p class=\"subtitle\">{{subtitle}}</p></label>"
  );


  $templateCache.put('src/templates/tvg-collapse.html',
    "<button ng-init=\"expanded = false\" ng-click=\"expanded = !expanded; scrollDown()\" ng-class=\"{expanded: expanded}\" type=\"button\">{{title}}</button><div ng-class=\"{expanded: expanded}\" class=\"content-ctnr\"><div class=\"content\" ng-transclude></div></div>"
  );


  $templateCache.put('src/templates/welcome-dialog-fdr.html',
    "<div class=\"dialog-welcome-wrapper\"><div class=\"dialog-welcome-inner\"><div class=\"header\"><h2>Fund your account</h2><span class=\"dismiss\" ng-click=\"dismiss()\"></span></div><div class=\"content\"><div class=\"success\"><h3>Account Created!</h3><p>{{'accountDetailsEmailSent' | CMSValue : null}} {{ $root.user.emailAddress ? $root.user.emailAddress : 'your email address' }}</p></div><div class=\"disclaimer\">Fund your account so you can start betting with FanDuel Racing. Click continue below to get started.</div><button ng-click=\"dismiss()\">Make first deposit</button></div></div></div>"
  );


  $templateCache.put('src/applepay/deposits/deposit-button/deposit-button.template.html',
    "<div class=\"field\"><button type=\"button\" qa-label=\"applepayButton\" class=\"applepay-deposit__button pa_0\" ng-disabled=\"$ctrl.isDisabled\" ng-click=\"$ctrl.onDeposit($event)\" ng-bind-html=\"::('depositButton' | CMSLabels: 'applepayLabels')\"></button></div>"
  );


  $templateCache.put('src/applepay/deposits/deposit.template.html',
    "<div ng-class=\"{loading: $ctrl.loading}\" class=\"applepay applepay-deposit\"><ng-form name=\"$ctrl.applepayDeposits\" ng-show=\"!$ctrl.loading\"><div class=\"disclaimer\" qa-label=\"applepayDisclaimer\" ng-bind-html=\"::('tutorial' | CMSLabels: 'applepayLabels')\"></div><section-title class=\"first-title\" qalabel=\"applepay-depositAmountTitle\" title=\"{{::'deposit-amount-title' | CMSLabels: 'dmaDepositLabels'}}\"></section-title><applepay-select-amount form=\"::$ctrl.applepayDeposits\" amount=\"$ctrl.applepayAmount\" min-amount=\"$ctrl.minAmount\" max-amount=\"$ctrl.maxAmount\" amounts=\"::$ctrl.amountOptions\" on-amount-change=\"::$ctrl.handleApplePayAmountChange($event)\"></applepay-select-amount><section-title class=\"second-title\" title=\"Review and Authorize\" qalabel=\"applepay-reviewTitle\"></section-title><applepay-total-cost ng-if=\"!$ctrl.unableToFetchBraintreeClient\" data=\"$ctrl.fees\" email=\"$ctrl.email\" handle-fetch-fees=\"$ctrl.fetchFees($ctrl.depositAmount)\"></applepay-total-cost><div ng-if=\"$ctrl.unableToFetchBraintreeClient\" ng-style=\"{ 'margin-bottom': '24px' }\"><dw-info-dialog>{{'braintreeClientFailMessage' | CMSLabels: 'applepayLabels'}}</dw-info-dialog></div><applepay-deposit-button ng-if=\"!$ctrl.unableToFetchBraintreeClient\" is-disabled=\"$ctrl.shouldDisableApplePayButton()\" on-apple-pay-deposit=\"$ctrl.onApplePayDeposit()\"></applepay-deposit-button></ng-form></div>"
  );


  $templateCache.put('src/applepay/deposits/select-amount/select-amount.template.html',
    "<div class=\"dma-amount-ctn\" qa-label=\"deposit-amount\"><div class=\"dma-amount-table\"><div class=\"row\"><div class=\"cell w155\"><toggle-options><button qa-label=\"amount-button-{{amountOption}}\" ng-repeat=\"amountOption in $ctrl.amounts track by $index\" ng-class=\"{selected: $ctrl.amount == amountOption}\" class=\"amount-button\" type=\"button\" qa-label=\"amount-button-{{amountOption}}\" ng-click=\"$ctrl.change(amountOption)\">${{amountOption}}</button></toggle-options></div><span class=\"cell minw30 amount-divider\">or <span class=\"amount-dollar-label\">$</span></span><div class=\"cell align-right amount-input-ctn\"><input qa-label=\"amount-input\" money-formater class=\"amount\" name=\"amount\" type=\"number\" placeholder=\"Other amount\" ng-min=\"{{$ctrl.minAmount||0}}\" ng-max=\"{{$ctrl.maxAmount||100000}}\" ng-model-options=\"{ allowInvalid: true, updateOn: 'default blur', debounce: { default: 1000, blur: 0 } }\" num-length=\"5\" step=\"any\" ng-model=\"$ctrl.amount\" ng-required=\"true\" ng-change=\"$ctrl.change($ctrl.amount)\" restrict-chars ng-blur=\"inputIsNowFocused = false\" ng-focus=\"inputIsNowFocused = true\" ng-class=\"{\n" +
    "                        inputIsInvalid: $root.isFdrApp && $ctrl.form.amount.$invalid && $ctrl.form.$submitted,\n" +
    "                        inputIsFocused: ($root.isFdrApp && !$ctrl.form.amount.$invalid && !!inputIsNowFocused)\n" +
    "                            || ($root.isFdrApp && !$ctrl.form.amount.$dirty && !!inputIsNowFocused)\n" +
    "                    }\"></div></div></div><div class=\"row non-table amount-errors-ctn\" ng-if=\"$ctrl.form.amount.$touched || $ctrl.form.$submitted || $ctrl.form.amount.$dirty\"><div ng-messages=\"$ctrl.form.amount.$error\"><div class=\"js-error-label error-label\" ng-if=\"$ctrl.maxAmount !== 0\" ng-message=\"min\" ng-bind-html=\"(('minimum' | CMSLabels: 'applepayLabels') + ' ' + ($ctrl.minAmount | currency) | trust )\"></div><div qa-label=\"error-required\" class=\"js-error-label error-label\" ng-message=\"required\" ng-bind-html=\"('required' | CMSLabels: 'applepayLabels' | trust )\"></div><div class=\"js-error-label error-label\" ng-message=\"max\" ng-bind-html=\"(('maximum' | CMSLabels: 'applepayLabels') + ' ' + ($ctrl.maxAmount | currency) | trust )\"></div><div ng-init=\"events.sendOtherAmountErrorToGTM('Maximum amount reached')\" ng-if=\"$ctrl.maxAmount === 0\" qa-label=\"error-maximum-amount\" class=\"js-error-label error-label\">Maximum amount reached</div></div></div></div>"
  );


  $templateCache.put('src/applepay/deposits/total-cost/total-cost.template.html',
    "<label ng-if=\"$ctrl.data.loading && !$root.isFdrApp\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label> <label ng-if=\"$ctrl.data.retryFetchingFees\" ng-click=\"$ctrl.handleFetchFees()\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees-error' | CMSLabels: 'dmaDepositLabels' | trust\"></label><ul qa-label=\"deposit-summary\" class=\"deposit__summary\"><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('deposit-summary-amount' | CMSLabels: 'dmaDepositLabels') + (' <span>') +\n" +
    "                      (($ctrl.data.netAmount | currency: '$') || '$--') | trust ) + ('</span>')\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-fee\" ng-bind-html=\"(('deposit-summary-fee' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                      (($ctrl.data.fee | currency: '$') || '$--') | trust ) + ('</span>')\"></li><li ng-if=\"!$root.isFdrApp && $ctrl.data.feeDiscount\" qa-label=\"deposit-summary-discount\" ng-bind-html=\"(('deposit-summary-discount' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                      (($ctrl.data.feeDiscount | currency: '-$') || '$--') | trust ) + ('</span>')\"></li><li><strong qa-label=\"deposit-summary-total\" ng-bind-html=\"(('deposit-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') + (($ctrl.data.transactionTotal | currency: '$') || '$--') | trust ) + ('</span>')\"></strong></li></ul><label ng-if=\"$ctrl.data.loading && $root.isFdrApp\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label>"
  );


  $templateCache.put('src/common/modal-dialog/modal-dialog.template.html',
    "<div class=\"tvg-dialog dma-redesign\" ng-class=\"::$ctrl.klass\"><div class=\"tvg-dialog-dma-redesign-header\"><span class=\"tvg-dialog-dma-redesign-title\" ng-bind=\"::$ctrl.title\"></span> <button class=\"tvg-dialog-dma-redesign-close-icon\" ng-click=\"$ctrl.close()\"><i class=\"tvg-icon-close\"></i></button></div><div class=\"tvg-dialog-dma-redesign-body\" data-add-click-listener-to=\"::$ctrl.body\" data-add-to-all=\"true\" data-click-listener=\"$ctrl.scrollToSection(event)\"></div></div>"
  );


  $templateCache.put('src/common/modal-dialog/modal-window.html',
    "<div modal-render=\"{{$isRendered}}\" tabindex=\"-1\" role=\"dialog\" class=\"tvgmodal fade in\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\"><div class=\"tvgmodal-dismiss no-click-feedback\" ng-click=\"close($event)\"></div><div class=\"tvgmodal-dialog\"><div class=\"tvgmodal-content\" ng-transclude></div></div></div>"
  );


  $templateCache.put('src/moneypak/limits-table/limits-table.template.html',
    "<div class=\"limits-table-container\"><table><thead><tr><th ng-repeat=\"header in vm.content.headers track by $index\" ng-bind=\"header\"></th></tr></thead><tbody><tr ng-repeat=\"row in vm.content.rows track by $index\"><td ng-repeat=\"data in row track by $index\" ng-bind=\"data\"></td></tr></tbody></table></div>"
  );


  $templateCache.put('src/moneypak/moneypak-activation-number-input/moneypak-activation-number-input.template.html',
    "<div class=\"mpak-number-container field\" ng-class=\"{fieldInvalid: $ctrl.form.mpakNumber.$touched && $ctrl.form.mpakNumber.$invalid, inputFocused: inputNumberFocused}\"><div class=\"field-label\"><label for=\"mpak-number\" qa-label=\"mpInputLabel\" ng-bind-html=\"::('moneypakNumberLabel' | CMSLabels: 'moneyPakLabels')\"></label></div><div class=\"field-input mpak-number\"><span class=\"input-container\"><input type=\"text\" qa-label=\"mpInput\" class=\"form-control mpak-number\" id=\"mpak-number\" placeholder=\"{{::('moneypakNumberPlaceholder' | CMSLabels: 'moneyPakLabels')}}\" autocomplete=\"off\" name=\"mpakNumber\" ng-model=\"$ctrl.mpakNumber\" ui-mask=\"999 999 9999 9?9?9?9\" ng-focus=\"$ctrl.startDeposit(); inputNumberFocused= true;\" ui-mask-placeholder ui-mask-placeholder-char=\" \" ng-blur=\"inputNumberFocused = false\" ui-options=\"{ clearOnBlur: false, allowInvalidValue: true }\" ng-change=\"$ctrl.update()\" ng-model-options=\"{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }\" required></span></div><additional-info ng-click=\"$ctrl.openTooltip()\"><span class=\"card-imgs mpak\" qa-label=\"mpHelperImage\"></span></additional-info><div class=\"row non-table amount-errors-ctn clearfix\" ng-if=\"$ctrl.form.mpakNumber.$touched || $ctrl.form.$submitted\"><div ng-messages=\"$ctrl.form.mpakNumber.$error\"><div qa-label=\"error-required\" class=\"js-error-label error-label\" ng-message=\"required\" ng-bind-html=\"::('required' | CMSLabels: 'moneyPakLabels' | trust )\"></div><div qa-label=\"error-invalid\" class=\"js-error-label error-label\" ng-message=\"mask\" ng-bind-html=\"::('invalidCard' | CMSLabels: 'moneyPakLabels')\"></div></div></div></div>"
  );


  $templateCache.put('src/moneypak/moneypak.template.html',
    "<div ng-class=\"{loading: $ctrl.loading || $ctrl.activePoller}\" class=\"moneypak\"><form name=\"$ctrl.moneyPakDepositForm\" ng-submit=\"$ctrl.handleFormSubmit($event)\" novalidate><div class=\"disclaimer\" qa-label=\"moneyPakDisclaimer\" ng-bind-html=\"::('tutorial' | CMSLabels: 'moneyPakLabels')\"></div><section-title qalabel=\"mpak-depositLimitsTitle\" class=\"first-title\" title=\"{{::'depositLimitsTitle' | CMSLabels: 'moneyPakLabels'}}\"></section-title><div class=\"disclaimer\" qa-label=\"mPtableLimitsDisclaimer\" ng-bind-html=\"::('depositLimitsText' | CMSLabels: 'moneyPakLabels')\"></div><limits-table content-obj=\"::('depositLimitsTable' | CMSLabels: 'moneyPakLabels')\"></limits-table><section-title qalabel=\"mpak-authorizeTitle\" title=\"{{::'redeemAndAuthorizeTitle' | CMSLabels: 'moneyPakLabels'}}\"></section-title><div class=\"disclaimer\" qa-label=\"mpRedeemAuthorizeDisclaimer\" ng-bind-html=\"::('redeemAndAuthorizeText' | CMSLabels: 'moneyPakLabels')\"></div><moneypak-activation-number-input ng-if=\"isRGAvailable && !rgLimitReached || !isRGAvailable\" class=\"mb_20\" data-mpak-number=\"$ctrl.mpakNumber\" form=\"$ctrl.moneyPakDepositForm\" on-update=\"$ctrl.update(value)\"></moneypak-activation-number-input><div ng-if=\"isRGAvailable && !rgLimitReached && rgMoneypakAvailableDepositAmount\" class=\"warningMessage\"><div></div><span>{{messageWithRemainingAmount}}</span></div><button ng-if=\"isRGAvailable && !rgLimitReached || !isRGAvailable\" qa-label=\"submitDeposit\" class=\"submit authorize-deposit mb_20\" ng-disabled=\"$ctrl.loading || $ctrl.moneyPakDepositForm.$invalid || $ctrl.activePoller || $ctrl.responsibleGamingDelay\" type=\"submit\"><i class=\"tvg-icon tvg-icon-lock\"></i> <strong ng-bind=\"::'depositExecuteButton' | CMSValue\"></strong></button><div ng-if=\"isRGAvailable && rgLimitReached\" class=\"warningMessage\"><div></div><span>{{::'DMARGLimitReached' | CMSLabels: 'moneyPakLabels'}}</span></div><div class=\"disclaimer\" qa-label=\"mpFaqDisclaimer\" data-add-click-listener-to=\"::('faqText' | CMSLabels: 'moneyPakLabels')\" data-click-listener=\"$ctrl.openModal(event)\"></div></form></div>"
  );


  $templateCache.put('src/paypal/deposits/deposit-button/deposit-button.template.html',
    "<div class=\"field\"><div ng-if=\"!$root.isFdrApp\" class=\"paypal-deposit__message disclaimer pv_10\" qa-label=\"payPalDepositMessageDisclaimerPv_10\"><p class=\"pb_5\" ng-bind-html=\"::('clickMessage' | CMSLabels: 'paypalLabels')\"></p><p class=\"pb_5\" ng-bind-html=\"::('accountMessage' | CMSLabels: 'paypalLabels')\"></p><p ng-bind-html=\"::('connectedAcount' | CMSLabels: 'paypalLabels')\"></p></div><div ng-if=\"$root.isFdrApp\" class=\"paypal-deposit__message disclaimer pv_10\" qa-label=\"payPalDepositMessageDisclaimerPv_10\">{{'clickMessage' | CMSLabels: 'paypalLabels'}} {{'accountMessage' | CMSLabels: 'paypalLabels'}} {{'connectedAcount' | CMSLabels: 'paypalLabels'}}</div><button qa-label=\"payPalButton\" class=\"paypal-deposit__button pa_0\" ng-click=\"$ctrl.onDeposit($event)\" ng-disabled=\"$ctrl.isDisabled\"><img src=\"https://www.paypalobjects.com/webstatic/en_US/i/btn/png/blue-rect-paypal-44px.png\" alt=\"PayPal Checkout\"></button></div>"
  );


  $templateCache.put('src/paypal/deposits/deposit.template.html',
    "<div ng-class=\"{loading: $ctrl.loading}\" class=\"paypal paypal-deposit\"><ng-form name=\"$ctrl.paypalDeposits\" ng-show=\"!$ctrl.loading\"><div class=\"disclaimer\" qa-label=\"payPalDisclaimer\" ng-bind-html=\"::('tutorial' | CMSLabels: 'paypalLabels')\"></div><section-title ng-if=\"$root.isFdrApp && $ctrl.email\" title=\"PayPal Account Details\" qalabel=\"paypal-accountDetails\" index=\"0\"></section-title><div ng-if=\"$root.isFdrApp && $ctrl.email\" qa-label=\"paypal-accountDetails-email\" email=\"$ctrl.email\" class=\"paypal-account-details\">Email address set to: <strong class=\"paypal-user-email\">{{ $ctrl.email }}</strong></div><section-title class=\"first-title\" qalabel=\"paypal-depositAmountTitle\" title=\"{{::'deposit-amount-title' | CMSLabels: 'dmaDepositLabels'}}\" index=\"1\"></section-title><select-amount form=\"::$ctrl.paypalDeposits\" amount=\"$ctrl.depositAmount\" min-amount=\"::$ctrl.minAmount\" max-amount=\"::$ctrl.maxAmount\" amounts=\"::$ctrl.amountOptions\" on-amount-change=\"::$ctrl.handleOnAmountChange($event)\"></select-amount><section-title title=\"Review and Authorize\" qalabel=\"paypal-reviewTitle\" index=\"2\"></section-title><total-cost data=\"$ctrl.fees\" email=\"$ctrl.email\"></total-cost><deposit-button is-disabled=\"$ctrl.shouldDisablePaypalButton()\" on-paypal-deposit=\"$ctrl.makePaypalDeposit($event)\"></deposit-button></ng-form></div>"
  );


  $templateCache.put('src/paypal/deposits/select-amount/select-amount.template.html',
    "<div class=\"dma-amount-ctn\" qa-label=\"deposit-amount\"><div class=\"dma-amount-table\"><div class=\"row\"><div class=\"cell w155\"><toggle-options><button qa-label=\"amount-button-{{amountOption}}\" ng-repeat=\"amountOption in $ctrl.amounts track by $index\" ng-class=\"{selected: $ctrl.amount == amountOption}\" class=\"amount-button\" type=\"button\" qa-label=\"amount-button-{{amountOption}}\" ng-click=\"$ctrl.change(amountOption)\">${{amountOption}}</button></toggle-options></div><span class=\"cell minw30 amount-divider\">or <span class=\"amount-dollar-label\">$</span></span><div class=\"cell align-right amount-input-ctn\"><input qa-label=\"amount-input\" money-formater class=\"amount\" name=\"amount\" type=\"number\" placeholder=\"Other amount\" ng-min=\"{{$ctrl.minAmount||0}}\" ng-max=\"{{$ctrl.maxAmount||100000}}\" ng-model-options=\"{ allowInvalid: true, updateOn: 'default blur', debounce: { default: 1000, blur: 0 } }\" num-length=\"5\" step=\"any\" ng-model=\"$ctrl.amount\" ng-required=\"true\" ng-change=\"$ctrl.change($ctrl.amount)\" restrict-chars ng-blur=\"inputIsNowFocused = false\" ng-focus=\"inputIsNowFocused = true\" ng-class=\"{\n" +
    "                        inputIsInvalid: $root.isFdrApp && $ctrl.form.amount.$invalid && $ctrl.form.$submitted,\n" +
    "                        inputIsFocused: ($root.isFdrApp && !$ctrl.form.amount.$invalid && !!inputIsNowFocused)\n" +
    "                            || ($root.isFdrApp && !$ctrl.form.amount.$dirty && !!inputIsNowFocused)\n" +
    "                    }\"></div></div></div><div class=\"row non-table amount-errors-ctn\" ng-if=\"$ctrl.form.amount.$touched || $ctrl.form.$submitted || $ctrl.form.amount.$dirty\"><div ng-messages=\"$ctrl.form.amount.$error\"><div class=\"js-error-label error-label\" ng-message=\"min\" ng-bind-html=\"(('minimum' | CMSLabels: 'paypalLabels') + ' ' + ($ctrl.minAmount | currency) | trust )\"></div><div qa-label=\"error-required\" class=\"js-error-label error-label\" ng-message=\"required\" ng-bind-html=\"('required' | CMSLabels: 'paypalLabels' | trust )\"></div><div class=\"js-error-label error-label\" ng-message=\"max\" ng-bind-html=\"(('maximum' | CMSLabels: 'paypalLabels') + ' ' + ($ctrl.maxAmount | currency) | trust )\"></div></div></div></div>"
  );


  $templateCache.put('src/paypal/deposits/total-cost/total-cost.template.html',
    "<label ng-if=\"$ctrl.data.loading && !$root.isFdrApp\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label><ul qa-label=\"deposit-summary\" class=\"deposit__summary\"><li ng-if=\"!$root.isFdrApp\" qa-label=\"paypal-email\" ng-if=\"$ctrl.email && !$root.isFdrApp\" ng-bind-html=\"(('email' | CMSLabels: 'paypalLabels') + ' ' + ($ctrl.email  | trust ))\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('deposit-summary-amount' | CMSLabels: 'dmaDepositLabels') + ' ' +\n" +
    "                      (($ctrl.data.netAmount | currency: '$') || '$--') | trust )\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-fee-amount\" ng-bind-html=\"(('deposit-summary-fee-amount' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                      (($ctrl.data.feeAmount | currency: '$') || '$--') | trust ) + ('</span>')\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-fee-refund\" ng-bind-html=\"(('deposit-summary-fee-refund' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                    (($ctrl.data.feeRefundAmount | currency: '$') || '$--') | trust ) + ('</span>')\"></li><li><strong qa-label=\"deposit-summary-total\" ng-bind-html=\"(('deposit-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') + (($ctrl.data.transactionTotal | currency: '$') || '$--') | trust ) + ('</span>')\"></strong></li></ul><label ng-if=\"$ctrl.data.loading && $root.isFdrApp\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/deposit-limits.html',
    "<div class=\"field\"><h2 class=\"dma-section-title\"><span ng-bind=\"('depositLimitsTitle' | CMSLabels: 'dmaManagementLabels' | trust)\"></span></h2><div class=\"limits\" ng-if=\"(!events.unableToFetchLimits() || !(data.selectedPayOption.ftype === 'IBC' || data.selectedPayOption.ftype === 'ACH' || data.selectedPayOption.ftype === 'CC' || data.selectedPayOption.ftype === 'APPL'))\"><div class=\"limits-table\"><div class=\"header\"><div class=\"header-row\"><div class=\"header-cell\"><span ng-if=\"data.selectedPayOption.ftype === 'APPL'\">Card Type</span> <span ng-if=\"data.selectedPayOption.ftype === 'CC'\">Card Type</span> <span ng-if=\"data.selectedPayOption.ftype === 'IBC'\">Account Type</span></div><div class=\"header-cell\"><span>Daily Limit</span></div><div class=\"header-cell\"><span>Monthly Limit</span></div></div></div><div class=\"body\"><div class=\"body-row\" ng-repeat=\"limitType in data.selectedPayOption.paymentLimits\"><div class=\"body-cell card-type-cell\" qa-label=\"cardTypeCell\"><span>{{limitType.typeName}}</span></div><div class=\"body-cell\"><div class=\"image-row\"><span class=\"image-cell\" qa-label=\"dailyLimitCell\">{{limitType.limitInterval.Daily.Effective | noFractionCurrency}}</span> <button class=\"edit\" ng-click=\"events.editLimit(true, limitType)\" qa-label=\"dailyLimitEditButton\"><strong>Edit</strong></button></div><div ng-if=\"limitType.limitInterval.Daily.ShowFuture\" class=\"image-row\"><span class=\"schedule image-cell\" qa-label=\"dailyLimitFutureCell\">Scheduled to change to {{limitType.limitInterval.Daily.Future | noFractionCurrency}} on {{limitType.limitInterval.Daily.FutureDateStr}}</span></div></div><div class=\"body-cell\"><div class=\"image-row\"><span class=\"image-cell\" qa-label=\"monthlyLimitCell\">{{limitType.limitInterval.Monthly.Effective | noFractionCurrency}}</span> <button class=\"edit\" ng-click=\"events.editLimit(false, limitType)\" qa-label=\"monthlyLimitEditButton\"><strong>Edit</strong></button></div><div ng-if=\"limitType.limitInterval.Monthly.ShowFuture\" class=\"image-row\"><span class=\"schedule image-cell\" qa-label=\"monthlyLimitFutureCell\">Scheduled to change to {{limitType.limitInterval.Monthly.Future | noFractionCurrency}} on {{limitType.limitInterval.Monthly.FutureDateStr}}</span></div></div></div></div></div><div class=\"tvg-dialog-filter\" ng-if=\"data.limitEditor\"></div><limit-editor ng-if=\"data.limitEditor\"><edit-info><span class=\"cell\"></span><div class=\"cell\"><span><strong>Edit - {{depositLimitModel.depositLimitTypeName}} Card</strong></span><div class=\"limit-notification\"><span class=\"icon-input-error\" ng-if=\"data.limitError\"></span> <span ng-if=\"data.limitError\">{{data.limitErrorMessage}}</span></div></div></edit-info><edit-input><span class=\"cell\"><strong>$</strong></span><div class=\"cell\"><div class=\"align-left\"><input class=\"limit-amount\" name=\"limit-value\" ng-min=\"{{depositLimitModel.min||0}}\" ng-model=\"depositLimitModel.amount\" ng-required=\"true\" ng-change=\"events.validateLimitAmount()\" ng-enter=\"events.saveLimit()\" qa-label=\"depositLimitModelInput\"></div><div class=\"align-right\"><button class=\"cancel\" ng-click=\"events.cancelLimitEdition()\" qa-label=\"depositLimitModelCancelButton\"><strong>Cancel</strong></button> <button class=\"save\" ng-disabled=\"data.limitError\" ng-click=\"events.saveLimit()\" qa-label=\"depositLimitModelSaveButton\"><strong>Save</strong></button></div></div></edit-input></limit-editor></div><div ng-if=\"events.unableToFetchLimits() && (data.selectedPayOption.ftype === 'IBC' || data.selectedPayOption.ftype === 'ACH' || data.selectedPayOption.ftype === 'CC' || data.selectedPayOption.ftype === 'APPL')\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'ManagementBetcashUnableToFetchLimits' | CMSValue : null}}</dw-info-dialog></div></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/new-payment-method.html',
    "<div class=\"table\"><div class=\"row\"><new-method-add class=\"cell\"><button name=\"add-card\" ng-click=\"data.newCardForm = true\"><span class=\"add\"></span> <span>Add a new credit or debit card</span></button></new-method-add><new-method-option class=\"cell\"><span>We accept</span><div class=\"row\"><span class=\"visa-icon\"></span> <span class=\"mastercard-icon\"></span></div></new-method-option></div></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-method-card.html',
    "<div class=\"payment-management-option-main payment-management-block-grid\"><div class=\"payment-management-icon\"><div class=\"credit-card__placeholder\"></div></div><div class=\"payment-management-info\"><ul><li><strong ng-if=\"$ctrl.card.ftype === 'CC'\" ng-bind=\"$ctrl.card.typeName + ' Card'\"></strong> <strong ng-if=\"$ctrl.card.ftype === 'ACH'\" ng-bind=\"::$ctrl.card.bankName\"></strong></li><li ng-if=\"$ctrl.card.ftype === 'CC'\">{{\"xxxx-xxxx-xxxx-\" + $ctrl.card.cardNumber}}</li><li ng-if=\"$ctrl.card.ftype === 'ACH'\">*****{{$ctrl.sliceCard({number: $ctrl.card.bankAccNumber})}}</li><li ng-if=\"$ctrl.card.ftype === 'CC'\">Expires {{$ctrl.card.expirationDate}}</li></ul></div><a ng-if=\"$ctrl.card.ftype === 'CC'\" class=\"payment-management-close\" href ng-click=\"$ctrl.removeCard({card: card})\"><i class=\"tvg-icon-close\"></i></a></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-method-on-file-list.html',
    "<div class=\"field\"><payment-method-on-file-option ng-attr-card=\"card\" ng-attr-on-edit-card-action=\"events.showEditCardConfirmModal(card)\" ng-attr-on-go-to-deposit=\"events.goToDeposit(card, $index)\" ng-attr-on-remove-card-action=\"events.showRemoveCardConfirmModal(card)\" ng-attr-index=\"$index\" ng-repeat=\"card in data.selectedPayOption.onFile track by $index\"></payment-method-on-file-option><div ng-if=\"data.selectedPayOption.onFile.length === 0\"><p class=\"text-center\" ng-if=\"data.selectedPayOption.ftype === 'IBC'\" ng-bind=\"('noAccountsFound' | CMSLabels: 'dmaManagementLabels')\"></p><p class=\"text-center\" ng-if=\"data.selectedPayOption.ftype === 'CC'\" ng-bind=\"('no-cards-found' | CMSLabels: 'dmaDepositLabels')\"></p></div></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-method-on-file-option.html',
    "<div class=\"payment-management-option\" ng-class=\"{'payment-management-option--expired': card.isExpired}\" ng-controller=\"ManagePaymentMethodsController\" qa-label=\"paymentManagementOption\"><span ng-if=\"card.isExpired\" class=\"expired-card-label\">{{'expired-card' | CMSLabels: 'dmaDepositLabels'}} </span><span ng-if=\"card.IsPending\" class=\"expired-card-label\">{{'pendingAccount' | CMSLabels: 'dmaManagementLabels'}}</span><payment-method-card card=\"card\" remove-card=\"onRemoveCardAction(card)\" slice-card=\"events.slicedCard(number)\"></payment-method-card><ul class=\"payment-management-action-list\"><li><a href class=\"payment-management-action payment-management-action--primary\" ng-click=\"onGoToDeposit({index: index, card: card})\" qa-label=\"paymentManagementActionDepositButton\">Deposit</a></li><li ng-if=\"card.ftype === 'CC'\"><a href class=\"payment-management-action payment-management-action--secondary\" ng-click=\"onEditCardAction({card: card})\" qa-label=\"paymentManagementActionEditDetailsButton\">Edit Details</a></li></ul></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-methods-type-selector.html',
    "<payment-methods-options-container><payment-methods-option ng-repeat=\"option in data.paymentMethodsOptions\" ng-click=\"data.selectedPayOption = option; events.resetDataModel()\" ng-class=\"{selected:data.selectedPayOption.name == option.name}\">{{option.name}}</payment-methods-option></payment-methods-options-container>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/titles.html',
    "<h2 class=\"dma-section-title\" ng-if=\"$ctrl.type === 'CC'\"><span ng-bind=\"('creditCardTitle' | CMSLabels: 'dmaManagementLabels')\"></span> <a class=\"dma-section-link\" href ng-click=\"$ctrl.redirectAdd({type: $ctrl.type})\" ng-bind=\"('addNewCardLink' | CMSLabels: 'dmaManagementLabels')\" qa-label=\"addNewCCardLink\"></a></h2><h2 class=\"dma-section-title\" ng-if=\"$ctrl.type === 'IBC'\"><span ng-bind=\"('betCashTitle' | CMSLabels: 'dmaManagementLabels')\"></span><div class=\"dma-section-link\"><a href ng-click=\"events.redirectToAddNewCard($ctrl.type)\" ng-bind=\"('addNewAccountLink' | CMSLabels: 'dmaManagementLabels')\" qa-label=\"addNewAccountLink\"></a> <span ng-if=\"!njxIntegration\" ng-bind=\"('submit' | CMSLabels: 'dmaManagementLabels')\"></span> <a ng-if=\"!njxIntegration\" target=\"_blank\" ng-href=\"{{('linkBetcash' | CMSLabels: 'dmaManagementLabels')}}\" ng-bind=\"('BetcashAgreement' | CMSLabels: 'dmaManagementLabels')\" qa-label=\"BetcashAgreementLink\"></a><div></div></div></h2><p ng-if=\"$ctrl.type === 'IBC' && $ctrl.length > 0\" class=\"disclaimer\" ng-bind-html=\"('callSupport' | CMSLabels: 'dmaManagementLabels')\"></p>"
  );


  $templateCache.put('src/templates/managePaymentMethods/manage-payment-methods.html',
    "<div class=\"tvg-deposit\" name=\"managePaymentMethodsDiv\" ng-controller=\"ManagePaymentMethodsController\" ng-class=\"{loading: data.loading}\"><deposit-options-container class=\"dma-nav dma-nav-tabs\"><deposit-option ng-repeat=\"option in data.paymentMethodsOptions track by $index\" ng-click=\"events.selectOption(option)\" ng-class=\"{selected:data.selectedPayOption.ftype === option.ftype}\"><span qa-label=\"{{::option.ftype}}\">{{::option.name}}</span></deposit-option></deposit-options-container><div class=\"before-notification\"></div><dw-info-dialog ng-if=\"data.errorPaymentRestrictions && !data.loading\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\">{{'depositInitialDataErrorMessage' | CMSValue : null}}</dw-info-dialog><form class=\"deposit-form\" name=\"depositFrm\" ng-if=\"!data.errorPaymentRestrictions && !data.loading\" ng-submit=\"data.newCardForm ? events.addNewCard(depositFrm): data.editCardForm ? events.editCard(depositFrm) : null\" novalidate><payment-titles type=\"data.selectedPayOption.ftype\" length=\"data.selectedPayOption.onFile.length\" redirect-add=\"events.redirectToAddNewCard(type)\"></payment-titles><div class=\"payment-method-container\"><payment-method-on-file-list ng-if=\"(data.selectedPayOption.ftype !== 'IBC' || !data.unableToFetchBankAccounts)\n" +
    "     && (data.selectedPayOption.ftype !== 'CC' || !data.unableToFetchCardsOnFile)\"></payment-method-on-file-list><div ng-if=\"data.selectedPayOption.ftype === 'IBC' && data.unableToFetchBankAccounts\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'ManagementBetcashUnableToFetchBankAccounts' | CMSValue : null}}</dw-info-dialog></div><div ng-if=\"data.selectedPayOption.ftype === 'CC' && data.unableToFetchCardsOnFile\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'ManagementBetcashUnableToFetchCardsOnFile' | CMSValue : null}}</dw-info-dialog></div><deposit-limits ng-if=\"data.showLimits\"></deposit-limits></div><div ng-if=\"data.editCardForm\" class=\"payment-method-container\"><div class=\"form-fields\" ng-repeat=\"field in data.forms['NEW']['CC']\"><div ng-include=\"'src/templates/deposit/fields/'+field+'.html'\"></div></div><div class=\"field\"><button class=\"submit add-payment\" ng-disabled=\"data.savingCard\" type=\"submit\"><strong>Edit credit card details</strong></button><p ng-if=\"!notifyErrors\" ng-show=\"data.showInvalidFormMessage\" ng-class=\"{show: data.showInvalidFormMessage}\" class=\"js-error-label error-label fade-msg text-centered\">This form contains errors. Please fix all errors before continuing.</p></div></div></form></div>"
  );


  $templateCache.put('src/templates/transfer/fields/transfer-amount-input.html',
    "<div class=\"table\" ng-class=\"{ 'dma-amount-table' : $root.product == 'njx' }\" qa-label=\"dmaAmountTable\"><div class=\"row\"><span class=\"cell title\">I want to transfer $</span> <span class=\"cell\"></span> <span class=\"cell\"><div ng-if=\"transferFrm.amount.$error.min\" class=\"js-error-label error-label minimum\" ng-class=\"{invalidAmount: transferFrm.amount.$invalid && transferFrm.amount.$dirty}\">Minimum {{(transferDataModel.min) | currency}}</div><div ng-if=\"transferFrm.amount.$error.max\" class=\"js-error-label error-label maximum\" ng-class=\"{invalidAmount: transferFrm.amount.$invalid && transferFrm.amount.$dirty}\">Maximum {{(transferDataModel.max) | currency}}</div></span></div><div class=\"row\"><span class=\"cell w160\"><toggle-options><button ng-class=\"{selected: transferDataModel.amount == data.availableAmountOptions[0]}\" class=\"amount-button\" type=\"button\" ng-click=\"transferDataModel.amount=data.availableAmountOptions[0];\" ng-disable=\"data.loading\">${{data.availableAmountOptions[0]}}</button> <button ng-class=\"{selected: transferDataModel.amount == data.availableAmountOptions[1]}\" class=\"amount-button\" type=\"button\" ng-click=\"transferDataModel.amount=data.availableAmountOptions[1];\" ng-disable=\"data.loading\">${{data.availableAmountOptions[1]}}</button> <button ng-class=\"{selected: transferDataModel.amount == data.availableAmountOptions[2]}\" class=\"amount-button\" type=\"button\" ng-click=\"transferDataModel.amount=data.availableAmountOptions[2];\" ng-disable=\"data.loading\">${{data.availableAmountOptions[2]}}</button></toggle-options></span><span class=\"cell minw30\">or <span class=\"amount-dollar-label\">$</span></span> <span class=\"cell\"><input class=\"amount\" name=\"amount\" type=\"number\" placeholder=\"Other Amount\" min=\"{{transferDataModel.min}}\" max=\"{{transferDataModel.max}}\" maxlength=\"9\" step=\"0.01\" ng-model=\"transferDataModel.amount\" ng-model-options=\"{debounce: 500}\" ng-required=\"true\" ng-disable=\"data.loading\" restrict-chars qa-label=\"transferFundsExchange\"></span></div></div>"
  );


  $templateCache.put('src/templates/transfer/fields/transfer-source-destination.html',
    "<div class=\"form-fields\"><div class=\"field\"><span class=\"input-container\"><select-container class=\"others\"><select class=\"card\" name=\"slcOrigin\" ng-disable=\"data.loading\" ng-model=\"transferDataModel.source\" ng-options=\"option.label for option in data.optionsAccounts\" ng-change=\"events.selectSource()\" qa-label=\"exchangeFromSelect\"><option value=\"\" disabled=\"disabled\">{{'depositAchOnFileSelectionLabel' | CMSValue : null}}</option></select> <span qa-label=\"transferSourceLabel\">{{transferDataModel.source.label || 'From' }}</span></select-container></span></div><div class=\"field\"><select-container><select class=\"ng-pristine ng-valid ng-touched\" name=\"slcDestination\" ng-disable=\"data.loading\" ng-model=\"transferDataModel.destination\" ng-options=\"option.label for option in data.optionsAccounts\" ng-change=\"events.selectDestination()\" qa-label=\"exchangeToSelect\"><option value=\"\" disabled=\"disabled\">{{'depositAchOnFileSelectionLabel' | CMSValue : null}}</option></select> <span qa-label=\"transferDestinationLabel\">{{transferDataModel.destination.label || 'To' }}</span></select-container></div></div>"
  );


  $templateCache.put('src/templates/transfer/transfer.html',
    "<div class=\"tvg-deposit tvg-deposit-transfer\" ng-controller=\"TransferController\"><div ng-class=\"{'loading': data.loading}\"></div><dw-info-dialog ng-if=\"data.errorDepositRestrictions\" ng-bind=\"data.message\"></dw-info-dialog><form ng-if=\"!data.errorDepositRestrictions\" class=\"deposit-form\" name=\"transferFrm\" ng-submit=\"events.makeTransfer(transferFrm)\" ng-class=\"{loading: data.makingTransfer}\"><transfer-amount-input></transfer-amount-input><div class=\"disclaimer\">Although you can access both 4NJbets and the Betfair Exchange, you'll need to transfer funds between them in order to bet.</div><transfer-source-destination></transfer-source-destination><div ng-if=\"transferDataModel.isPending != true\" class=\"field\"><button class=\"submit add-funds\" ng-disabled=\"(data.makingTransfer || !transferDataModel.source || !transferDataModel.destination || !transferDataModel.amount || !transferFrm.$valid || data.loading)\" type=\"submit\"><strong>Transfer funds</strong></button><p ng-if=\"!notifyErrors\" ng-show=\"data.showInvalidFormMessage\" ng-class=\"{show: data.showInvalidFormMessage}\" class=\"js-error-label error-label fade-msg text-centered\">This form contains errors. Please fix all errors before continuing.</p></div></form></div>"
  );


  $templateCache.put('src/templates/withdraw/desktop/pendingWithdrawals/pending-withdraw-element.html',
    "<li qa-label=\"pending-withdrawal-element\"><!-- Cancel Confirmation --><div class=\"pending-messages warning-message\" qa-label=\"pending-withdrawal-cancel-confirmation\" ng-show=\"showConfirmation\"><div class=\"warning-info\" qa-label=\"pending-withdrawal-cancel-confirmation-message\"><i class=\"tvg-icon-warning-2\"></i> <strong>Are you sure you want to cancel this withdraw?</strong></div><div class=\"action-buttons\"><button class=\"warning-message-cancel\" ng-click=\"undoCancel()\" qa-label=\"pending-withdrawal-cancel-button\" ng-disabled=\"loading\">Cancel</button> <button class=\"warning-message-confirm\" ng-click=\"cancelPendingWithdraw()(item.withdrawalId)\" qa-label=\"pending-withdrawal-confirm-button\" ng-disabled=\"loading\">Confirm</button></div></div><!-- Messages --><div class=\"pending-messages feedback-message animate-hide\" qa-label=\"pending-withdrawal-feedback-message\" ng-show=\"showMessage\" ng-class=\"{'error-message': isError || isCriticalError, 'success-message': isSuccess, 'warning-message': isWarning}\"><i class=\"tvg-icon-success animate-hide\" ng-show=\"isSuccess\"></i> <i class=\"tvg-icon-danger animate-hide\" ng-show=\"isError || isWarning\"></i><div qa-label=\"pending-withdrawal-feedback-error-message\" class=\"animate-hide\" ng-show=\"isError\" ng-bind-html=\"errorMessage\"></div><div qa-label=\"pending-withdrawal-feedback-success-message\" class=\"animate-hide\" ng-show=\"isSuccess\">{{successMessage}}</div><div qa-label=\"pending-withdrawal-feedback-warning-message\" class=\"animate-hide\" ng-show=\"isWarning\">{{warningMessage}}</div><i class=\"tvg-icon-times close-button\" ng-click=\"onRemoveMessage()\" qa-label=\"pending-withdrawal-feedback-message-close\"></i></div><!-- Withdrawal content --><div qa-label=\"pending-withdrawal-element-date\" class=\"pending-withdraw-datetime\" ng-bind=\"item.DateInitiated | date :'MM/dd/yyyy'\"></div><div qa-label=\"pending-withdrawal-element-type\" class=\"pending-withdraw-type\" ng-bind=\"getBetTypeName(item.paymentType)\"></div><div ng-if=\"!njxIntegration\" qa-label=\"pending-withdrawal-element-accNumber\" class=\"pending-withdraw-account\" ng-bind=\"$root.user.accountNumber\"></div><div qa-label=\"pending-withdrawal-element-amount\" class=\"pending-withdraw-amount\" ng-bind=\"'$' + item.amount\"></div><div class=\"pending-withdraw-cancel\"><button qa-label=\"pending-withdrawal-element-cancel-button\" id=\"cancelWithdraw\" class=\"pending-withdrawals-button\" ng-show=\"!showConfirmation && showCancelButton && !item.processing\" ng-click=\"onCancel()\">Cancel Withdraw</button></div></li>"
  );


  $templateCache.put('src/templates/withdraw/desktop/pendingWithdrawals/withdraw-pending-requests.html',
    "<div class=\"panel\" qa-label=\"withdraw-pending-requests\" ng-if=\"showPendingWithdrawls\" ng-controller=\"WithdrawCancelController\" ng-class=\"{'component-loading': model.isLoading}\"><h2>Pending Request</h2><div class=\"panel-body\"><table class=\"table pending-requests-table no-margin\" ng-if=\"model.withdrawPendingList.length && !model.errorFetchingPending\"><thead><tr><th>Date</th><th>Type</th><th ng-if=\"!njxIntegration\">Account #</th><th>Amount</th><th></th></tr></thead></table><ul qa-label=\"pending-withdrawals-elements-container\" class=\"pending-withdrawals-information\" ng-if=\"model.withdrawPendingList.length && !model.errorFetchingPending\"><pending-withdraw-element ng-repeat=\"item in model.withdrawPendingList track by item.withdrawalId\" item=\"item\" loading=\"model.isLoading\" cancel-pending-withdraw=\"events.cancelPendingWithdraw\"></pending-withdraw-element></ul><!-- Message with no withdrawals --> <label qa-label=\"pending-withdrawals-no-elements\" class=\"centered-label\" ng-if=\"model.withdrawPendingList.length == 0 && !model.isLoading && !model.errorFetchingPending\">No more pending withdrawals</label><!-- Error message when there's an error fetching the pending withdrawals--> <label qa-label=\"pending-withdrawals-error-fetching\" class=\"centered-label\" ng-if=\"model.errorFetchingPending\">An error occurred while fetching your pending withdrawals</label></div></div><h2 ng-if=\"showPendingWithdrawls\">New Request</h2><!-- This should disappear when the withdraws section is remade for desktop version-->"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-account-info.html',
    "<!-- Account info --><div ng-if=\"!isDesktop\"><div class=\"account-info table\"><div class=\"row\" ng-if=\"!$root.isFdrApp\"><span class=\"cell\">Account #</span> <span class=\"cell\">Balance</span> <span class=\"cell\">Available to Withdraw</span></div><div class=\"row\" ng-if=\"$root.isFdrApp\"><span class=\"cell\">Account</span> <span class=\"cell\">Balance</span> <span class=\"cell\">Valid Withdraw</span></div><div class=\"row\"><span qa-label=\"account-number\" class=\"cell\">{{ data.accountId || \"N/A\" }}</span> <span qa-label=\"account-balance\" class=\"cell\">{{ data.balance || \"$--\" }}</span> <span qa-label=\"available-balance\" class=\"cell\">{{ (data.availableBalance | currency: '$') || \"$--\" }}</span></div></div><tvg-collapse qa-label=\"max-withdraw-info\" ng-if=\"data.balance && data.balance !== (data.availableBalance | currency: '$')\" class=\"info-message\" ng-attr-title=\"{{'maxWithdrawLessTotalBalanceTitle' | CMSLabels: 'withdrawLabels'}}\"><p qa-label=\"max-withdraw-info-message\" ng-bind-html=\"'maxWithdrawLessTotalBalance' | CMSLabels: 'withdrawLabels' | trust\"></p></tvg-collapse></div><div ng-if=\"isDesktop\"><dw-info-message qa-label=\"max-withdraw-info\" ng-if=\"data.balance && data.balance !== (data.availableBalance | currency: '$')\" ng-attr-title=\"{{'maxWithdrawLessTotalBalanceTitle' | CMSLabels: 'withdrawLabels'}}\" ng-attr-message=\"{{'maxWithdrawLessTotalBalance' | CMSLabels: 'withdrawLabels'}}\"></dw-info-message><dw-info-message qa-label=\"withdrawNoCardsAvailable-info\" ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD' && data.cardsOnFile.length === 0\" ng-attr-title=\"{{'withdrawNoCardsAvailableTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'withdrawNoCardsAvailable' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message><dw-info-message qa-label=\"chequeRequestProcessing-info\" ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\" ng-attr-title=\"{{'chequeRequestProcessingTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'chequeRequestProcessing' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message><div class=\"account-info table dma-account-info\"><table><thead><tr><th ng-bind-html=\"'balanceLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-bind-html=\"'availableToWithdrawLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'BETCASH'\" ng-bind-html=\"'tvgBetCashAccountLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\" ng-bind-html=\"'addressLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD'\" ng-bind-html=\"'debitCardLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'PAY' && data.providerEmail\" ng-bind-html=\"providerEmailLabel\"></th><th ng-bind-html=\"'withdrawAmountLabel' | CMSLabels: 'withdrawLabels' | trust\"></th></tr></thead><tbody><tr qa-label=\"error-message\" ng-if=\"withdrawFrm.newAmount.$invalid && (withdrawFrm.newAmount.$touched || withdrawFrm.$submitted)\" class=\"error-row\"><td colspan=\"{{ showThreeColumns() ? '3' : '4' }}\"><span class=\"alert-box red\" ng-bind=\"getInvalidWithdrawalMessage(withdrawFrm.newAmount, data.minWithdraw)\"></span></td></tr><tr><td qa-label=\"account-balance\" ng-bind=\"data.balance || '$--'\"></td><td qa-label=\"available-balance\" ng-bind=\"(data.availableBalance | currency: '$') || '$--'\"></td><td ng-if=\"data.selectedWithdrawOption.id === 'PAY' && data.providerEmail\"><div qa-label=\"paypal-email-value\">{{data.providerEmail}}</div></td><td ng-if=\"!showAddressForPayment()\" class=\"select-cell\"><!-- tvg bet cash accounts select --><div class=\"field select-field\" ng-if=\"data.selectedWithdrawOption.id === 'BETCASH'\"><span ng-if=\"data.availableBetCashAccounts.length > 0\"><select-container><select qa-label=\"betcash-bank-selector\" ng-model=\"data.selectedBetCashAccount\" ng-options=\"option.name for option in data.availableBetCashAccounts\" ng-init=\"events.initDropdown(data.selectedWithdrawOption.id)\" ng-change=\"events.setCurrentBetCash(data.selectedBetCashAccount)\"></select> <span ng-bind=\"data.selectedBetCashAccount.name\"></span></select-container></span><span ng-if=\"data.availableBetCashAccounts.length == 0\">No Bet Cash Accounts Available.</span></div><!-- check addresses select --><div class=\"field select-field\" ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\"><span ng-if=\"data.availableCheckOptions.length > 0\"><select-container><select qa-label=\"check-address-selector\" ng-model=\"data.selectedAddressSection\" ng-options=\"option.name for option in data.availableCheckOptions\" ng-change=\"events.toggleHomeMailMethods(data.selectedAddressSection)\" ng-init=\"events.initDropdown(data.selectedWithdrawOption.id)\"></select> <span ng-bind=\"data.selectedAddressSection.name\"></span></select-container></span><span ng-if=\"data.availableCheckOptions.length == 0\" ng-bind-html=\"'noAddressAvailableLabel' | CMSLabels: 'withdrawLabels' | trust\"></span></div><!-- tvg credit card select --><div class=\"field select-field\" ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD'\"><span ng-if=\"data.cardsOnFile.length > 0\"><select-container><select qa-label=\"betcash-bank-selector\" ng-model=\"data.selectedCardOnFile\" ng-options=\"option.name for option in data.cardsOnFile\" ng-init=\"events.initDropdown(data.selectedWithdrawOption.id)\" ng-change=\"events.setCurrentCardOnFile(data.selectedCardOnFile)\"></select> <span ng-bind=\"data.selectedCardOnFile.name\"></span></select-container></span></div></td><td class=\"amount-cell\"><div class=\"field amount-input\"><div class=\"input-container\"><input qa-label=\"withdraw-amount\" class=\"withdraw-amount-input\" name=\"newAmount\" type=\"number\" max=\"{{ getMaxWithdrawValue() }}\" min=\"{{ data.minWithdraw }}\" step=\"0.01\" num-length=\"30\" ng-model=\"withdrawDataModel.amount\" ng-model-options=\"{ debounce: 300 }\" ng-required=\"true\" pattern=\"^\\d+(?:\\.\\d{1,2})?$\" placeholder=\"$0.00\" ng-blur=\"events.changeAmount(withdrawFrm.amount.$touched, withdrawFrm.amount.$valid)\"></div></div><div class=\"btn-container\"><button qa-label=\"withdraw-button\" class=\"submit withdraw-btn\" type=\"submit\" ng-if=\"(data.selectedWithdrawOption.id !== 'BETCASH' || data.availableBetCashAccounts.length > 0)\"><strong><i class=\"tvg-icon-login\"></i> <span ng-bind-html=\"'authorizeWithdrawalBtn' | CMSLabels: 'withdrawLabels' | trust\"></span></strong></button></div></td></tr><tr ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\"><td></td><td></td><td class=\"check-address\"><p qa-label=\"check-address-selected\" ng-if=\"data.selectedAddressSection\" ng-bind=\"data.selectedAddressSection.address\"></p></td><td></td></tr><tr ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD'\"><td></td><td></td><td></td><td><label class=\"fee\" ng-bind-html=\"'withdraw-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label><ul qa-label=\"withdraw-summary\" class=\"deposit__summary\"><li qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('withdraw-summary-amount' | CMSLabels: 'dmaDepositLabels') + ' ' +\n" +
    "                            ((withdrawDataModel.amount | currency: '$') || '$--') | trust )\"></li><li qa-label=\"deposit-summary-fee\" ng-bind-html=\"(('withdraw-summary-fee' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                            ((0 | currency: '$') || '$--') | trust ) + ('</span>')\"></li><strong qa-label=\"deposit-summary-total\" ng-bind-html=\"(('withdraw-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                            ((withdrawDataModel.amount | currency: '$') || '$--') | trust ) + ('</span>')\"></strong></ul></td></tr></tbody></table></div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-amount-input.html',
    "<div class=\"field withdraw-input-ctn withdraw-amount-input clearfix\" ng-if=\"!isDesktop\" ng-class=\"{\n" +
    "      inputIsInvalid: $root.isFdrApp && withdrawFrm.amount.$invalid && (withdrawFrm.amount.$touched || withdrawFrm.$submitted),\n" +
    "      inputIsFocused: $root.isFdrApp && inputIsFocused\n" +
    "    }\"><div class=\"label withdraw-amount-label\"><span>Withdraw amount (min. $2)</span></div><div class=\"input-container\"><span>$</span> <input qa-label=\"withdraw-amount\" class=\"withdraw-amount-input\" name=\"amount\" type=\"number\" max=\"{{getMaxWithdrawValue()}}\" min=\"{{data.minWithdraw}}\" step=\"0.01\" num-length=\"30\" ng-model=\"withdrawDataModel.amount\" ng-required=\"true\" ng-pattern=\"data.numberPattern\" placeholder=\"00.00\" money-formater restrict-chars ng-focus=\"inputIsFocused = true; events.started()\"></div><span qa-label=\"error-message\" class=\"js-error-label error-label\" ng-if=\"withdrawFrm.amount.$invalid && (withdrawFrm.amount.$touched || withdrawFrm.$submitted)\" ng-bind=\"getInvalidWithdrawalMessage(withdrawFrm.amount, data.minWithdraw)\"></span></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-betcash-selector.html',
    "<div ng-if=\"!isDesktop\"><section-title ng-if=\"!$root.isFdrApp\" title=\"BetCash Accounts\" index=\"\"></section-title><section-title ng-if=\"$root.isFdrApp\" title=\"Echeck Accounts\" index=\"\"></section-title><div qa-label=\"betcash-bank-selector\" class=\"deposit-card-options\" ng-if=\"data.availableBetCashAccounts.length > 0\"><ul><li qa-label=\"betcash-bank-option\" ng-repeat=\"card in data.availableBetCashAccounts track by card.achId\" class=\"card\"><label ng-class=\"{'active': data.selectedBetCashAccount === card}\"><strong ng-bind=\"::($root.isFdrApp ? card.bankName.toLowerCase() : card.bankName)\"></strong><div ng-bind=\"::card.name\"></div><input type=\"radio\" ng-model=\"data.selectedBetCashAccount\" ng-change=\"events.setCurrentBetCash(data.selectedBetCashAccount)\" ng-value=\"card\"></label></li></ul></div><div class=\"field\" ng-if=\"data.availableBetCashAccounts.length === 0\"><span>{{ $root.isFdrApp ? 'No Echeck Accounts Available.' : 'No Bet Cash Accounts Available.'}}</span></div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-card-selector.html',
    "<div ng-if=\"!isDesktop\"><section-title title=\"Select debit card\" index=\"\"></section-title><div qa-label=\"withdraw-card-selector\" class=\"deposit-card-options\" ng-if=\"data.cardsOnFile.length > 0\"><ul qa-label=\"cardsList\" ng-init=\"data.pageSetFromParams ? null : data.selectedCardOnFile = data.cardsOnFile[0]; events.setCurrentCardOnFile(data.selectedCardOnFile) \"><li qa-label=\"ccCardsOnFile\" ng-repeat=\"card in data.cardsOnFile track by card.id\" class=\"card\"><label qa-label=\"cardInfo\" ng-class=\"{'active': data.selectedCardOnFile === card ||\n" +
    "                                    (card.ftype === 'CC' && data.selectedCardOnFile.id === card.id) }\"><strong ng-bind=\"::card.network\"></strong><div><span ng-if=\"card.isExpired\" class=\"expired-card-label\">{{'expired-card' | CMSLabels: 'dmaDepositLabels'}} </span><span ng-bind=\"::card.cardNumberExt\"></span> (<span ng-bind=\"::card.expirationDate\"></span>)</div><input qa-label=\"cardSelection\" type=\"radio\" ng-model=\"data.selectedCardOnFile\" ng-change=\"events.setCurrentCardOnFile(card)\" ng-value=\"card\"></label></li></ul></div><dw-info-message qa-label=\"withdrawNoCardsAvailable-info\" ng-if=\"data.cardsOnFile.length === 0\" ng-attr-title=\"{{'withdrawNoCardsAvailableTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'withdrawNoCardsAvailable' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-home-mail-selector.html',
    "<section-title index=\"\" title=\"Select Address\" ng-if=\"!isDesktop\"></section-title><div ng-if=\"!isDesktop\"><dw-info-message qa-label=\"chequeRequestProcessing-info\" ng-attr-title=\"{{'chequeRequestProcessingTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'chequeRequestProcessing' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message><div qa-label=\"check-address-selector\" class=\"deposit-card-options\" ng-if=\"data.availableCheckOptions.length > 0\"><ul><li qa-label=\"check-address-option\" ng-repeat=\"card in data.availableCheckOptions\" class=\"card\" ng-if=\"card.address && card.address.length\"><label ng-class=\"{'active': data.selectedAddressSection.id == card.id}\"><strong ng-bind=\"::card.name\"></strong><div ng-bind=\"::card.address\"></div><input type=\"radio\" ng-model=\"data.selectedAddressSection\" ng-change=\"events.toggleHomeMailMethods(card)\" ng-value=\"card\"></label></li></ul></div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-provider-email.html',
    "<div ng-if=\"(data.selectedWithdrawOption.id === 'PAY' && data.providerEmail) && !isDesktop\" class=\"paypal-account-details\"><section-title title=\"{{$root.isFdrApp ? 'Paypal Account Details' : 'Details' }}\" index=\"\"></section-title><div qa-label=\"provider-email\"><strong ng-if=\"!$root.isFdrApp\" ng-bind-html=\"'email' | CMSLabels: 'paypalLabels' | trust\"></strong> <strong ng-if=\"$root.isFdrApp\">Email address set to: </strong>{{ data.providerEmail }}</div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-total-cost.html',
    "<div ng-if=\"!isDesktop\"><section-title title=\"{{'withdraw-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust}}\" index=\"\"></section-title><ul qa-label=\"withdraw-summary\" class=\"deposit__summary disabled_fdr_styles withdraw-left-padding\"><li qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('withdraw-summary-amount' | CMSLabels: 'dmaDepositLabels') + ' ' +\n" +
    "                          ((withdrawDataModel.amount | currency: '$') || '$--') | trust )\"></li><li qa-label=\"deposit-summary-fee\" ng-bind-html=\"(('withdraw-summary-fee' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                          ((0 | currency: '$') || '$--') | trust ) + ('</span>')\"></li><strong qa-label=\"deposit-summary-total\" class=\"bold\" ng-bind-html=\"(('withdraw-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                          ((withdrawDataModel.amount | currency: '$') || '$--') | trust ) + ('</span>')\"></strong></ul></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-type-selector.html',
    "<withdraw-options-container class=\"dma-nav dma-nav-tabs\"><withdraw-option ng-repeat=\"option in data.withdrawOptions\" qa-label=\"{{option.qalabel}}\" ng-click=\"events.toggleWithdrawOptions(option)\" ng-class=\"{selected:data.selectedWithdrawOption == option}\"><span ng-bind=\"option.name\"></span></withdraw-option></withdraw-options-container>"
  );


  $templateCache.put('src/templates/withdraw/withdraw-cancel.html',
    "<div class=\"tvg-deposit\" ng-controller=\"WithdrawCancelController\" ng-class=\"{loading: data.isLoading}\"><div class=\"before-notification\"></div><div class=\"withdraw-cancel-container\" ng-if=\"!data.isLoading\"><dw-info-dialog><p>Changed your mind?</p>Cancel pending withdrawals for immediate access to your funds.</dw-info-dialog><table class=\"table-withdrawals\" ng-if=\"data.withdrawPendingList.length\"><tr><th>DATE</th><th>TYPE</th><th>AMOUNT</th><th>ACTION</th></tr><tr ng-repeat=\"item in data.withdrawPendingList\"><td ng-bind=\"item.transactionDate | date :'MM/dd/yyyy'\"></td><td ng-bind=\"item.paymentType\"></td><td ng-bind=\"item.amount | currency\"></td><td><button class=\"red\" ng-click=\"cancelPendingWithdraw(item.withdrawalId)\">Cancel</button></td></tr></table><label class=\"no-withdrawals-message\" ng-if=\"!data.withdrawPendingList.length\">No more pending withdrawals</label></div></div>"
  );


  $templateCache.put('src/templates/withdraw/withdraw-error.html',
    "<div class=\"handler-error-container\"><span class=\"image\"></span><h1 class=\"title\">Error!</h1><div class=\"message-container\"><h2><strong>This method of withdrawal doesn't seem to be going through.</strong></h2><p class=\"customer_service\" ng-bind-html=\"('widthdrawErrorDefault'| CMSValue : null) | trust\"></p></div></div>"
  );


  $templateCache.put('src/templates/withdraw/withdraw-success.html',
    "<div class=\"handler-success-container\"><span class=\"image\"></span><h1 class=\"title\">Success!</h1><div class=\"message-container\"><h2><strong>Withdrawal Request Successful.</strong></h2><p class=\"message\">{{withdraw.description}}<!--TODO: CMS--></p></div></div>"
  );


  $templateCache.put('src/templates/withdraw/withdraw.html',
    "<withdraw-pending-requests qa-label=\"pending-withdrawals\" class=\"withdraw-pending-requests-desktop\" ng-if=\"showPendingWithdrawals &&\n" +
    "        !data.isLoading && !data.errorFetchingData\"></withdraw-pending-requests><div ng-show=\"!data.showingFallback\" class=\"tvg-deposit\" ng-class=\"{loading: data.isLoading, 'njx-deposit': njxIntegration}\"><!-- Toggles between CHECK and BetCash option --><withdraw-type-selector></withdraw-type-selector><section ng-if=\"!data.unableToFetchProfile\" ng-class=\"{'loading sightline-loading': sightlineLoading}\"><sightline-enrollment ng-if=\"displays.isSightlineApiEnrollmentVisible()\" ng-controller=\"SightlineController\" qa-label=\"sln-api-enrollment\" ng-class=\"{'loading': data.isEnrollingCard}\"></sightline-enrollment></section><form novalidate qa-label=\"withdraw-form\" name=\"withdrawFrm\" ng-submit=\"events.withdraw(withdrawFrm)\" ng-if=\"(!data.isLoading && !data.errorFetchingData &&\n" +
    "            data.selectedWithdrawOption.id !== 'SLN' ||\n" +
    "            data.hasSightlineAccount) &&\n" +
    "            !payPalTVG3() &&\n" +
    "            !payPalNJX() &&\n" +
    "            !(data.selectedWithdrawOption.id === 'BETCASH' && data.unableToFetchBankAccounts) &&\n" +
    "            !(data.selectedWithdrawOption.id === 'CHECK' && data.unableToFetchProfile)\"><!-- Dynamically render fields depending on selected withdraw option --><div ng-repeat=\"field in data.forms[data.selectedWithdrawOption.id]\"><div ng-include=\"'src/templates/withdraw/fields/' + field + '.html'\"></div></div><!-- Withdraw button --> <button qa-label=\"withdraw-button\" ng-if=\"(data.selectedWithdrawOption.id != 'BETCASH' || data.availableBetCashAccounts.length > 0) && !isDesktop\" class=\"submit withdraw-btn\" type=\"submit\"><strong><i class=\"tvg-icon-lock\"></i> Authorize Withdrawal</strong></button></form><div ng-if=\"payPalTVG3()\" class=\"disclaimer paypal-disclaimer\" ng-bind-html=\"'tvg3Message' | CMSLabels: 'paypalLabels'\"></div><div class=\"disclaimer paypal-disclaimer\" ng-if=\"payPalNJX()\">Coming Soon</div><dw-info-dialog qa-label=\"fetching-error-message\" ng-if=\"!data.isLoading && (data.errorFetchingData || (data.selectedWithdrawOption.id === 'BETCASH' && data.unableToFetchBankAccounts))\" live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositsBetcashUnableToFetchBankAccounts' | CMSValue : null}}</dw-info-dialog><dw-info-dialog qa-label=\"fetching-error-message\" ng-if=\"!data.isLoading && (data.errorFetchingData ||\n" +
    "        ((data.selectedWithdrawOption.id === 'CHECK' || data.selectedWithdrawOption.id === 'SLN') && data.unableToFetchProfile))\" live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'withdrawUnableToFetchProfile' | CMSValue : null}}</dw-info-dialog></div><dw-info-dialog ng-if=\"!data.loading && !$root.isFdrApp && data.showingFallback\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\">{{'withdrawalNoPaymentMethodsAvailable' | CMSValue : null}}</dw-info-dialog>"
  );

}]);

angular.module('TVG.Withdraw').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('src/templates/withdraw/desktop/pendingWithdrawals/pending-withdraw-element.html',
    "<li qa-label=\"pending-withdrawal-element\"><!-- Cancel Confirmation --><div class=\"pending-messages warning-message\" qa-label=\"pending-withdrawal-cancel-confirmation\" ng-show=\"showConfirmation\"><div class=\"warning-info\" qa-label=\"pending-withdrawal-cancel-confirmation-message\"><i class=\"tvg-icon-warning-2\"></i> <strong>Are you sure you want to cancel this withdraw?</strong></div><div class=\"action-buttons\"><button class=\"warning-message-cancel\" ng-click=\"undoCancel()\" qa-label=\"pending-withdrawal-cancel-button\" ng-disabled=\"loading\">Cancel</button> <button class=\"warning-message-confirm\" ng-click=\"cancelPendingWithdraw()(item.withdrawalId)\" qa-label=\"pending-withdrawal-confirm-button\" ng-disabled=\"loading\">Confirm</button></div></div><!-- Messages --><div class=\"pending-messages feedback-message animate-hide\" qa-label=\"pending-withdrawal-feedback-message\" ng-show=\"showMessage\" ng-class=\"{'error-message': isError || isCriticalError, 'success-message': isSuccess, 'warning-message': isWarning}\"><i class=\"tvg-icon-success animate-hide\" ng-show=\"isSuccess\"></i> <i class=\"tvg-icon-danger animate-hide\" ng-show=\"isError || isWarning\"></i><div qa-label=\"pending-withdrawal-feedback-error-message\" class=\"animate-hide\" ng-show=\"isError\" ng-bind-html=\"errorMessage\"></div><div qa-label=\"pending-withdrawal-feedback-success-message\" class=\"animate-hide\" ng-show=\"isSuccess\">{{successMessage}}</div><div qa-label=\"pending-withdrawal-feedback-warning-message\" class=\"animate-hide\" ng-show=\"isWarning\">{{warningMessage}}</div><i class=\"tvg-icon-times close-button\" ng-click=\"onRemoveMessage()\" qa-label=\"pending-withdrawal-feedback-message-close\"></i></div><!-- Withdrawal content --><div qa-label=\"pending-withdrawal-element-date\" class=\"pending-withdraw-datetime\" ng-bind=\"item.DateInitiated | date :'MM/dd/yyyy'\"></div><div qa-label=\"pending-withdrawal-element-type\" class=\"pending-withdraw-type\" ng-bind=\"getBetTypeName(item.paymentType)\"></div><div ng-if=\"!njxIntegration\" qa-label=\"pending-withdrawal-element-accNumber\" class=\"pending-withdraw-account\" ng-bind=\"$root.user.accountNumber\"></div><div qa-label=\"pending-withdrawal-element-amount\" class=\"pending-withdraw-amount\" ng-bind=\"'$' + item.amount\"></div><div class=\"pending-withdraw-cancel\"><button qa-label=\"pending-withdrawal-element-cancel-button\" id=\"cancelWithdraw\" class=\"pending-withdrawals-button\" ng-show=\"!showConfirmation && showCancelButton && !item.processing\" ng-click=\"onCancel()\">Cancel Withdraw</button></div></li>"
  );


  $templateCache.put('src/templates/withdraw/desktop/pendingWithdrawals/withdraw-pending-requests.html',
    "<div class=\"panel\" qa-label=\"withdraw-pending-requests\" ng-if=\"showPendingWithdrawls\" ng-controller=\"WithdrawCancelController\" ng-class=\"{'component-loading': model.isLoading}\"><h2>Pending Request</h2><div class=\"panel-body\"><table class=\"table pending-requests-table no-margin\" ng-if=\"model.withdrawPendingList.length && !model.errorFetchingPending\"><thead><tr><th>Date</th><th>Type</th><th ng-if=\"!njxIntegration\">Account #</th><th>Amount</th><th></th></tr></thead></table><ul qa-label=\"pending-withdrawals-elements-container\" class=\"pending-withdrawals-information\" ng-if=\"model.withdrawPendingList.length && !model.errorFetchingPending\"><pending-withdraw-element ng-repeat=\"item in model.withdrawPendingList track by item.withdrawalId\" item=\"item\" loading=\"model.isLoading\" cancel-pending-withdraw=\"events.cancelPendingWithdraw\"></pending-withdraw-element></ul><!-- Message with no withdrawals --> <label qa-label=\"pending-withdrawals-no-elements\" class=\"centered-label\" ng-if=\"model.withdrawPendingList.length == 0 && !model.isLoading && !model.errorFetchingPending\">No more pending withdrawals</label><!-- Error message when there's an error fetching the pending withdrawals--> <label qa-label=\"pending-withdrawals-error-fetching\" class=\"centered-label\" ng-if=\"model.errorFetchingPending\">An error occurred while fetching your pending withdrawals</label></div></div><h2 ng-if=\"showPendingWithdrawls\">New Request</h2><!-- This should disappear when the withdraws section is remade for desktop version-->"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-account-info.html',
    "<!-- Account info --><div ng-if=\"!isDesktop\"><div class=\"account-info table\"><div class=\"row\" ng-if=\"!$root.isFdrApp\"><span class=\"cell\">Account #</span> <span class=\"cell\">Balance</span> <span class=\"cell\">Available to Withdraw</span></div><div class=\"row\" ng-if=\"$root.isFdrApp\"><span class=\"cell\">Account</span> <span class=\"cell\">Balance</span> <span class=\"cell\">Valid Withdraw</span></div><div class=\"row\"><span qa-label=\"account-number\" class=\"cell\">{{ data.accountId || \"N/A\" }}</span> <span qa-label=\"account-balance\" class=\"cell\">{{ data.balance || \"$--\" }}</span> <span qa-label=\"available-balance\" class=\"cell\">{{ (data.availableBalance | currency: '$') || \"$--\" }}</span></div></div><tvg-collapse qa-label=\"max-withdraw-info\" ng-if=\"data.balance && data.balance !== (data.availableBalance | currency: '$')\" class=\"info-message\" ng-attr-title=\"{{'maxWithdrawLessTotalBalanceTitle' | CMSLabels: 'withdrawLabels'}}\"><p qa-label=\"max-withdraw-info-message\" ng-bind-html=\"'maxWithdrawLessTotalBalance' | CMSLabels: 'withdrawLabels' | trust\"></p></tvg-collapse></div><div ng-if=\"isDesktop\"><dw-info-message qa-label=\"max-withdraw-info\" ng-if=\"data.balance && data.balance !== (data.availableBalance | currency: '$')\" ng-attr-title=\"{{'maxWithdrawLessTotalBalanceTitle' | CMSLabels: 'withdrawLabels'}}\" ng-attr-message=\"{{'maxWithdrawLessTotalBalance' | CMSLabels: 'withdrawLabels'}}\"></dw-info-message><dw-info-message qa-label=\"withdrawNoCardsAvailable-info\" ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD' && data.cardsOnFile.length === 0\" ng-attr-title=\"{{'withdrawNoCardsAvailableTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'withdrawNoCardsAvailable' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message><dw-info-message qa-label=\"chequeRequestProcessing-info\" ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\" ng-attr-title=\"{{'chequeRequestProcessingTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'chequeRequestProcessing' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message><div class=\"account-info table dma-account-info\"><table><thead><tr><th ng-bind-html=\"'balanceLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-bind-html=\"'availableToWithdrawLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'BETCASH'\" ng-bind-html=\"'tvgBetCashAccountLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\" ng-bind-html=\"'addressLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD'\" ng-bind-html=\"'debitCardLabel' | CMSLabels: 'withdrawLabels' | trust\"></th><th ng-if=\"data.selectedWithdrawOption.id === 'PAY' && data.providerEmail\" ng-bind-html=\"providerEmailLabel\"></th><th ng-bind-html=\"'withdrawAmountLabel' | CMSLabels: 'withdrawLabels' | trust\"></th></tr></thead><tbody><tr qa-label=\"error-message\" ng-if=\"withdrawFrm.newAmount.$invalid && (withdrawFrm.newAmount.$touched || withdrawFrm.$submitted)\" class=\"error-row\"><td colspan=\"{{ showThreeColumns() ? '3' : '4' }}\"><span class=\"alert-box red\" ng-bind=\"getInvalidWithdrawalMessage(withdrawFrm.newAmount, data.minWithdraw)\"></span></td></tr><tr><td qa-label=\"account-balance\" ng-bind=\"data.balance || '$--'\"></td><td qa-label=\"available-balance\" ng-bind=\"(data.availableBalance | currency: '$') || '$--'\"></td><td ng-if=\"data.selectedWithdrawOption.id === 'PAY' && data.providerEmail\"><div qa-label=\"paypal-email-value\">{{data.providerEmail}}</div></td><td ng-if=\"!showAddressForPayment()\" class=\"select-cell\"><!-- tvg bet cash accounts select --><div class=\"field select-field\" ng-if=\"data.selectedWithdrawOption.id === 'BETCASH'\"><span ng-if=\"data.availableBetCashAccounts.length > 0\"><select-container><select qa-label=\"betcash-bank-selector\" ng-model=\"data.selectedBetCashAccount\" ng-options=\"option.name for option in data.availableBetCashAccounts\" ng-init=\"events.initDropdown(data.selectedWithdrawOption.id)\" ng-change=\"events.setCurrentBetCash(data.selectedBetCashAccount)\"></select> <span ng-bind=\"data.selectedBetCashAccount.name\"></span></select-container></span><span ng-if=\"data.availableBetCashAccounts.length == 0\">No Bet Cash Accounts Available.</span></div><!-- check addresses select --><div class=\"field select-field\" ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\"><span ng-if=\"data.availableCheckOptions.length > 0\"><select-container><select qa-label=\"check-address-selector\" ng-model=\"data.selectedAddressSection\" ng-options=\"option.name for option in data.availableCheckOptions\" ng-change=\"events.toggleHomeMailMethods(data.selectedAddressSection)\" ng-init=\"events.initDropdown(data.selectedWithdrawOption.id)\"></select> <span ng-bind=\"data.selectedAddressSection.name\"></span></select-container></span><span ng-if=\"data.availableCheckOptions.length == 0\" ng-bind-html=\"'noAddressAvailableLabel' | CMSLabels: 'withdrawLabels' | trust\"></span></div><!-- tvg credit card select --><div class=\"field select-field\" ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD'\"><span ng-if=\"data.cardsOnFile.length > 0\"><select-container><select qa-label=\"betcash-bank-selector\" ng-model=\"data.selectedCardOnFile\" ng-options=\"option.name for option in data.cardsOnFile\" ng-init=\"events.initDropdown(data.selectedWithdrawOption.id)\" ng-change=\"events.setCurrentCardOnFile(data.selectedCardOnFile)\"></select> <span ng-bind=\"data.selectedCardOnFile.name\"></span></select-container></span></div></td><td class=\"amount-cell\"><div class=\"field amount-input\"><div class=\"input-container\"><input qa-label=\"withdraw-amount\" class=\"withdraw-amount-input\" name=\"newAmount\" type=\"number\" max=\"{{ getMaxWithdrawValue() }}\" min=\"{{ data.minWithdraw }}\" step=\"0.01\" num-length=\"30\" ng-model=\"withdrawDataModel.amount\" ng-model-options=\"{ debounce: 300 }\" ng-required=\"true\" pattern=\"^\\d+(?:\\.\\d{1,2})?$\" placeholder=\"$0.00\" ng-blur=\"events.changeAmount(withdrawFrm.amount.$touched, withdrawFrm.amount.$valid)\"></div></div><div class=\"btn-container\"><button qa-label=\"withdraw-button\" class=\"submit withdraw-btn\" type=\"submit\" ng-if=\"(data.selectedWithdrawOption.id !== 'BETCASH' || data.availableBetCashAccounts.length > 0)\"><strong><i class=\"tvg-icon-login\"></i> <span ng-bind-html=\"'authorizeWithdrawalBtn' | CMSLabels: 'withdrawLabels' | trust\"></span></strong></button></div></td></tr><tr ng-if=\"data.selectedWithdrawOption.id === 'CHECK'\"><td></td><td></td><td class=\"check-address\"><p qa-label=\"check-address-selected\" ng-if=\"data.selectedAddressSection\" ng-bind=\"data.selectedAddressSection.address\"></p></td><td></td></tr><tr ng-if=\"data.selectedWithdrawOption.id === 'DEBIT_CARD'\"><td></td><td></td><td></td><td><label class=\"fee\" ng-bind-html=\"'withdraw-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label><ul qa-label=\"withdraw-summary\" class=\"deposit__summary\"><li qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('withdraw-summary-amount' | CMSLabels: 'dmaDepositLabels') + ' ' +\n" +
    "                            ((withdrawDataModel.amount | currency: '$') || '$--') | trust )\"></li><li qa-label=\"deposit-summary-fee\" ng-bind-html=\"(('withdraw-summary-fee' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                            ((0 | currency: '$') || '$--') | trust ) + ('</span>')\"></li><strong qa-label=\"deposit-summary-total\" ng-bind-html=\"(('withdraw-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                            ((withdrawDataModel.amount | currency: '$') || '$--') | trust ) + ('</span>')\"></strong></ul></td></tr></tbody></table></div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-amount-input.html',
    "<div class=\"field withdraw-input-ctn withdraw-amount-input clearfix\" ng-if=\"!isDesktop\" ng-class=\"{\n" +
    "      inputIsInvalid: $root.isFdrApp && withdrawFrm.amount.$invalid && (withdrawFrm.amount.$touched || withdrawFrm.$submitted),\n" +
    "      inputIsFocused: $root.isFdrApp && inputIsFocused\n" +
    "    }\"><div class=\"label withdraw-amount-label\"><span>Withdraw amount (min. $2)</span></div><div class=\"input-container\"><span>$</span> <input qa-label=\"withdraw-amount\" class=\"withdraw-amount-input\" name=\"amount\" type=\"number\" max=\"{{getMaxWithdrawValue()}}\" min=\"{{data.minWithdraw}}\" step=\"0.01\" num-length=\"30\" ng-model=\"withdrawDataModel.amount\" ng-required=\"true\" ng-pattern=\"data.numberPattern\" placeholder=\"00.00\" money-formater restrict-chars ng-focus=\"inputIsFocused = true; events.started()\"></div><span qa-label=\"error-message\" class=\"js-error-label error-label\" ng-if=\"withdrawFrm.amount.$invalid && (withdrawFrm.amount.$touched || withdrawFrm.$submitted)\" ng-bind=\"getInvalidWithdrawalMessage(withdrawFrm.amount, data.minWithdraw)\"></span></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-betcash-selector.html',
    "<div ng-if=\"!isDesktop\"><section-title ng-if=\"!$root.isFdrApp\" title=\"BetCash Accounts\" index=\"\"></section-title><section-title ng-if=\"$root.isFdrApp\" title=\"Echeck Accounts\" index=\"\"></section-title><div qa-label=\"betcash-bank-selector\" class=\"deposit-card-options\" ng-if=\"data.availableBetCashAccounts.length > 0\"><ul><li qa-label=\"betcash-bank-option\" ng-repeat=\"card in data.availableBetCashAccounts track by card.achId\" class=\"card\"><label ng-class=\"{'active': data.selectedBetCashAccount === card}\"><strong ng-bind=\"::($root.isFdrApp ? card.bankName.toLowerCase() : card.bankName)\"></strong><div ng-bind=\"::card.name\"></div><input type=\"radio\" ng-model=\"data.selectedBetCashAccount\" ng-change=\"events.setCurrentBetCash(data.selectedBetCashAccount)\" ng-value=\"card\"></label></li></ul></div><div class=\"field\" ng-if=\"data.availableBetCashAccounts.length === 0\"><span>{{ $root.isFdrApp ? 'No Echeck Accounts Available.' : 'No Bet Cash Accounts Available.'}}</span></div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-card-selector.html',
    "<div ng-if=\"!isDesktop\"><section-title title=\"Select debit card\" index=\"\"></section-title><div qa-label=\"withdraw-card-selector\" class=\"deposit-card-options\" ng-if=\"data.cardsOnFile.length > 0\"><ul qa-label=\"cardsList\" ng-init=\"data.pageSetFromParams ? null : data.selectedCardOnFile = data.cardsOnFile[0]; events.setCurrentCardOnFile(data.selectedCardOnFile) \"><li qa-label=\"ccCardsOnFile\" ng-repeat=\"card in data.cardsOnFile track by card.id\" class=\"card\"><label qa-label=\"cardInfo\" ng-class=\"{'active': data.selectedCardOnFile === card ||\n" +
    "                                    (card.ftype === 'CC' && data.selectedCardOnFile.id === card.id) }\"><strong ng-bind=\"::card.network\"></strong><div><span ng-if=\"card.isExpired\" class=\"expired-card-label\">{{'expired-card' | CMSLabels: 'dmaDepositLabels'}} </span><span ng-bind=\"::card.cardNumberExt\"></span> (<span ng-bind=\"::card.expirationDate\"></span>)</div><input qa-label=\"cardSelection\" type=\"radio\" ng-model=\"data.selectedCardOnFile\" ng-change=\"events.setCurrentCardOnFile(card)\" ng-value=\"card\"></label></li></ul></div><dw-info-message qa-label=\"withdrawNoCardsAvailable-info\" ng-if=\"data.cardsOnFile.length === 0\" ng-attr-title=\"{{'withdrawNoCardsAvailableTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'withdrawNoCardsAvailable' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-home-mail-selector.html',
    "<section-title index=\"\" title=\"Select Address\" ng-if=\"!isDesktop\"></section-title><div ng-if=\"!isDesktop\"><dw-info-message qa-label=\"chequeRequestProcessing-info\" ng-attr-title=\"{{'chequeRequestProcessingTitle' | CMSLabels: 'withdrawLabels' | trust}}\" ng-attr-message=\"{{'chequeRequestProcessing' | CMSLabels: 'withdrawLabels' | trust}}\"></dw-info-message><div qa-label=\"check-address-selector\" class=\"deposit-card-options\" ng-if=\"data.availableCheckOptions.length > 0\"><ul><li qa-label=\"check-address-option\" ng-repeat=\"card in data.availableCheckOptions\" class=\"card\" ng-if=\"card.address && card.address.length\"><label ng-class=\"{'active': data.selectedAddressSection.id == card.id}\"><strong ng-bind=\"::card.name\"></strong><div ng-bind=\"::card.address\"></div><input type=\"radio\" ng-model=\"data.selectedAddressSection\" ng-change=\"events.toggleHomeMailMethods(card)\" ng-value=\"card\"></label></li></ul></div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-provider-email.html',
    "<div ng-if=\"(data.selectedWithdrawOption.id === 'PAY' && data.providerEmail) && !isDesktop\" class=\"paypal-account-details\"><section-title title=\"{{$root.isFdrApp ? 'Paypal Account Details' : 'Details' }}\" index=\"\"></section-title><div qa-label=\"provider-email\"><strong ng-if=\"!$root.isFdrApp\" ng-bind-html=\"'email' | CMSLabels: 'paypalLabels' | trust\"></strong> <strong ng-if=\"$root.isFdrApp\">Email address set to: </strong>{{ data.providerEmail }}</div></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-total-cost.html',
    "<div ng-if=\"!isDesktop\"><section-title title=\"{{'withdraw-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust}}\" index=\"\"></section-title><ul qa-label=\"withdraw-summary\" class=\"deposit__summary disabled_fdr_styles withdraw-left-padding\"><li qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('withdraw-summary-amount' | CMSLabels: 'dmaDepositLabels') + ' ' +\n" +
    "                          ((withdrawDataModel.amount | currency: '$') || '$--') | trust )\"></li><li qa-label=\"deposit-summary-fee\" ng-bind-html=\"(('withdraw-summary-fee' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                          ((0 | currency: '$') || '$--') | trust ) + ('</span>')\"></li><strong qa-label=\"deposit-summary-total\" class=\"bold\" ng-bind-html=\"(('withdraw-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                          ((withdrawDataModel.amount | currency: '$') || '$--') | trust ) + ('</span>')\"></strong></ul></div>"
  );


  $templateCache.put('src/templates/withdraw/fields/withdraw-type-selector.html',
    "<withdraw-options-container class=\"dma-nav dma-nav-tabs\"><withdraw-option ng-repeat=\"option in data.withdrawOptions\" qa-label=\"{{option.qalabel}}\" ng-click=\"events.toggleWithdrawOptions(option)\" ng-class=\"{selected:data.selectedWithdrawOption == option}\"><span ng-bind=\"option.name\"></span></withdraw-option></withdraw-options-container>"
  );


  $templateCache.put('src/templates/withdraw/withdraw-cancel.html',
    "<div class=\"tvg-deposit\" ng-controller=\"WithdrawCancelController\" ng-class=\"{loading: data.isLoading}\"><div class=\"before-notification\"></div><div class=\"withdraw-cancel-container\" ng-if=\"!data.isLoading\"><dw-info-dialog><p>Changed your mind?</p>Cancel pending withdrawals for immediate access to your funds.</dw-info-dialog><table class=\"table-withdrawals\" ng-if=\"data.withdrawPendingList.length\"><tr><th>DATE</th><th>TYPE</th><th>AMOUNT</th><th>ACTION</th></tr><tr ng-repeat=\"item in data.withdrawPendingList\"><td ng-bind=\"item.transactionDate | date :'MM/dd/yyyy'\"></td><td ng-bind=\"item.paymentType\"></td><td ng-bind=\"item.amount | currency\"></td><td><button class=\"red\" ng-click=\"cancelPendingWithdraw(item.withdrawalId)\">Cancel</button></td></tr></table><label class=\"no-withdrawals-message\" ng-if=\"!data.withdrawPendingList.length\">No more pending withdrawals</label></div></div>"
  );


  $templateCache.put('src/templates/withdraw/withdraw-error.html',
    "<div class=\"handler-error-container\"><span class=\"image\"></span><h1 class=\"title\">Error!</h1><div class=\"message-container\"><h2><strong>This method of withdrawal doesn't seem to be going through.</strong></h2><p class=\"customer_service\" ng-bind-html=\"('widthdrawErrorDefault'| CMSValue : null) | trust\"></p></div></div>"
  );


  $templateCache.put('src/templates/withdraw/withdraw-success.html',
    "<div class=\"handler-success-container\"><span class=\"image\"></span><h1 class=\"title\">Success!</h1><div class=\"message-container\"><h2><strong>Withdrawal Request Successful.</strong></h2><p class=\"message\">{{withdraw.description}}<!--TODO: CMS--></p></div></div>"
  );


  $templateCache.put('src/templates/withdraw/withdraw.html',
    "<withdraw-pending-requests qa-label=\"pending-withdrawals\" class=\"withdraw-pending-requests-desktop\" ng-if=\"showPendingWithdrawals &&\n" +
    "        !data.isLoading && !data.errorFetchingData\"></withdraw-pending-requests><div ng-show=\"!data.showingFallback\" class=\"tvg-deposit\" ng-class=\"{loading: data.isLoading, 'njx-deposit': njxIntegration}\"><!-- Toggles between CHECK and BetCash option --><withdraw-type-selector></withdraw-type-selector><section ng-if=\"!data.unableToFetchProfile\" ng-class=\"{'loading sightline-loading': sightlineLoading}\"><sightline-enrollment ng-if=\"displays.isSightlineApiEnrollmentVisible()\" ng-controller=\"SightlineController\" qa-label=\"sln-api-enrollment\" ng-class=\"{'loading': data.isEnrollingCard}\"></sightline-enrollment></section><form novalidate qa-label=\"withdraw-form\" name=\"withdrawFrm\" ng-submit=\"events.withdraw(withdrawFrm)\" ng-if=\"(!data.isLoading && !data.errorFetchingData &&\n" +
    "            data.selectedWithdrawOption.id !== 'SLN' ||\n" +
    "            data.hasSightlineAccount) &&\n" +
    "            !payPalTVG3() &&\n" +
    "            !payPalNJX() &&\n" +
    "            !(data.selectedWithdrawOption.id === 'BETCASH' && data.unableToFetchBankAccounts) &&\n" +
    "            !(data.selectedWithdrawOption.id === 'CHECK' && data.unableToFetchProfile)\"><!-- Dynamically render fields depending on selected withdraw option --><div ng-repeat=\"field in data.forms[data.selectedWithdrawOption.id]\"><div ng-include=\"'src/templates/withdraw/fields/' + field + '.html'\"></div></div><!-- Withdraw button --> <button qa-label=\"withdraw-button\" ng-if=\"(data.selectedWithdrawOption.id != 'BETCASH' || data.availableBetCashAccounts.length > 0) && !isDesktop\" class=\"submit withdraw-btn\" type=\"submit\"><strong><i class=\"tvg-icon-lock\"></i> Authorize Withdrawal</strong></button></form><div ng-if=\"payPalTVG3()\" class=\"disclaimer paypal-disclaimer\" ng-bind-html=\"'tvg3Message' | CMSLabels: 'paypalLabels'\"></div><div class=\"disclaimer paypal-disclaimer\" ng-if=\"payPalNJX()\">Coming Soon</div><dw-info-dialog qa-label=\"fetching-error-message\" ng-if=\"!data.isLoading && (data.errorFetchingData || (data.selectedWithdrawOption.id === 'BETCASH' && data.unableToFetchBankAccounts))\" live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'depositsBetcashUnableToFetchBankAccounts' | CMSValue : null}}</dw-info-dialog><dw-info-dialog qa-label=\"fetching-error-message\" ng-if=\"!data.isLoading && (data.errorFetchingData ||\n" +
    "        ((data.selectedWithdrawOption.id === 'CHECK' || data.selectedWithdrawOption.id === 'SLN') && data.unableToFetchProfile))\" live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'withdrawUnableToFetchProfile' | CMSValue : null}}</dw-info-dialog></div><dw-info-dialog ng-if=\"!data.loading && !$root.isFdrApp && data.showingFallback\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\">{{'withdrawalNoPaymentMethodsAvailable' | CMSValue : null}}</dw-info-dialog>"
  );

}]);

angular.module('TVG.Transfer').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('src/templates/transfer/fields/transfer-amount-input.html',
    "<div class=\"table\" ng-class=\"{ 'dma-amount-table' : $root.product == 'njx' }\" qa-label=\"dmaAmountTable\"><div class=\"row\"><span class=\"cell title\">I want to transfer $</span> <span class=\"cell\"></span> <span class=\"cell\"><div ng-if=\"transferFrm.amount.$error.min\" class=\"js-error-label error-label minimum\" ng-class=\"{invalidAmount: transferFrm.amount.$invalid && transferFrm.amount.$dirty}\">Minimum {{(transferDataModel.min) | currency}}</div><div ng-if=\"transferFrm.amount.$error.max\" class=\"js-error-label error-label maximum\" ng-class=\"{invalidAmount: transferFrm.amount.$invalid && transferFrm.amount.$dirty}\">Maximum {{(transferDataModel.max) | currency}}</div></span></div><div class=\"row\"><span class=\"cell w160\"><toggle-options><button ng-class=\"{selected: transferDataModel.amount == data.availableAmountOptions[0]}\" class=\"amount-button\" type=\"button\" ng-click=\"transferDataModel.amount=data.availableAmountOptions[0];\" ng-disable=\"data.loading\">${{data.availableAmountOptions[0]}}</button> <button ng-class=\"{selected: transferDataModel.amount == data.availableAmountOptions[1]}\" class=\"amount-button\" type=\"button\" ng-click=\"transferDataModel.amount=data.availableAmountOptions[1];\" ng-disable=\"data.loading\">${{data.availableAmountOptions[1]}}</button> <button ng-class=\"{selected: transferDataModel.amount == data.availableAmountOptions[2]}\" class=\"amount-button\" type=\"button\" ng-click=\"transferDataModel.amount=data.availableAmountOptions[2];\" ng-disable=\"data.loading\">${{data.availableAmountOptions[2]}}</button></toggle-options></span><span class=\"cell minw30\">or <span class=\"amount-dollar-label\">$</span></span> <span class=\"cell\"><input class=\"amount\" name=\"amount\" type=\"number\" placeholder=\"Other Amount\" min=\"{{transferDataModel.min}}\" max=\"{{transferDataModel.max}}\" maxlength=\"9\" step=\"0.01\" ng-model=\"transferDataModel.amount\" ng-model-options=\"{debounce: 500}\" ng-required=\"true\" ng-disable=\"data.loading\" restrict-chars qa-label=\"transferFundsExchange\"></span></div></div>"
  );


  $templateCache.put('src/templates/transfer/fields/transfer-source-destination.html',
    "<div class=\"form-fields\"><div class=\"field\"><span class=\"input-container\"><select-container class=\"others\"><select class=\"card\" name=\"slcOrigin\" ng-disable=\"data.loading\" ng-model=\"transferDataModel.source\" ng-options=\"option.label for option in data.optionsAccounts\" ng-change=\"events.selectSource()\" qa-label=\"exchangeFromSelect\"><option value=\"\" disabled=\"disabled\">{{'depositAchOnFileSelectionLabel' | CMSValue : null}}</option></select> <span qa-label=\"transferSourceLabel\">{{transferDataModel.source.label || 'From' }}</span></select-container></span></div><div class=\"field\"><select-container><select class=\"ng-pristine ng-valid ng-touched\" name=\"slcDestination\" ng-disable=\"data.loading\" ng-model=\"transferDataModel.destination\" ng-options=\"option.label for option in data.optionsAccounts\" ng-change=\"events.selectDestination()\" qa-label=\"exchangeToSelect\"><option value=\"\" disabled=\"disabled\">{{'depositAchOnFileSelectionLabel' | CMSValue : null}}</option></select> <span qa-label=\"transferDestinationLabel\">{{transferDataModel.destination.label || 'To' }}</span></select-container></div></div>"
  );


  $templateCache.put('src/templates/transfer/transfer.html',
    "<div class=\"tvg-deposit tvg-deposit-transfer\" ng-controller=\"TransferController\"><div ng-class=\"{'loading': data.loading}\"></div><dw-info-dialog ng-if=\"data.errorDepositRestrictions\" ng-bind=\"data.message\"></dw-info-dialog><form ng-if=\"!data.errorDepositRestrictions\" class=\"deposit-form\" name=\"transferFrm\" ng-submit=\"events.makeTransfer(transferFrm)\" ng-class=\"{loading: data.makingTransfer}\"><transfer-amount-input></transfer-amount-input><div class=\"disclaimer\">Although you can access both 4NJbets and the Betfair Exchange, you'll need to transfer funds between them in order to bet.</div><transfer-source-destination></transfer-source-destination><div ng-if=\"transferDataModel.isPending != true\" class=\"field\"><button class=\"submit add-funds\" ng-disabled=\"(data.makingTransfer || !transferDataModel.source || !transferDataModel.destination || !transferDataModel.amount || !transferFrm.$valid || data.loading)\" type=\"submit\"><strong>Transfer funds</strong></button><p ng-if=\"!notifyErrors\" ng-show=\"data.showInvalidFormMessage\" ng-class=\"{show: data.showInvalidFormMessage}\" class=\"js-error-label error-label fade-msg text-centered\">This form contains errors. Please fix all errors before continuing.</p></div></form></div>"
  );

}]);

angular.module('TVG.ManagePaymentMethods').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('src/templates/managePaymentMethods/fields/deposit-limits.html',
    "<div class=\"field\"><h2 class=\"dma-section-title\"><span ng-bind=\"('depositLimitsTitle' | CMSLabels: 'dmaManagementLabels' | trust)\"></span></h2><div class=\"limits\" ng-if=\"(!events.unableToFetchLimits() || !(data.selectedPayOption.ftype === 'IBC' || data.selectedPayOption.ftype === 'ACH' || data.selectedPayOption.ftype === 'CC' || data.selectedPayOption.ftype === 'APPL'))\"><div class=\"limits-table\"><div class=\"header\"><div class=\"header-row\"><div class=\"header-cell\"><span ng-if=\"data.selectedPayOption.ftype === 'APPL'\">Card Type</span> <span ng-if=\"data.selectedPayOption.ftype === 'CC'\">Card Type</span> <span ng-if=\"data.selectedPayOption.ftype === 'IBC'\">Account Type</span></div><div class=\"header-cell\"><span>Daily Limit</span></div><div class=\"header-cell\"><span>Monthly Limit</span></div></div></div><div class=\"body\"><div class=\"body-row\" ng-repeat=\"limitType in data.selectedPayOption.paymentLimits\"><div class=\"body-cell card-type-cell\" qa-label=\"cardTypeCell\"><span>{{limitType.typeName}}</span></div><div class=\"body-cell\"><div class=\"image-row\"><span class=\"image-cell\" qa-label=\"dailyLimitCell\">{{limitType.limitInterval.Daily.Effective | noFractionCurrency}}</span> <button class=\"edit\" ng-click=\"events.editLimit(true, limitType)\" qa-label=\"dailyLimitEditButton\"><strong>Edit</strong></button></div><div ng-if=\"limitType.limitInterval.Daily.ShowFuture\" class=\"image-row\"><span class=\"schedule image-cell\" qa-label=\"dailyLimitFutureCell\">Scheduled to change to {{limitType.limitInterval.Daily.Future | noFractionCurrency}} on {{limitType.limitInterval.Daily.FutureDateStr}}</span></div></div><div class=\"body-cell\"><div class=\"image-row\"><span class=\"image-cell\" qa-label=\"monthlyLimitCell\">{{limitType.limitInterval.Monthly.Effective | noFractionCurrency}}</span> <button class=\"edit\" ng-click=\"events.editLimit(false, limitType)\" qa-label=\"monthlyLimitEditButton\"><strong>Edit</strong></button></div><div ng-if=\"limitType.limitInterval.Monthly.ShowFuture\" class=\"image-row\"><span class=\"schedule image-cell\" qa-label=\"monthlyLimitFutureCell\">Scheduled to change to {{limitType.limitInterval.Monthly.Future | noFractionCurrency}} on {{limitType.limitInterval.Monthly.FutureDateStr}}</span></div></div></div></div></div><div class=\"tvg-dialog-filter\" ng-if=\"data.limitEditor\"></div><limit-editor ng-if=\"data.limitEditor\"><edit-info><span class=\"cell\"></span><div class=\"cell\"><span><strong>Edit - {{depositLimitModel.depositLimitTypeName}} Card</strong></span><div class=\"limit-notification\"><span class=\"icon-input-error\" ng-if=\"data.limitError\"></span> <span ng-if=\"data.limitError\">{{data.limitErrorMessage}}</span></div></div></edit-info><edit-input><span class=\"cell\"><strong>$</strong></span><div class=\"cell\"><div class=\"align-left\"><input class=\"limit-amount\" name=\"limit-value\" ng-min=\"{{depositLimitModel.min||0}}\" ng-model=\"depositLimitModel.amount\" ng-required=\"true\" ng-change=\"events.validateLimitAmount()\" ng-enter=\"events.saveLimit()\" qa-label=\"depositLimitModelInput\"></div><div class=\"align-right\"><button class=\"cancel\" ng-click=\"events.cancelLimitEdition()\" qa-label=\"depositLimitModelCancelButton\"><strong>Cancel</strong></button> <button class=\"save\" ng-disabled=\"data.limitError\" ng-click=\"events.saveLimit()\" qa-label=\"depositLimitModelSaveButton\"><strong>Save</strong></button></div></div></edit-input></limit-editor></div><div ng-if=\"events.unableToFetchLimits() && (data.selectedPayOption.ftype === 'IBC' || data.selectedPayOption.ftype === 'ACH' || data.selectedPayOption.ftype === 'CC' || data.selectedPayOption.ftype === 'APPL')\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'ManagementBetcashUnableToFetchLimits' | CMSValue : null}}</dw-info-dialog></div></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/new-payment-method.html',
    "<div class=\"table\"><div class=\"row\"><new-method-add class=\"cell\"><button name=\"add-card\" ng-click=\"data.newCardForm = true\"><span class=\"add\"></span> <span>Add a new credit or debit card</span></button></new-method-add><new-method-option class=\"cell\"><span>We accept</span><div class=\"row\"><span class=\"visa-icon\"></span> <span class=\"mastercard-icon\"></span></div></new-method-option></div></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-method-card.html',
    "<div class=\"payment-management-option-main payment-management-block-grid\"><div class=\"payment-management-icon\"><div class=\"credit-card__placeholder\"></div></div><div class=\"payment-management-info\"><ul><li><strong ng-if=\"$ctrl.card.ftype === 'CC'\" ng-bind=\"$ctrl.card.typeName + ' Card'\"></strong> <strong ng-if=\"$ctrl.card.ftype === 'ACH'\" ng-bind=\"::$ctrl.card.bankName\"></strong></li><li ng-if=\"$ctrl.card.ftype === 'CC'\">{{\"xxxx-xxxx-xxxx-\" + $ctrl.card.cardNumber}}</li><li ng-if=\"$ctrl.card.ftype === 'ACH'\">*****{{$ctrl.sliceCard({number: $ctrl.card.bankAccNumber})}}</li><li ng-if=\"$ctrl.card.ftype === 'CC'\">Expires {{$ctrl.card.expirationDate}}</li></ul></div><a ng-if=\"$ctrl.card.ftype === 'CC'\" class=\"payment-management-close\" href ng-click=\"$ctrl.removeCard({card: card})\"><i class=\"tvg-icon-close\"></i></a></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-method-on-file-list.html',
    "<div class=\"field\"><payment-method-on-file-option ng-attr-card=\"card\" ng-attr-on-edit-card-action=\"events.showEditCardConfirmModal(card)\" ng-attr-on-go-to-deposit=\"events.goToDeposit(card, $index)\" ng-attr-on-remove-card-action=\"events.showRemoveCardConfirmModal(card)\" ng-attr-index=\"$index\" ng-repeat=\"card in data.selectedPayOption.onFile track by $index\"></payment-method-on-file-option><div ng-if=\"data.selectedPayOption.onFile.length === 0\"><p class=\"text-center\" ng-if=\"data.selectedPayOption.ftype === 'IBC'\" ng-bind=\"('noAccountsFound' | CMSLabels: 'dmaManagementLabels')\"></p><p class=\"text-center\" ng-if=\"data.selectedPayOption.ftype === 'CC'\" ng-bind=\"('no-cards-found' | CMSLabels: 'dmaDepositLabels')\"></p></div></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-method-on-file-option.html',
    "<div class=\"payment-management-option\" ng-class=\"{'payment-management-option--expired': card.isExpired}\" ng-controller=\"ManagePaymentMethodsController\" qa-label=\"paymentManagementOption\"><span ng-if=\"card.isExpired\" class=\"expired-card-label\">{{'expired-card' | CMSLabels: 'dmaDepositLabels'}} </span><span ng-if=\"card.IsPending\" class=\"expired-card-label\">{{'pendingAccount' | CMSLabels: 'dmaManagementLabels'}}</span><payment-method-card card=\"card\" remove-card=\"onRemoveCardAction(card)\" slice-card=\"events.slicedCard(number)\"></payment-method-card><ul class=\"payment-management-action-list\"><li><a href class=\"payment-management-action payment-management-action--primary\" ng-click=\"onGoToDeposit({index: index, card: card})\" qa-label=\"paymentManagementActionDepositButton\">Deposit</a></li><li ng-if=\"card.ftype === 'CC'\"><a href class=\"payment-management-action payment-management-action--secondary\" ng-click=\"onEditCardAction({card: card})\" qa-label=\"paymentManagementActionEditDetailsButton\">Edit Details</a></li></ul></div>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/payment-methods-type-selector.html',
    "<payment-methods-options-container><payment-methods-option ng-repeat=\"option in data.paymentMethodsOptions\" ng-click=\"data.selectedPayOption = option; events.resetDataModel()\" ng-class=\"{selected:data.selectedPayOption.name == option.name}\">{{option.name}}</payment-methods-option></payment-methods-options-container>"
  );


  $templateCache.put('src/templates/managePaymentMethods/fields/titles.html',
    "<h2 class=\"dma-section-title\" ng-if=\"$ctrl.type === 'CC'\"><span ng-bind=\"('creditCardTitle' | CMSLabels: 'dmaManagementLabels')\"></span> <a class=\"dma-section-link\" href ng-click=\"$ctrl.redirectAdd({type: $ctrl.type})\" ng-bind=\"('addNewCardLink' | CMSLabels: 'dmaManagementLabels')\" qa-label=\"addNewCCardLink\"></a></h2><h2 class=\"dma-section-title\" ng-if=\"$ctrl.type === 'IBC'\"><span ng-bind=\"('betCashTitle' | CMSLabels: 'dmaManagementLabels')\"></span><div class=\"dma-section-link\"><a href ng-click=\"events.redirectToAddNewCard($ctrl.type)\" ng-bind=\"('addNewAccountLink' | CMSLabels: 'dmaManagementLabels')\" qa-label=\"addNewAccountLink\"></a> <span ng-if=\"!njxIntegration\" ng-bind=\"('submit' | CMSLabels: 'dmaManagementLabels')\"></span> <a ng-if=\"!njxIntegration\" target=\"_blank\" ng-href=\"{{('linkBetcash' | CMSLabels: 'dmaManagementLabels')}}\" ng-bind=\"('BetcashAgreement' | CMSLabels: 'dmaManagementLabels')\" qa-label=\"BetcashAgreementLink\"></a><div></div></div></h2><p ng-if=\"$ctrl.type === 'IBC' && $ctrl.length > 0\" class=\"disclaimer\" ng-bind-html=\"('callSupport' | CMSLabels: 'dmaManagementLabels')\"></p>"
  );


  $templateCache.put('src/templates/managePaymentMethods/manage-payment-methods.html',
    "<div class=\"tvg-deposit\" name=\"managePaymentMethodsDiv\" ng-controller=\"ManagePaymentMethodsController\" ng-class=\"{loading: data.loading}\"><deposit-options-container class=\"dma-nav dma-nav-tabs\"><deposit-option ng-repeat=\"option in data.paymentMethodsOptions track by $index\" ng-click=\"events.selectOption(option)\" ng-class=\"{selected:data.selectedPayOption.ftype === option.ftype}\"><span qa-label=\"{{::option.ftype}}\">{{::option.name}}</span></deposit-option></deposit-options-container><div class=\"before-notification\"></div><dw-info-dialog ng-if=\"data.errorPaymentRestrictions && !data.loading\" live-person=\"{{'depositInitialDataErrorActionText'| CMSValue : null}}\">{{'depositInitialDataErrorMessage' | CMSValue : null}}</dw-info-dialog><form class=\"deposit-form\" name=\"depositFrm\" ng-if=\"!data.errorPaymentRestrictions && !data.loading\" ng-submit=\"data.newCardForm ? events.addNewCard(depositFrm): data.editCardForm ? events.editCard(depositFrm) : null\" novalidate><payment-titles type=\"data.selectedPayOption.ftype\" length=\"data.selectedPayOption.onFile.length\" redirect-add=\"events.redirectToAddNewCard(type)\"></payment-titles><div class=\"payment-method-container\"><payment-method-on-file-list ng-if=\"(data.selectedPayOption.ftype !== 'IBC' || !data.unableToFetchBankAccounts)\n" +
    "     && (data.selectedPayOption.ftype !== 'CC' || !data.unableToFetchCardsOnFile)\"></payment-method-on-file-list><div ng-if=\"data.selectedPayOption.ftype === 'IBC' && data.unableToFetchBankAccounts\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'ManagementBetcashUnableToFetchBankAccounts' | CMSValue : null}}</dw-info-dialog></div><div ng-if=\"data.selectedPayOption.ftype === 'CC' && data.unableToFetchCardsOnFile\"><dw-info-dialog live-person=\"{{'depositBetCashAvailabilityActionText'| CMSValue : null}}\">{{'ManagementBetcashUnableToFetchCardsOnFile' | CMSValue : null}}</dw-info-dialog></div><deposit-limits ng-if=\"data.showLimits\"></deposit-limits></div><div ng-if=\"data.editCardForm\" class=\"payment-method-container\"><div class=\"form-fields\" ng-repeat=\"field in data.forms['NEW']['CC']\"><div ng-include=\"'src/templates/deposit/fields/'+field+'.html'\"></div></div><div class=\"field\"><button class=\"submit add-payment\" ng-disabled=\"data.savingCard\" type=\"submit\"><strong>Edit credit card details</strong></button><p ng-if=\"!notifyErrors\" ng-show=\"data.showInvalidFormMessage\" ng-class=\"{show: data.showInvalidFormMessage}\" class=\"js-error-label error-label fade-msg text-centered\">This form contains errors. Please fix all errors before continuing.</p></div></div></form></div>"
  );

}]);

angular.module('TVG.Paypal').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('src/paypal/deposits/deposit-button/deposit-button.template.html',
    "<div class=\"field\"><div ng-if=\"!$root.isFdrApp\" class=\"paypal-deposit__message disclaimer pv_10\" qa-label=\"payPalDepositMessageDisclaimerPv_10\"><p class=\"pb_5\" ng-bind-html=\"::('clickMessage' | CMSLabels: 'paypalLabels')\"></p><p class=\"pb_5\" ng-bind-html=\"::('accountMessage' | CMSLabels: 'paypalLabels')\"></p><p ng-bind-html=\"::('connectedAcount' | CMSLabels: 'paypalLabels')\"></p></div><div ng-if=\"$root.isFdrApp\" class=\"paypal-deposit__message disclaimer pv_10\" qa-label=\"payPalDepositMessageDisclaimerPv_10\">{{'clickMessage' | CMSLabels: 'paypalLabels'}} {{'accountMessage' | CMSLabels: 'paypalLabels'}} {{'connectedAcount' | CMSLabels: 'paypalLabels'}}</div><button qa-label=\"payPalButton\" class=\"paypal-deposit__button pa_0\" ng-click=\"$ctrl.onDeposit($event)\" ng-disabled=\"$ctrl.isDisabled\"><img src=\"https://www.paypalobjects.com/webstatic/en_US/i/btn/png/blue-rect-paypal-44px.png\" alt=\"PayPal Checkout\"></button></div>"
  );


  $templateCache.put('src/paypal/deposits/deposit.template.html',
    "<div ng-class=\"{loading: $ctrl.loading}\" class=\"paypal paypal-deposit\"><ng-form name=\"$ctrl.paypalDeposits\" ng-show=\"!$ctrl.loading\"><div class=\"disclaimer\" qa-label=\"payPalDisclaimer\" ng-bind-html=\"::('tutorial' | CMSLabels: 'paypalLabels')\"></div><section-title ng-if=\"$root.isFdrApp && $ctrl.email\" title=\"PayPal Account Details\" qalabel=\"paypal-accountDetails\" index=\"0\"></section-title><div ng-if=\"$root.isFdrApp && $ctrl.email\" qa-label=\"paypal-accountDetails-email\" email=\"$ctrl.email\" class=\"paypal-account-details\">Email address set to: <strong class=\"paypal-user-email\">{{ $ctrl.email }}</strong></div><section-title class=\"first-title\" qalabel=\"paypal-depositAmountTitle\" title=\"{{::'deposit-amount-title' | CMSLabels: 'dmaDepositLabels'}}\" index=\"1\"></section-title><select-amount form=\"::$ctrl.paypalDeposits\" amount=\"$ctrl.depositAmount\" min-amount=\"::$ctrl.minAmount\" max-amount=\"::$ctrl.maxAmount\" amounts=\"::$ctrl.amountOptions\" on-amount-change=\"::$ctrl.handleOnAmountChange($event)\"></select-amount><section-title title=\"Review and Authorize\" qalabel=\"paypal-reviewTitle\" index=\"2\"></section-title><total-cost data=\"$ctrl.fees\" email=\"$ctrl.email\"></total-cost><deposit-button is-disabled=\"$ctrl.shouldDisablePaypalButton()\" on-paypal-deposit=\"$ctrl.makePaypalDeposit($event)\"></deposit-button></ng-form></div>"
  );


  $templateCache.put('src/paypal/deposits/select-amount/select-amount.template.html',
    "<div class=\"dma-amount-ctn\" qa-label=\"deposit-amount\"><div class=\"dma-amount-table\"><div class=\"row\"><div class=\"cell w155\"><toggle-options><button qa-label=\"amount-button-{{amountOption}}\" ng-repeat=\"amountOption in $ctrl.amounts track by $index\" ng-class=\"{selected: $ctrl.amount == amountOption}\" class=\"amount-button\" type=\"button\" qa-label=\"amount-button-{{amountOption}}\" ng-click=\"$ctrl.change(amountOption)\">${{amountOption}}</button></toggle-options></div><span class=\"cell minw30 amount-divider\">or <span class=\"amount-dollar-label\">$</span></span><div class=\"cell align-right amount-input-ctn\"><input qa-label=\"amount-input\" money-formater class=\"amount\" name=\"amount\" type=\"number\" placeholder=\"Other amount\" ng-min=\"{{$ctrl.minAmount||0}}\" ng-max=\"{{$ctrl.maxAmount||100000}}\" ng-model-options=\"{ allowInvalid: true, updateOn: 'default blur', debounce: { default: 1000, blur: 0 } }\" num-length=\"5\" step=\"any\" ng-model=\"$ctrl.amount\" ng-required=\"true\" ng-change=\"$ctrl.change($ctrl.amount)\" restrict-chars ng-blur=\"inputIsNowFocused = false\" ng-focus=\"inputIsNowFocused = true\" ng-class=\"{\n" +
    "                        inputIsInvalid: $root.isFdrApp && $ctrl.form.amount.$invalid && $ctrl.form.$submitted,\n" +
    "                        inputIsFocused: ($root.isFdrApp && !$ctrl.form.amount.$invalid && !!inputIsNowFocused)\n" +
    "                            || ($root.isFdrApp && !$ctrl.form.amount.$dirty && !!inputIsNowFocused)\n" +
    "                    }\"></div></div></div><div class=\"row non-table amount-errors-ctn\" ng-if=\"$ctrl.form.amount.$touched || $ctrl.form.$submitted || $ctrl.form.amount.$dirty\"><div ng-messages=\"$ctrl.form.amount.$error\"><div class=\"js-error-label error-label\" ng-message=\"min\" ng-bind-html=\"(('minimum' | CMSLabels: 'paypalLabels') + ' ' + ($ctrl.minAmount | currency) | trust )\"></div><div qa-label=\"error-required\" class=\"js-error-label error-label\" ng-message=\"required\" ng-bind-html=\"('required' | CMSLabels: 'paypalLabels' | trust )\"></div><div class=\"js-error-label error-label\" ng-message=\"max\" ng-bind-html=\"(('maximum' | CMSLabels: 'paypalLabels') + ' ' + ($ctrl.maxAmount | currency) | trust )\"></div></div></div></div>"
  );


  $templateCache.put('src/paypal/deposits/total-cost/total-cost.template.html',
    "<label ng-if=\"$ctrl.data.loading && !$root.isFdrApp\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label><ul qa-label=\"deposit-summary\" class=\"deposit__summary\"><li ng-if=\"!$root.isFdrApp\" qa-label=\"paypal-email\" ng-if=\"$ctrl.email && !$root.isFdrApp\" ng-bind-html=\"(('email' | CMSLabels: 'paypalLabels') + ' ' + ($ctrl.email  | trust ))\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-amount\" ng-bind-html=\"(('deposit-summary-amount' | CMSLabels: 'dmaDepositLabels') + ' ' +\n" +
    "                      (($ctrl.data.netAmount | currency: '$') || '$--') | trust )\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-fee-amount\" ng-bind-html=\"(('deposit-summary-fee-amount' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                      (($ctrl.data.feeAmount | currency: '$') || '$--') | trust ) + ('</span>')\"></li><li ng-if=\"!$root.isFdrApp\" qa-label=\"deposit-summary-fee-refund\" ng-bind-html=\"(('deposit-summary-fee-refund' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') +\n" +
    "                    (($ctrl.data.feeRefundAmount | currency: '$') || '$--') | trust ) + ('</span>')\"></li><li><strong qa-label=\"deposit-summary-total\" ng-bind-html=\"(('deposit-summary-total' | CMSLabels: 'dmaDepositLabels' | trust) + (' <span>') + (($ctrl.data.transactionTotal | currency: '$') || '$--') | trust ) + ('</span>')\"></strong></li></ul><label ng-if=\"$ctrl.data.loading && $root.isFdrApp\" class=\"activity-info fee\" ng-bind-html=\"'deposit-summary-calculation-fees' | CMSLabels: 'dmaDepositLabels' | trust\"></label>"
  );

}]);

angular.module('TVG.MoneyPak').run(['$templateCache', function($templateCache) {
  'use strict';

  $templateCache.put('src/moneypak/moneypak.template.html',
    "<div ng-class=\"{loading: $ctrl.loading || $ctrl.activePoller}\" class=\"moneypak\"><form name=\"$ctrl.moneyPakDepositForm\" ng-submit=\"$ctrl.handleFormSubmit($event)\" novalidate><div class=\"disclaimer\" qa-label=\"moneyPakDisclaimer\" ng-bind-html=\"::('tutorial' | CMSLabels: 'moneyPakLabels')\"></div><section-title qalabel=\"mpak-depositLimitsTitle\" class=\"first-title\" title=\"{{::'depositLimitsTitle' | CMSLabels: 'moneyPakLabels'}}\"></section-title><div class=\"disclaimer\" qa-label=\"mPtableLimitsDisclaimer\" ng-bind-html=\"::('depositLimitsText' | CMSLabels: 'moneyPakLabels')\"></div><limits-table content-obj=\"::('depositLimitsTable' | CMSLabels: 'moneyPakLabels')\"></limits-table><section-title qalabel=\"mpak-authorizeTitle\" title=\"{{::'redeemAndAuthorizeTitle' | CMSLabels: 'moneyPakLabels'}}\"></section-title><div class=\"disclaimer\" qa-label=\"mpRedeemAuthorizeDisclaimer\" ng-bind-html=\"::('redeemAndAuthorizeText' | CMSLabels: 'moneyPakLabels')\"></div><moneypak-activation-number-input ng-if=\"isRGAvailable && !rgLimitReached || !isRGAvailable\" class=\"mb_20\" data-mpak-number=\"$ctrl.mpakNumber\" form=\"$ctrl.moneyPakDepositForm\" on-update=\"$ctrl.update(value)\"></moneypak-activation-number-input><div ng-if=\"isRGAvailable && !rgLimitReached && rgMoneypakAvailableDepositAmount\" class=\"warningMessage\"><div></div><span>{{messageWithRemainingAmount}}</span></div><button ng-if=\"isRGAvailable && !rgLimitReached || !isRGAvailable\" qa-label=\"submitDeposit\" class=\"submit authorize-deposit mb_20\" ng-disabled=\"$ctrl.loading || $ctrl.moneyPakDepositForm.$invalid || $ctrl.activePoller || $ctrl.responsibleGamingDelay\" type=\"submit\"><i class=\"tvg-icon tvg-icon-lock\"></i> <strong ng-bind=\"::'depositExecuteButton' | CMSValue\"></strong></button><div ng-if=\"isRGAvailable && rgLimitReached\" class=\"warningMessage\"><div></div><span>{{::'DMARGLimitReached' | CMSLabels: 'moneyPakLabels'}}</span></div><div class=\"disclaimer\" qa-label=\"mpFaqDisclaimer\" data-add-click-listener-to=\"::('faqText' | CMSLabels: 'moneyPakLabels')\" data-click-listener=\"$ctrl.openModal(event)\"></div></form></div>"
  );


  $templateCache.put('src/moneypak/limits-table/limits-table.template.html',
    "<div class=\"limits-table-container\"><table><thead><tr><th ng-repeat=\"header in vm.content.headers track by $index\" ng-bind=\"header\"></th></tr></thead><tbody><tr ng-repeat=\"row in vm.content.rows track by $index\"><td ng-repeat=\"data in row track by $index\" ng-bind=\"data\"></td></tr></tbody></table></div>"
  );


  $templateCache.put('src/moneypak/moneypak-activation-number-input/moneypak-activation-number-input.template.html',
    "<div class=\"mpak-number-container field\" ng-class=\"{fieldInvalid: $ctrl.form.mpakNumber.$touched && $ctrl.form.mpakNumber.$invalid, inputFocused: inputNumberFocused}\"><div class=\"field-label\"><label for=\"mpak-number\" qa-label=\"mpInputLabel\" ng-bind-html=\"::('moneypakNumberLabel' | CMSLabels: 'moneyPakLabels')\"></label></div><div class=\"field-input mpak-number\"><span class=\"input-container\"><input type=\"text\" qa-label=\"mpInput\" class=\"form-control mpak-number\" id=\"mpak-number\" placeholder=\"{{::('moneypakNumberPlaceholder' | CMSLabels: 'moneyPakLabels')}}\" autocomplete=\"off\" name=\"mpakNumber\" ng-model=\"$ctrl.mpakNumber\" ui-mask=\"999 999 9999 9?9?9?9\" ng-focus=\"$ctrl.startDeposit(); inputNumberFocused= true;\" ui-mask-placeholder ui-mask-placeholder-char=\" \" ng-blur=\"inputNumberFocused = false\" ui-options=\"{ clearOnBlur: false, allowInvalidValue: true }\" ng-change=\"$ctrl.update()\" ng-model-options=\"{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }\" required></span></div><additional-info ng-click=\"$ctrl.openTooltip()\"><span class=\"card-imgs mpak\" qa-label=\"mpHelperImage\"></span></additional-info><div class=\"row non-table amount-errors-ctn clearfix\" ng-if=\"$ctrl.form.mpakNumber.$touched || $ctrl.form.$submitted\"><div ng-messages=\"$ctrl.form.mpakNumber.$error\"><div qa-label=\"error-required\" class=\"js-error-label error-label\" ng-message=\"required\" ng-bind-html=\"::('required' | CMSLabels: 'moneyPakLabels' | trust )\"></div><div qa-label=\"error-invalid\" class=\"js-error-label error-label\" ng-message=\"mask\" ng-bind-html=\"::('invalidCard' | CMSLabels: 'moneyPakLabels')\"></div></div></div></div>"
  );

}]);

angular.module('TVG.ApplePay.Common', ['ngMessages', 'TVG.DMA.Common', 'TVG.Configuration']);

angular.module('TVG.ApplePay.Deposits', [
  'TVG.ApplePay.Common',
  'UserActionEvents'
]);



angular.module('TVG.ApplePay', [
  'TVG.Paypal.Common',
  'TVG.ApplePay.Deposits'
]);

angular.module('TVG.DMA.AddClickListener', []);

angular.module('TVG.DMA.Common', [
  'TVG.DMA.ModalDialog',
  'TVG.DMA.AddClickListener'
]);

angular.module('TVG.DMA.ModalDialog', [
  'ui.bootstrap',
  'TVG.DMA.AddClickListener'
]);

/* eslint angular/no-service-method: 0 */
(function () {
  'use strict';
  ApplePayService.$inject = ['ConfigurationFac', 'Utilities', '$q', '$http', '$filter'];
  function ApplePayService(
    ConfigurationFac,
    Utilities,
    $q,
    $http,
    $filter
  ) {
    var self = this;

    /* endpoint
     * Give the endpoint resources, build the final URI.
     * @param {string} ...resources One or more resources
     * @return {string} URI
     */
    var endpoint = function (base, service, version) {
      version = version || 'v1';
      return function (/* resources */) {
        var separator = '/';
        var resources = [].slice.call(arguments, 0);
        return [base, service, version].concat(resources).join(separator);
      };
    };

    var brainTreeEndpoint = endpoint(ConfigurationFac.getBaseServiceUrl(), 'brt');

    var checkError = function (response) {
      return $q(function (resolve, reject) {
        return reject(self.createApiError([{
          message: _.get(response, 'data.message'),
          code: response.status,
          data: response.data
        }]));
      });
    };

    /**
     * Create an API error instance
     * Try to fetch an error message from the CMS (using the error code)
     * If none is found, use the error.message as a fallback
     *
     * @param  {Array} errors [description]
     * @return {Error}     [description]
     */
    self.createApiError = function (data) {
      var apiError = new Error();
      var error = data[0] || {};
      var applePayError = self.getFromCMS(error.code);

      apiError.message = applePayError || error.message;
      apiError.code = error.code;
      apiError.data = error.data || {};
      return apiError;
    };

    /**
     * request
     * @param  {Object} data
     * @param  {string} data.url
     * @param  {string} data.method
     * @param  {Object} data.data
     *
     * @return {Promise}
     */
    self.request = function (params) {
      var defaults = {
        headers: self.addHeaders(),
        method: 'POST'
      };

      return $http(_.extend({}, defaults, params))
        .catch(function (err) {
          return checkError(err);
        })
        .then(function (response) {
          response.data = _.assign({}, response.data, { statusCode: response.status });
          return response;
        })
        .then(Utilities.prop('data'));
    };

    /**
     * Add the headers needed to perform API calls
     *
     * @return {object}: Header Object
     */
    self.addHeaders = function (options) {
      var headers = {
        'x-tvgcontext': angular.toJson(ConfigurationFac.getApplicationContext())
      };

      if (Utilities.prop('cache', options)) {
        headers = _.extend({}, {
          'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
          'Cache-Control': 'no-cache',
          Pragma: 'no-cache'
        }, headers);
      }
      return headers;
    };

    /**
     * Get labels from CMS
     * @param  {[string]} name [label Name]
     * @return {[string]}      [label]
     */
    self.getFromCMS = function (name) {
      return $filter('CMSLabels')(name, 'applepayLabels');
    };

    self.getDepositFee = function (amount, accountNumber) {
      var path = 'users/' + accountNumber + '/deposits/fees?amount=' + amount + '&paymentType=APPL';

      var requestOptions = {
        url: brainTreeEndpoint(path),
        method: 'GET'
      };

      return self.request(requestOptions);
    };
  }

  angular
    .module('TVG.ApplePay.Common')
    .service('applepayService', ApplePayService);
}());

angular
  .module('TVG.ApplePay.Deposits')
  .component('applepayDepositButton', {
    controller: 'applepaydepositButtonController',
    bindings: {
      onApplePayDeposit: '&',
      isDisabled: '<'
    },
    templateUrl: 'src/applepay/deposits/deposit-button/deposit-button.template.html'
  });

/* eslint angular/controller-as-vm: 0 */
(function () {
  'use strict';

  function DepositButtonController() {
    var self = this;

    self.onDeposit = function ($event) {
      self.onApplePayDeposit({ $event: $event });
    };
  }

  angular
    .module('TVG.ApplePay.Deposits')
    .controller('applepaydepositButtonController', DepositButtonController);
}());

angular
  .module('TVG.ApplePay.Deposits')
  .component('applepayDeposit', {
    templateUrl: 'src/applepay/deposits/deposit.template.html',
    controller: 'applepayDepositController',
    bindings: {
      minAmount: '<',
      maxAmount: '<',
      amountOptions: '<',
      depositAmount: '<',
      onAmountChange: '&',
      onPaymentComplete: '&'
    }
  });

/* eslint angular/controller-as-vm: "off" */

/**
 * This controllers' use case is mostly to know when to load
 * each screen and which properties it should pass to each component
 */
function ApplePayDepositController(
  $routeParams,
  $document,
  $window,
  $q,
  $timeout,
  NotificationService,
  applepayService,
  ApiDepositsGTMFac,
  ApplePayFac,
  $scope,
  $rootScope
) {
  var self = this;

  self.loading = true;
  self.applePayInstance = null;
  self.deviceData = '';
  self.depositAmount = undefined;
  self.unableToFetchBraintreeClient = false;
  self.fees = { loading: false };
  self.accountNumber = _.get($scope, '$parent.accountDetails.accountDetails.accountNumber', '') ||
    ($rootScope.user && $rootScope.user.accountNumber);
  self.feeRequestFailed = false;

  self.$onInit = function () {
    NotificationService.clearBanner();

    ApplePayFac.createClientInstance(self.accountNumber, false, self.handleBraintreeClientError)
      .then(function (response) {
        self.applePayInstance = response.applePayInstance;

        ApplePayFac.createDataCollector(response.braintreeClientInstance)
          .then(function (deviceData) {
            self.deviceData = deviceData;
            self.loading = false;
          });
      });
  };

  self.handleBraintreeClientError = function () {
    self.unableToFetchBraintreeClient = true;
  };

  /**
   * Method to handle apple pay input amount on change
   * @param {any} event
   * @return null
   */
  self.handleApplePayAmountChange = function ($event) {
    self.fees = {};
    self.depositAmount = $event.amount;
    self.fetchFees($event.amount);
  };

  /**
   * Method to tell if there is any error related with min & max values
   * @return boolean
   */
  self.isMinMaxError = function () {
    return self.minAmount > self.depositAmount || self.maxAmount < self.depositAmount;
  };

  /**
   * Method to fetch the apple pay fees
   * @param {number} amount
   * @return promise
   */
  self.fetchFees = function (amount) {
    if (self.isMinMaxError()) {
      return;
    }

    self.fees.retryFetchingFees = false;
    self.fees.loading = true;

    // stop if no amount is inserted
    // (amount is undefined if the value is not valid)
    if (!amount) {
      return $q.reject('invalid amount');
    }

    self.feeRequestFailed = false;
    NotificationService.clearBanner();

    return applepayService.getDepositFee(
      amount,
      self.accountNumber
    )
      .then(function (data) {
        var feeDiscount = data.feeRefundAmount;
        var feeAmount = parseFloat(data.feeAmount);
        var feeTotalAmount = parseFloat(data.feeTotalAmount);
        self.fees = _.assign({}, self.fees, {
          netAmount: amount,
          fee: feeAmount,
          feeDiscount: feeDiscount,
          transactionTotal: amount + feeTotalAmount
        });
        self.depositAmount = amount;
        return self.fees;
      })
      .then(function (fees) {
        ApiDepositsGTMFac.sendGTMEvent('deposit', {
          gaEventCategory: 'Deposit',
          gaEventAction: 'Deposit Start',
          gaEventLabel: undefined,
          depositType: 'Apple Pay',
          module: 'My Funds',
          depositAmount: amount + fees.fee
        });
      })
      .catch(function () {
        self.feeRequestFailed = true;
        self.fees.retryFetchingFees = true;
      })
      .finally(function () {
        self.fees.loading = false;
      });
  };

  /**
   * Should disable apple pay button
   * @return {boolean}
   */
  self.shouldDisableApplePayButton = function () {
    var amount = self.depositAmount || 0;

    return self.fees.loading ||
      self.feeRequestFailed ||
      amount === 0 ||
      !self.applePayInstance ||
      !self.deviceData ||
      self.isMinMaxError();
  };

  self.successCallbackPayment = function (data) {
    if (data) {
      $scope.$emit('onDepositEventSuccess', data);
      $rootScope.$broadcast('accountBalance_update');
      $rootScope.$emit('accountBalance_changed', data);
    }
    self.onPaymentComplete();
    self.depositAmount = undefined;

    // very ugly hack to force clear amount value
    self.applepayAmount = null;
    self.applepayDeposits.amount.$$writeModelToScope(); //eslint-disable-line
    setTimeout(function () { //eslint-disable-line
      self.applepayAmount = undefined;
      self.applepayDeposits.amount.$$writeModelToScope(); //eslint-disable-line

      $scope.$parent.events.setDepositTypeLimits('APPL');

      $timeout(function () {
        self.fees = { loading: false };
      }, 400);
    }, 0);
  };

  self.getApplePayErrorModalConfigParam = $scope.$parent.events.getApplePayErrorModalConfig;
  /**
   * Method that calls apple pay fac to handle the apple pay deposit
   * @return null
   */
  self.onApplePayDeposit = function () {
    ApplePayFac.onApplePayDeposit(
      self.applePayInstance,
      self.depositAmount,
      self.fees.fee,
      self.fees.feeDiscount,
      self.accountNumber,
      self.deviceData,
      null,
      self.successCallbackPayment,
      self.getApplePayErrorModalConfigParam()
    );
  };
}

angular
  .module('TVG.ApplePay.Deposits')
  .controller('applepayDepositController', ApplePayDepositController);

angular
  .module('TVG.ApplePay.Deposits')
  .component('applepaySelectAmount', {
    controller: 'applepaySelectAmountController',
    bindings: {
      form: '=',
      amount: '<',
      amounts: '<',
      minAmount: '<',
      maxAmount: '<',
      onAmountChange: '&'
    },
    templateUrl: 'src/applepay/deposits/select-amount/select-amount.template.html'
  });

/* eslint angular/controller-as-vm: "off" */
(function () {
  'use strict';

  SelectAmountController.$inject = ['UserActionEventsService', '$timeout'];
  function SelectAmountController(UserActionEventsService, $timeout) {
    var self = this;

    self.change = function (amount) {
      if (self.form.$error) {
        $timeout(function () {
          UserActionEventsService.emit('applePayFill', self.form.$error);
        }, 200);
      }
      self.amount = amount;
      if (self.onAmountChange) {
        self.onAmountChange({ $event: { amount: amount } });
      }
    };
  }

  angular
    .module('TVG.ApplePay.Deposits')
    .controller('applepaySelectAmountController', SelectAmountController);
}());

angular
  .module('TVG.ApplePay.Deposits')
  .component('applepayTotalCost', {
    bindings: {
      data: '<',
      email: '<',
      handleFetchFees: '&'
    },
    templateUrl: 'src/applepay/deposits/total-cost/total-cost.template.html'
  });

(function () {
  'use strict';

  /**
   * This directive adds a "ng-click" to the first, or all, "<a>" found in the "addClickListenerTo" text.
   * This could be useful if someone wants to do something before the default action takes effect or
   * cancel the default action.
   *
   * Before the compilation is performed the text is wrapped in a "<span>" element.
   * This avoids errors when compiling the "addClickListenerTo" text if it's not an HTML element.
   */
  addClickListenerToDirective.$inject = ['$compile', 'addClickListenerToService'];
  function addClickListenerToDirective($compile, addClickListenerToService) {
    var NG_CLICK_TO_APPEND = ' ng-click="clickListener({event: $event})"';
    var SPLIT_STR = '<a';

    return {
      restrict: 'A',
      scope: {
        addClickListenerTo: '<',
        clickListener: '&',
        addToAll: '@?'
      },
      link: function (scope, element) {
        var htmlText;

        if (!scope.addClickListenerTo) {
          return;
        }

        htmlText = addClickListenerToService.appendAttributeTo(
          scope.addClickListenerTo,
          NG_CLICK_TO_APPEND,
          SPLIT_STR,
          scope.addToAll);

        htmlText = addClickListenerToService
          .wrapHtmlTextIn('span', htmlText);

        element.html(htmlText);
        $compile(element.contents())(scope);
      }
    };
  }

  angular
    .module('TVG.DMA.AddClickListener')
    .directive('addClickListenerTo', addClickListenerToDirective);
}());

(function () {
  'use strict';

  function addClickListenerToService() {
    /**
     * @param {String} text The original text.
     * @param {String} attribute The partial text to insert in the middle of the provided text.
     * @param {String} separator A character or string that's going to be used to split the original in half or more.
     * @param {boolean} appendToAll true to append attribute to all parts of the divided text. Otherwise,
     *  the attribute is inserted only in the first occurrence even if the separator is found more than once.
     * @returns {String} The original text with the provided attribute inserted in the middle if separator is found.
     *
     * @private
     */
    function _appendAttributeTo(text, attribute, separator, appendToAll) {
      var i;
      var length;
      var htmlText = text.split(separator);

      if (htmlText.length > 1) {
        length = appendToAll ? htmlText.length : 2;

        for (i = 1; i < length; i++) {
          htmlText[i] = attribute + htmlText[i];
        }
      }

      return htmlText.join(separator);
    }

    /**
     * @param {String} wrapper A HTML element's name
     * @param {String} htmlText The HTML text to wrap
     * @returns {String} The HTML text wrapped with the provided HTML element.
     * @private
     */
    function _wrapHtmlTextIn(wrapper, htmlText) {
      return '<{0}>{1}</{0}>'
        .replace(/\{0\}/gi, wrapper)
        .replace('{1}', htmlText);
    }

    return {
      appendAttributeTo: _appendAttributeTo,
      wrapHtmlTextIn: _wrapHtmlTextIn
    };
  }

  angular
    .module('TVG.DMA.AddClickListener')
    .factory('addClickListenerToService', addClickListenerToService);
}());

(function () {
  'use strict';

  var modalDialogComponent = {
    bindings: {
      body: '<',
      title: '<',
      close: '&',
      klass: '@'
    },
    controller: 'ModalDialogController',
    templateUrl: 'src/common/modal-dialog/modal-dialog.template.html'
  };

  angular
    .module('TVG.DMA.ModalDialog')
    .component('modalDialog', modalDialogComponent);
}());

(function () {
  'use strict';

  ModalDialogController.$inject = ['$document', '$window'];
  function ModalDialogController($document, $window) {
    var vm = this;

    function _getIdOfElementToScrollTo(originalElement) {
      var path;
      var hash;

      path = originalElement && originalElement.pathname;
      hash = originalElement && originalElement.hash;

      if (path !== '/' || hash === '') {
        return null;
      }

      return hash;
    }

    vm.scrollToSection = function (event) {
      var hash;
      var element;

      if (!event || !event.target) {
        return undefined;
      }

      hash = _getIdOfElementToScrollTo(event.target);

      if (!hash) {
        return undefined;
      }

      event.preventDefault();

      // find the element with the id equal to the hash
      element = $document[0].querySelector(hash);
      if (element) {
        if ([
          'touch3',
          'ios2',
          'fdrmobile',
          'fdrios',
          'fdrandroid',
          'androidwrapper',
          'tvgandroid'
        ].indexOf($window.productContext) >= 0) {
          // prevent scroll to on ios iframe
          return true;
        }

        element.scrollIntoView();

        return true;
      }

      return false;
    };
  }

  angular
    .module('TVG.DMA.ModalDialog')
    .controller('ModalDialogController', ModalDialogController);
}());

(function () {
  'use strict';

  modalDialogService.$inject = ['$rootScope', '$uibModal'];
  function modalDialogService($rootScope, $uibModal) {
    var self = this;

    function _open(bindings, dimension, modalClass) {
      var cssClass = dimension || '';

      return $uibModal.open({
        template: '<modal-dialog data-body="modalBody" ' +
          'data-title="modalTitle" data-close="$close()" ' +
          'data-klass="' + cssClass + '"></modal-dialog>',
        scope: bindings,
        windowTemplateUrl: 'src/common/modal-dialog/modal-window.html',
        backdropClass: 'tvgmodal-backdrop',
        windowClass: 'tvgmodal-dma-redesign tvg-ui-modal-dialog ' + (modalClass || '')
      });
    }

    /**
     * Opens a medium-size modal dialog.
     *
     * @param {String} modalTitle The text that is going to appear on the header of the modal
     * @param {String} modalBody The text that is going to appear on the body of the modal. It can be a HTML text.
     * @returns {Object} a modal instance, an object with the following properties: <br>
     * * close(result) (Type: function) - Can be used to close a modal, passing a result.
     * * dismiss(reason) (Type: function) - Can be used to dismiss a modal, passing a reason.
     * * result (Type: promise) - Is resolved when a modal is closed and rejected when a modal is dismissed.
     * * opened (Type: promise) - Is resolved when a modal gets opened after downloading content's template and resolving all variables.
     * * closed (Type: promise) - Is resolved when a modal is closed and the animation completes.
     * * rendered (Type: promise) - Is resolved when a modal is rendered.
     */
    self.open = function (modalTitle, modalBody, modalClass) {
      var bindings = _.extend($rootScope.$new(), {
        modalBody: modalBody,
        modalTitle: modalTitle
      });

      return _open(bindings, '', modalClass);
    };

    /**
     * Opens a large-size modal dialog.
     *
     * @param {String} modalTitle The text that is going to appear on the header of the modal
     * @param {String} modalBody The text that is going to appear on the body of the modal. It can be a HTML text.
     * @returns {Object} a modal instance, an object with the following properties: <br>
     * * close(result) (Type: function) - Can be used to close a modal, passing a result.
     * * dismiss(reason) (Type: function) - Can be used to dismiss a modal, passing a reason.
     * * result (Type: promise) - Is resolved when a modal is closed and rejected when a modal is dismissed.
     * * opened (Type: promise) - Is resolved when a modal gets opened after downloading content's template and resolving all variables.
     * * closed (Type: promise) - Is resolved when a modal is closed and the animation completes.
     * * rendered (Type: promise) - Is resolved when a modal is rendered.
     */
    self.openLarge = function (modalTitle, modalBody, modalClass) {
      var bindings = _.extend($rootScope.$new(), {
        modalBody: modalBody,
        modalTitle: modalTitle
      });

      return _open(bindings, 'large', modalClass);
    };
  }

  angular.module('TVG.DMA.ModalDialog')
    .service('ModalDialogService', modalDialogService);
}());

(function () {
  'use strict';

  Utilities.$inject = ['$q', '$timeout', '$location', 'ConfigurationFac', '$window'];
  function Utilities($q, $timeout, $location, ConfigurationFac, $window) {
    /**
     * curry
     *
     * @param {Function} fn
     * @param {Object} ctx
     * @return {Function}
     */
    var curry = function (fn, ctx) {
      return function curriedFn() {
        var args = [].slice.call(arguments);
        return (args.length >= fn.length) ?
          fn.apply(null, args) :
          function () {
            return curriedFn.apply(ctx, args.concat([].slice.call(arguments)));
          };
      };
    };

    /**
     * attempt
     * Try to call the given function with the given arguments, if the resulting
     * call throws an error, that error is returned, otherwise returns the
     * resulting value.
     * Also, if a second function is given, it will be called if there was an
     * error, with the Error
     * as argument. The return value will then be resulting function return.
     *
     * @param  {Function} fn function to be called
     * @param  {Function} [errfn] if an Error was found, call this function with
     * the error as argument
     * @return {Error|*}
     */
    var attempt = function (fn, errfn) {
      var errorCb = errfn || id;
      var result;

      try {
        result = fn();
      } catch (e) {
        result = errorCb(e);
      }

      return result;
    };

    /**
     * Back Off algorithm with Fibonacci exponential
     * backOff :: (Function<next, stop>, Number) -> Promise<Any, Error>
     *
     * @param {Function<next, stop>} fn function to be called
     * @param {Number} timeout
     * @return {Promise<Any, Error>}
     * @example
     * ```
     *  backOff(function (next, stop) {
     *    // Let's perform this function repeatedly for 60s
     *    doSomething()
     *      .then(function (importantValue) {
     *        // importantValue is not exactly what we
     *        // need so we need to try again
     *        next();
     *
     *        // importantValue is exactly what we are expecting so
     *        // let's stop with the repetions and jump out of the cycle
     *        stop(importantValue);
     *      })
     *      .catch(function (error) {
     *        // there was an error, let's stop this with an error too
     *        stop(error);
     *      })
     *  }, 60000)
     *  .then(function (importantValue) {})
     *  .catch(function (error) {
     *    // deal with errors passed to stop()
     *  })
     * ```
     */
    var backOff = curry(function (fn, timeout) {
      var prevInterval = 0;
      var nextInterval = 1000;
      var checkTimedOut = curry(function (timeoutMax, startTime, currentTime) {
        return (currentTime - startTime > timeoutMax);
      });
      var hasTimedOut = checkTimedOut(timeout, (+new Date()));

      return $q(function (resolve, reject) {
        var stop = function (arg) {
          return (arg instanceof Error) ?
              reject(arg) :
              resolve(arg);
        };

        var next = function () {
          var tmp = nextInterval;
          if (!hasTimedOut((+new Date()))) {
            $timeout(fn.bind(null, next, stop), nextInterval);
            nextInterval = nextInterval + prevInterval;
            prevInterval = tmp;
          } else {
            reject(new Error('BACKOFF_TIMEOUT'));
          }
        };

        fn(next, stop);
      });
    });

    /**
     * compose :: (Function, Function) -> Function -> Any
     *
     * @param  {Function} f
     * @param  {Function} g
     * @return {Function}
     */
    var compose = function (f, g) {
      return function (x) {
        return f(g(x));
      };
    };


/*
@fn function that executes a request and returns the value of the break condition
@timeout expiration time for the poller (requests will be made until that time) - milliseconds
@interval time between requests - milliseconds
 */
    var depositStatusPoller = function (fn, timeout, interval) {
      var endTime = Number(new Date()) + (timeout || 300000);
      var interv = interval || 3000;

      var checkCondition = function (resolve, reject) {
        var result = fn();

        if (result.then) {
          result.then(function (res) {
            if ((res === 'FINISH_DEPOSIT_SUCCESS' || res === 'FINISH_DEPOSIT_ERROR') ||
              $window.pollerRes &&
              ($window.pollerRes === 'FINISH_DEPOSIT_SUCCESS' ||
                $window.pollerRes === 'FINISH_DEPOSIT_ERROR')) {
              resolve(res === 'FINISH_DEPOSIT_SUCCESS' ||
                $window.pollerRes === 'FINISH_DEPOSIT_SUCCESS');
            } else if (Number(new Date()) < endTime) {
              // eslint-disable-next-line
              setTimeout(checkCondition, interv, resolve, reject);
            } else {
              reject(new Error('timed out'));
            }
          });
        } else if (result) {
          resolve(result);
        } else if (Number(new Date()) < endTime) {
          // eslint-disable-next-line
          setTimeout(checkCondition, interv, resolve, reject);
        } else {
          reject(new Error('timed out'));
        }
      };
      return $q(checkCondition);
    };

    /**
     * id
     * Return the first argument given
     * @param  {*} val [description]
     * @return {*}     [description]
     */
    var id = function (val) {
      return val;
    };

    /**
     * isEmpty
     * @param  {Array|Object} list
     * @return {Boolean}
     */
    var isEmpty = function (list) {
      var keys = isObject(list) ? Object.keys(list) : list;
      return keys ? !keys.length : true;
    };

    /**
     * mapKeys
     * iterate and object and apply the given function to the keys of the object
     *
     * @param  {Function} function  A function that will receive the key and the
     * value as arguments
     * @param {object}  obj the object to be iterared
     * @return {object}   Object with new keys
     */
    var mapKeys = curry(function (mapfn, obj) {
      return Object.keys(obj).reduce(function (acc, key) {
        var result = acc;
        result[mapfn(key, obj[key])] = obj[key];
        return result;
      }, {});
    });

    /**
     * memoize
     * Cache function result for the given arguments
     * @param  {Function} func
     * @return {Function}
     * @FIXME Find something more performant than JSON.stringify/parse
     */
    var memoize = function (f) {
      var slice = [].slice;
      var cache = {};
      return function () {
        var args = angular.toJson(slice.call(arguments));
        return (args in cache) ?
          cache[args] :
          (cache[args] = f.apply(this, angular.fromJson(args)));
      };
    };

    /**
     * noop
     * Empty function. This is useful for optional callbacks
     */
    var noop = function () {};

    /**
     * pick
     * Return a new object with the given properties of the original object
     * pick :: ([String]) -> (Object) -> Object
     *
     * @param  {string[]} properties Desired properties
     * @param  {Object} obj
     * @return {Object}
     */
    var pick = curry(function (properties, obj) {
      var props = [].concat(properties);
      return props.reduce(function (acc, key) {
        var result = acc;
        if (obj.hasOwnProperty(key)) {
          result[key] = obj[key];
        }

        return result;
      }, {});
    });

    /**
     * prop
     * Return the given property from the given object
     * prop :: (String) -> (Object) -> Any
     *
     * @param  {string} property
     * @param  {Object} obj
     * @return {*}
     * @example prop('a.very.nested.property', obj);
     */
    var prop = curry(function (property, obj) {
      var path = property.split('.');
      var next = path.shift();
      var pointer = obj;

      if (!isObject(pointer)) {
        return undefined;
      }

      while (angular.isDefined(pointer) && pointer !== null && next) {
        if (pointer.hasOwnProperty(next)) {
          pointer = pointer[next];
          next = path.shift();
        } else {
          return undefined;
        }
      }

      return pointer;
    });

    /**
     * supplant
     * @see http://javascript.crockford.com/remedial.html
     * @param  {string} str
     * @param  {o} object
     * @return {string}
     */
    var supplant = curry(function (str, o) {
      return str.replace(/\{([^{}]*)\}/g, function (a, b) {
        var r = o[b];
        return angular.isString(r) || angular.isNumber(r) ? r : a;
      });
    });

    /*
     * timestamp
     * Returns a timestamp string formatted
     *
     * @return {String}
     * @example timestamp(); // '1458766136720'
     * */
    var timestamp = function () {
      return ('' + +new Date());
    };

    var toTypeString = function (val) {
      return Object.prototype.toString.call(val);
    };

    var isObject = function (val) {
      return Object(val) === val &&
        toTypeString(val) === '[object Object]' ||
        toTypeString(val) === '[object Window]';
    };

    /**
     * uuid ()
     *
     * @return {String} RFC4122 v.4
     */
    var uuid = function () {
      var template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';

      return template.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0;
        var v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      });
    };

    /**
     * Convert regular base64 strings into URL-safe base64
     *
     * @param  {string} b64 base64 string
     * @return {string}     URL-safe base64 string
     */
    var base64toBase64Url = function (b64) {
      return b64.replace(/=/g, '')
        .replace(/\+/g, '-')
        .replace(/\//g, '_');
    };

    /**
     * Convert URL-safe base64 strings into regular base64
     *
     * @param  {string} b64u URL-safe base64 string
     * @return {string}      base64 string
     */
    var base64UrlToBase64 = function (b64u) {
      var str = '' + b64u;

      if (b64u.length % 4 === 2) {
        str = b64u + '==';
      } else if (b64u.length % 4 === 3) {
        str = b64u + '=';
      }

      return str.replace(/-/g, '+').replace(/_/g, '/');
    };

    /**
     * Call fn with the given argument, and return the argument
     * This is useful to inject console.log statements into promises
     *
     * @param  {Function} fn
     * @return {Function}
     */
    var tap = curry(function (fn, val) {
      return (fn(val), val);
    });

    /**
     * toCamelCase
     * @param  {string} str String to convert
     * @return {string}
     */
    var toCamelCase = function (str) {
      var capitalized = str
        .toLowerCase()
        .split(/[^a-zA-Z0-0]/)
        .map(upperFirst)
        .join('');

      return lowerFirst(capitalized);
    };

    var toDateFormat = curry(function (format, inputDate) {
      var date = moment(inputDate);

      return date.isValid(inputDate) ?
          date.format(format) :
          '';
    });

    var lowerFirst = function (str) {
      return str.charAt(0).toLowerCase() + str.slice(1);
    };

    var upperFirst = function (str) {
      return str.charAt(0).toUpperCase() + str.slice(1);
    };

    /**
     * parseQueryString :: (String) -> Object
     * @param  {String} qs query string without the initial '?';
     * @return {Object}
     */
    var parseQueryString = function (str) {
      var qs = str;

      if (qs[0] === '?') {
        qs = str.substring(1);
      }

      return qs
        .split('&')
        .reduce(function (acc, pair) {
          var parts = pair.split('=');
          acc[parts[0]] = parts[1];
          return acc;
        }, {});
    };

    var endpoint = function (service) {
      return function (/* resources */) {
        var separator = '/';
        var resources = [].slice.call(arguments, 0);
        var baseUrl = ConfigurationFac.getServiceApiUrl(service) || '';
        var version = '/v1';

        if (service === 'slp') {
          version = '/v2';
          baseUrl = baseUrl.replace('/v1', version);
        }

        if (!baseUrl || baseUrl === 'false') {
          baseUrl = '/' + service + version;
        }

        if (baseUrl.indexOf('false') !== -1) {
          baseUrl = baseUrl.split('false')[0] + '/' + service + version;
        }

        return [baseUrl].concat(resources).join(separator);
      };
    };

    return {
      attempt: attempt,
      backOff: backOff,
      compose: compose,
      curry: curry,
      /**
       * decodeURLSafe
       * Decode URL-safe base64 strings into the original type
       *
       * @param  {string} data URL-safe base64 string
       * @return {*}
       */
      decodeURLSafe: function (data) {
        var b64 = base64UrlToBase64(data);
        var str = atob(b64);

        return attempt(function () {
          return angular.fromJson(str);
        }, function () {
          return str;
        });
      },
      /**
       * encodeURLSafe
       * Safely convert the given data into a URL-safe version of base64.
       *
       * @param  {*} data Any type as long as it's not an object with circular
       * references
       * @return {string}   URL-safe base64
       */
      encodeURLSafe: function (data) {
        var str = angular.isString(data) ? data : angular.toJson(data);
        var b64 = btoa(str);
        return base64toBase64Url(b64);
      },

      id: id,
      isEmpty: isEmpty,
      lowerFirst: lowerFirst,
      mapKeys: mapKeys,
      memoize: memoize,
      noop: noop,
      parseQueryString: parseQueryString,
      pick: pick,
      prop: prop,
      supplant: supplant,
      tap: tap,
      depositStatusPoller: depositStatusPoller,
      endpoint: endpoint,
      timestamp: timestamp,
      toCamelCase: toCamelCase,
      toDateFormat: toDateFormat,
      uuid: uuid,
      upperFirst: upperFirst,
      /**
       * urlBuilder
       * Prepends the full hostname and port to the given partial url
       *
       * @param  {string} property
       * @return {string}
       * @example urlBuilder('/partialURL');
       */
      urlBuilder: function (url) {
        /* ** Some notes: **
         *
         * - $location.host() does not return 'http'/'https'
         * - if the URL contains a querystring it must be removed, otherwise the
         * returned URL won't be valid
         * - $location.hash() doesn't return the '#', so you need to add it by
         * hand
         *
         **/
        var absUrl = $location.absUrl();
        var qsIndex = absUrl.indexOf('?');
        var hash = $location.hash() === '' ?
          $location.hash() :
        '#' + $location.hash();
        var hashIndex = absUrl.indexOf($location.hash());
        var domainNoHash = !!hash ? absUrl.substring(0, hashIndex - 1) : absUrl;
        var domainNoQs = qsIndex > 0 ?
          domainNoHash.substring(0, qsIndex) :
          domainNoHash;

        return domainNoQs.concat(url, hash);
      },

      returnToTab: function (tab, params) {
        var product = ConfigurationFac.getApplicationContextItem('product');
        var location = ConfigurationFac.getApplicationContextItem('location');
        product = (product !== '') ? '&product=' + product : '';
        location = (location !== '') ? '&location=' + location : '';

        return supplant('?activeTab={tab}{product}{location}{params}', {
          tab: tab,
          product: product,
          location: location,
          params: params || ''
        });
      }
    };
  }

  angular.module('TVG.DMA.Common').factory('Utilities', Utilities);
}());

/* global sightline */

(function () {
  'use strict';

  DepositController.$inject = ['$q', '$scope', '$log', '$rootScope', '$timeout', '$location', '$window', '$sce', '$filter', '$uibModal', 'DepositSrv', 'ConfigurationFac', 'ApiDepositsGTMFac', 'ApplePayFac', 'NotificationService', 'SightlineSrv', 'SightlineDepositConfig', 'Utilities', 'FeedbackFac', 'PaypalDepositConfig', 'ApplePayDepositConfig', 'ModalDialogService', 'UserActionEventsService', 'DEPOSIT_TYPES', 'DepositInitialDataFac', 'DMAFeatureTogglesHashContainerSvc', 'depositMinAmountOverrides'];
  function DepositController(
    $q,
    $scope,
    $log,
    $rootScope,
    $timeout,
    $location,
    $window,
    $sce,
    $filter,
    $uibModal,
    DepositSrv,
    ConfigurationFac,
    ApiDepositsGTMFac,
    ApplePayFac,
    NotificationService,
    SightlineSrv,
    SightlineDepositConfig,
    Utilities,
    FeedbackFac,
    PaypalDepositConfig,
    ApplePayDepositConfig,
    ModalDialogService,
    UserActionEventsService,
    DEPOSIT_TYPES,
    DepositInitialDataFac,
    DMAFeatureTogglesHashContainerSvc,
    depositMinAmountOverrides
  ) {
    var invalidFormLabelTimer;
    var bankNameInfoMessages = {
      DEFAULT: '',
      ERROR: 'Please fill the bank name',
      FETCHING: 'Fetching bank name'
    };
    var toggleTimestamp = null;
    var unbind = [];
    var today = new Date();

    var ERRORS = {
      NO_SIGHTLINE_ACCOUNT_FOUND: 'NO_SIGHTLINE_ACCOUNT_FOUND'
    };

    var siteVersion = ApiDepositsGTMFac.getSiteVersion(
      ConfigurationFac.getApplicationContextItem('product').toLowerCase()
    );

    var productVersion = ApiDepositsGTMFac.getProduct(
      ConfigurationFac.getApplicationContextItem('product')
    );
    var isNative = false;

    var applePayInstance = null;
    var deviceData = '';

    var FIRST_DEPOSIT_LABELS = {
      title: 'No deposit methods on File',
      text: 'Speed up your deposits, add a method now.',
      buttonText: 'Add new Deposit Options'
    };

    var SUCCESS_MODAL_LABELS = {
      title: 'Successful Deposit!',
      textTemplate: 'Your $@@@deposit_amount@@@ are now available!',
      buttonText: 'Let\'s bet!'
    };

    var firstDepositCallback = function () {
      ApiDepositsGTMFac.sendGTMEvent('navigation', {
        event: 'navigation',
        gaEventCategory: 'Navigation',
        gaEventAction: 'Navigated To',
        gaEventLabel: FIRST_DEPOSIT_LABELS.buttonText,
        module: 'quick deposit',
        sport: undefined,
        microApp: 'non-Microapp',
        tag: undefined,
        destinationUrl: 'https://www.tvg.com/more#funds'
      });
      if ($window && $window.handleNativeMessages) {
        $window.handleNativeMessages('GO_TO_DEPOSITS');
      }
    };


    var successModalOnOpenCallback = function () {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        event: 'siteClick',
        gaEventCategory: 'Site click',
        gaEventAction: 'seen',
        gaEventLabel: undefined,
        module: 'deposit success modal',
        tag: undefined,
        microApp: undefined
      });
    };

    var successModalButtonCallback = function () {
      ApiDepositsGTMFac.sendGTMEvent('navigation', {
        event: 'navigation',
        gaEventCategory: 'Navigation',
        gaEventAction: 'Navigated To',
        gaEventLabel: SUCCESS_MODAL_LABELS.buttonText,
        module: 'deposit success modal',
        tag: undefined,
        menu: undefined,
        sport: 'Horse Racing',
        destinationUrl: 'https://www.tvg.com/'
      });

      if ($window && $window.handleNativeMessages) {
        $window.handleNativeMessages('CLOSE_DMA');
      }
    };


    var successModalCloseCallback = function () {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        event: 'siteClick',
        gaEventCategory: 'Site click',
        gaEventAction: 'close',
        gaEventLabel: undefined,
        module: 'deposit success modal',
        tag: undefined,
        microApp: undefined
      });
    };

    var triggerGaPageLoadEvent = function (accountNumber, state) {
      if (siteVersion === 'ANDROIDWRAPPER') {
        siteVersion = 'android_native';
      }
      ApiDepositsGTMFac.sendGTMEvent('ga_pageload', {
        accountId: accountNumber,
        graphVersion: 'v2',
        page: $window.location.pathname,
        privateBrowser: localStorage.getItem('privateMode') === 'true' ? 'Yes' : 'No',
        productVersion: productVersion,
        residenceState: state,
        screenName: 'Deposit',
        sectionName: 'Deposit',
        siteVersion: siteVersion,
        appVersion: $rootScope.appVersion
      });
    };

        /**
     * Get labels from CMS
     * @param  {[string]} name [label Name]
     * @return {[string]}      [label]
     */
    var getFromCMS = function (name) {
      return $filter('CMSLabels')(name, 'applepayLabels');
    };

    var ApplePayErrorModalDefault = Object.freeze({
      buttonText: '',
      buttonTextSecond: '',
      buttonTextCustomerSupport: getFromCMS('applePayModalErrorButtonCustomerSupport'),
      textMain: getFromCMS('applePayModalErrorTextRedirect'),
      textCustomerSupport: getFromCMS('applePayModalErrorTextCustomerSupport'),
      buttonCallback: Utilities.noop,
      buttonCallbackSecond: Utilities.noop,
      buttonCallbackCustomerSupport: function () {
        window.location = window.location.protocol + '//' + window.location.host + '/redirectengine?type=messageus'; // eslint-disable-line
      }
    });

    $scope.currentYear = parseInt($filter('date')(today, 'yy'), 10);
    $scope.currentMonth = parseInt($filter('date')(today, 'MM'), 10);

    $scope.njxIntegration =
      ConfigurationFac.getApplicationContextItem('product') === 'njx';

    $window.isWrapped =
      ConfigurationFac.getApplicationContextItem('wrapper') === 'true';

    $scope.data = {
      currentMinValue: 0,
      currentMaxValue: 99999,
      numberPattern: /^[0-9]+$/,
      expirationDateValues: DepositSrv.getExpirationDateValues(),
      bankNameDisabled: true, // Disables bank name input by default
      bankNameMessage: bankNameInfoMessages.DEFAULT, // Default bank name label,
      depositSection: 'NEW',
      states: [],
      loading: true,
      makingDeposit: false,
      errorBankName: false,
      fee: {
        calculatingFees: false
      },
      showGreenDotInvalidCardNumberMessage: false,
      showIBCInvalidPinOrPasswordMessage: false,
      availableAmountOptions: [],
      showInvalidFormMessage: false,
      retryFetchingFees: false,
      showAddNewDepositOptions: false,
      defaultPaymentCard: false,
      defaultPaymentValues: [
        { name: 'Yes', value: true },
        { name: 'No', value: false }
      ],
      showAchDepositLimitExceeded: false,
      slnIframeURL: $sce.trustAsResourceUrl(
        ConfigurationFac.getSightline('iframeURL')
      ),
      selectedCard: $rootScope.selectedCard || 0,
      redirectMessage: false,
      shouldDisableApplePayButton: false
    };
    $scope.PaypalDepositConfig = PaypalDepositConfig;
    $scope.ApplePayDepositConfig = ApplePayDepositConfig;
    $scope.sightlineContext = 'deposit';
    $rootScope.sightlineLoaded = false;
    $scope.firstTimeAddFunds = false;

    // because we always get user's data on startup
    $scope.sightlineLoading = true;

    // options to be rendered in quick-deposit-default.html
    $scope.selectDefaultOptions = [
      { name: 'Yes', value: true },
      { name: 'No', value: false }
    ];

    $rootScope.selectedCard = 0;
    $scope.sightlineBalance = 0;

    $scope.events = {
      routingNumberOnChange: _routingNumberOnChange,
      updateTotalCosts: _updateTotalCosts,
      subTypeCardChanged: _subTypeCardChanged,
      selectOnFileChanged: _selectOnFileChanged,
      setDepositTypeLimits: _setDepositTypeLimits,
      toggleNewStoredMethods: _toggleNewStoredMethods,
      selectOption: _selectOption,
      makeDeposit: _makeDeposit,
      onApplePayDeposit: _onApplePayDeposit,
      shouldDisableApplePayButton: _shouldDisableApplePayButton,
      getApplePayErrorModalConfig: _getApplePayErrorModalConfig,
      clearCVN: _clearCVN,
      openTerms: _openTerms,
      goToFullDeposit: _goToFullDeposit,
      existsOnFile: _existSelectedOnFile,
      defaultPaymentChanged: _defaultPaymentChanged,
      resetAllModels: _resetAllModels,
      addQuickDepositFunds: _addQuickDepositFunds,
      addSightlineFunds: _addSightlineFunds,
      getMax: _getMax,
      isSightlinePayment: _isSightlinePayment,
      isSightlineInvalid: _isSightlineInvalid,
      showAddFundsInBetslipWarning: _showAddFundsInBetslipWarning,
      slicedCard: _slicedCard,
      selectOptionByName: _selectOptionByName,
      handleDefaultAmountButtonClick: _handleDefaultAmountButtonClick,
      handleAmountInputChange: _handleAmountInputChange,
      handleAmountInputBlur: _handleAmountInputBlur,
      anyCardsExpired: _anyCardsExpired,
      allCardsDeclined: _allCardsDeclined,
      isSLNDeclinedCard: _isSLNDeclinedCard,
      onlyNumbers: _onlyNumbers,
      FieldFilled: _FieldFilled,
      clickTooltip: _clickTooltip,
      isIos: _isIos,
      isBetslip: _isBetSlip,
      changeCard: _changeCard,
      selectAccount: _selectAccount,
      depositAttemptGtm: _depositAttemptGtm,
      handleBalanceUpdate: function () {
        $rootScope.$broadcast('accountBalance_update');
      },
      handlePaypalAmountChange: function (data) {
        $scope.depositDataModel.amount = data;
      },
      registerAccountSelectionOnGTM: _registerAccountSelectionOnGTM,
      sendOtherAmountErrorToGTM: _sendOtherAmountErrorToGTM,
      completedFieldAndBlursAway: _completedFieldAndBlursAway,
      newAccountFieldError: _newAccountFieldError,
      closeSuccessfulRegistrationModal: _closeSuccessfulRegistrationModal
    };

    $scope.depositDataModel = {
      selectedPayOption: {
        min: 0,
        max: 99999
      },
      toSaveOnFile: true,
      isDefaultPayment: false,
      responsibleGamingDelay: false
    };

    // used to calculate elements display flags in template
    $scope.displays = {
      getSLPLabel: _getSLPLabel,
      isNewOnFileVisible: _isNewOnFileVisible,
      isIBCNewOnFileVisible: _isIBCNewOnFileVisible,
      isDepositFormVisible: _isDepositFormVisible,
      isIBCInvalidVisible: _isIBCInvalidVisible,
      isNotIBCValidVisible: _isNotIBCValidVisible,
      isPendingNotCalculatingVisible: _isPendingNotCalculatingVisible,
      isIBCValidExceededVisible: _isIBCValidExceededVisible,
      isDepositLoaded: _isDepositLoaded,
      isBetcashLimitExceeded: _isBetcashLimitExceeded,
      isAddNewDepositOptionsVisible: _isAddNewDepositOptionsVisible,
      isDMAInjectNoPaymentQuickDepositEnabled: function () {
        return $rootScope.activeFeatures.isDMAInjectNoPaymentQuickDepositEnabled;
      },
      disableQuickDepositButton: _disableQuickDepositButton,
      isPaypalInQuickDepositEnabled: _isPaypalInQuickDepositEnabled,
      isApplePayInQuickDepositEnabled: _isApplePayInQuickDepositEnabled,
      sightlineBalanceExceeded: _sightlineBalanceExceeded,
      hasThreeTitles: _hasThreeTitles,
      toggleTitles: _toggleTitles,
      isIBCValidVisible: _isIBCValidVisible,
      isTVG3: _isTVG3,
      unableToFetchBankAccounts: _unableToFetchBankAccounts,
      unableToFetchCardsOnFile: _unableToFetchCardsOnFile,
      getCardImage: _getCardImage,
      getCardLabel: _getCardLabel,
      isAllRequestCardsFailed: _isAllRequestCardsFailed
    };

    $scope.defaultParams = {
      module: 'My Funds',
      accountId: DepositSrv.user.get('accountNumber'),
      customerStatus: DepositSrv.getCustomerStatus(),
      residenceState: DepositSrv.user.get('homeAddress.StateAbbr')
    };

    DepositSrv.updateCustomerStatus();

    // use "isAddingFunds" to control whether the adding funds iframe should
    // be visible (inherit the value from rootScope to opening on startup)
    $scope.isAddingFunds = false;

    $scope.quickDepositSightlineError = false;

    if ($rootScope.product) {
      isNative = $rootScope.product.indexOf('native') !== -1;
    }

    if (isNative) {
      $scope.$on('accountBalance_update', function () {
        if ($window && $window.handleNativeMessages) {
          $window.handleNativeMessages('UPDATE_BALANCE');
        }
      });
    }

    /**
     * Fills data object with:
     *  - States
     *  - New deposit options (NEW)
     *  - Deposit options on file (STORED)
     *  - Deposit forms object
     *
     * Sets default deposit option to the first in STORED option
     */
    function init() {
      var initData;

      $scope.data.showAddNewDepositOptions =
        ConfigurationFac.getApplicationContextItem('application') !== 'deposit';

      DepositSrv.getInitialData()
        .then(function (data) {
          initData = data;
          $scope.accountDetails = data;
          initData.quickDepositOptions = data.quickDepositOptions;
          initData.depositOptions = data.depositOptions;
          $scope.data.states = data.states;

          // This same GTM event is applied inside TVG4 scope in this case I want to MEP and FDR (UW-1237)
          if (!ApiDepositsGTMFac.isTVG4()) {
            triggerGaPageLoadEvent(
              data.accountDetails.accountNumber,
              data.accountDetails.accountHState
            );
          }

          return data.accountDetails.accountNumber;
        })
        .then(function (accountNumber) {
          if (_isApplePayInQuickDepositEnabled()) {
            var context = _getDepositFormFirstChildSelector(); // eslint-disable-line
            // eslint-disable-next-line
            var handleClientFailure = function () {
              NotificationService.error(
                null,
                $filter('CMSLabels')('quickDepositsBraintreeClientFailMessage', 'applepayLabels'),
                context
              );

              $scope.data.shouldDisableApplePayButton = true;
            };

            ApplePayFac.createClientInstance(accountNumber, true, handleClientFailure, context)
                .then(function (response) {
                  applePayInstance = response.applePayInstance;

                  ApplePayFac.createDataCollector(response.braintreeClientInstance)
                    .then(function (deviceDataResponse) {
                      deviceData = deviceDataResponse;
                    });
                });
          }

          return (
            _isQuickDeposit() &&
            _getUserQuickDepositBankAccounts().then(function (bankAccounts) {
              initData.quickDepositOptions.map(function (opt) {
                if (opt.ftype === 'IBC' || opt.ftype === 'ACH') {
                  opt.onFile = bankAccounts;
                }
                return opt;
              });
            })
          );
        })
        .then(function () {
          return (
            _isQuickDeposit() &&
            _getUserQuickDepositCardsOnFile().then(function (cardsOnFile) {
              initData.quickDepositOptions.map(function (opt) {
                if (opt.ftype === 'CC') {
                  opt.onFile = cardsOnFile;
                }
                return opt;
              });
            })
          );
        })
        .then(function () {
          if ($rootScope.sightlineFlowVersion === '2') {
            return _getUserQuickDepositSLNCards().then(function (cardsOnFile) {
              initData.quickDepositOptions.map(function (opt) {
                if (opt.ftype === 'SLN') {
                  opt.onFile =
                    cardsOnFile && cardsOnFile.length ? cardsOnFile : [];
                }
                return opt;
              });
            });
          }
          return initData.quickDepositOptions.map(function (opt) {
            if (opt.ftype === 'SLN') {
              opt.onFile = [];
            }
            return opt;
          });
        })
        .then(function () {
          var loadEnv =
            ($scope.fromOption && $scope.fromOption.tla) || 'deposit';
          $scope.data.loading = true;
          return DepositSrv.getDepositLandingTab(
            initData.depositOptions,
            loadEnv
          );
        })
        .then(function (params) {
          var depositLandingTab = params.depositLandingTab;
          var hasMadeInitialDeposit = params.hasMadeInitialDeposit;
          var shouldLoadSightline = false;

          $scope.sightlineFlowVersion = $rootScope.sightlineFlowVersion;
          if ($scope.fromOption) {
            shouldLoadSightline =
              $scope.fromOption.tla === 'SLN' ||
              SightlineSrv.isRedirectingToSightlineAddFunds() ||
              $scope.redirectFrom === 'SLN';
          }
          if (
            $scope.sightlineFlowVersion === '1' &&
            (depositLandingTab === 'SLN' || shouldLoadSightline)
          ) {
            // sightline old flow loaders start
            _selectOption(SightlineDepositConfig, false, true);
          }
          // sometimes sightlineLoaded is not reflected on the view...
          $timeout(function () {
            $rootScope.$apply();
          });

          // GTM purposes
          DepositSrv._setHasMadeInitialDeposit(hasMadeInitialDeposit);
          $scope.defaultParams.customerStatus = DepositSrv.getCustomerStatus();
          DepositSrv.updateCustomerStatus();

          $scope.data.loading = false;
          $timeout(function () {
            if (!$scope.activePoller && !$scope.makingDeposit && !$scope.fetchingInfo) {
              angular.element(document.querySelector('#cardsForm_id')).removeClass('loading'); // eslint-disable-line
            }
          }, 5000);
          return _isQuickDeposit()
            ? _initQuickDepositOptions(initData)
            : _initFullDepositOptions(initData, depositLandingTab);
        })
        .then(function (data) {
          $scope.$emit('onDepositLoaded', true, data);
          $scope.$emit('selectedPayOption', {
            depositType: _getCurrentDepositTypeString()
          });

          $scope.data.availableAmountOptions = DepositSrv.getAvailableAmountOptions(
            data
          );
          $scope.data.makingDeposit = false;
          $scope.data.activePoller = false;

          // this condition must match the one in quick-deposit.html
          if (
            _isQuickDeposit() &&
            !$rootScope.isFdrApp &&
            !$scope.data.depositOptions.length &&
            !_isBetSlip() &&
            !_isIos() &&
            !_isAllRequestCardsFailed() &&
            $rootScope.activeFeatures.isDMAInjectNoPaymentQuickDepositEnabled
          ) {
            if($window.ReactInjector && document.getElementById('inject-no-payment-methods')){// eslint-disable-line
              $window.ReactInjector.renderFirstDeposit(document.getElementById('inject-no-payment-methods'), // eslint-disable-line
                {
                  title: FIRST_DEPOSIT_LABELS.title,
                  buttonText: FIRST_DEPOSIT_LABELS.buttonText,
                  text: FIRST_DEPOSIT_LABELS.text,
                  callback: firstDepositCallback
                });
            }
          }

          return null;
        })
        .catch(function (error) {
          $scope.data.loading = false;
          if (error === 'depositRestrictions') {
            $scope.data.errorDepositRestrictions = true;
          } else {
            $scope.data.errorLoadingData = true;
          }

          $scope.data.loading = false;
          $rootScope.sightlineLoaded = true;
          $scope.data.makingDeposit = false;
          $scope.data.activePoller = false;
          $scope.$emit('onDepositLoaded', false);

          if (
            $rootScope.isFdrApp &&
            $rootScope.newUser &&
            $scope.data.errorLoadingData &&
            $location.search().callback
          ) {
            $window.sessionStorage.setItem('newUser', true);
            $window.location.href =
              'https://' + $location.search().callback + '#welcome';
          }
        });
    }

    $scope.$on('hasMadeInitialDeposit_update', function () {
      DepositSrv._setHasMadeInitialDeposit(true);
    });

    $scope.$on('cardType_invalid', function () {
      invalidCardModal($rootScope.activeFeatures.showCardDeclinedModal);
    });

    function _applePayDepositSuccessCallback(data) {
      _resetAllModels();
      _resetFeesInfo();
      $scope.depositDataModel.amount = null;

      if (data) {
        $scope.$emit('onDepositEventSuccess', data);
        $rootScope.$broadcast('accountBalance_update');
        $rootScope.$emit('accountBalance_changed', data);
      }
    }


    function _getPaymentMethod(type) {
      var i = 0;
      var opt = {};
      if ($scope.data.depositOptions && $scope.data.depositOptions.length > 0) {
        for (i = 0; i < $scope.data.depositOptions.length; i++) {
          opt = $scope.data.depositOptions[i];
          if (opt.ftype === type) {
            return opt;
          }
        }
      }
    }

    function _getApplePayErrorModalConfig() {
      var echeck = _getPaymentMethod('IBC');
      var creditDebit = _getPaymentMethod('CC');
      var applePayErrorModalConfig = {};
      var applePayErrorModalConfigParam;

      if (echeck) {
        applePayErrorModalConfig.buttonText = (
          getFromCMS('applePayModalErrorButton1') || echeck.name
        );
        applePayErrorModalConfig.buttonCallback = function _selectBetCash() {
          $scope.events.selectOption(echeck, true, false);
        };
      }

      if (creditDebit) {
        applePayErrorModalConfig.buttonTextSecond = (
          getFromCMS('applePayModalErrorButton2') || creditDebit.name
        );
        applePayErrorModalConfig.buttonCallbackSecond = function _selectCC() {
          $scope.events.selectOption(creditDebit, true, false);
        };
      }

      applePayErrorModalConfigParam = Object.assign(
          {},
          ApplePayErrorModalDefault,
          applePayErrorModalConfig);

      return applePayErrorModalConfigParam;
    }
    /**
     * Method that calls apple pay fac to handle the apple pay deposit
     * @return null
     */
    function _onApplePayDeposit() {
      var context = _getDepositFormFirstChildSelector();
      var accountNumber = $scope.accountDetails.accountDetails.accountNumber;

      var applePayErrorModalConfigParam = _getApplePayErrorModalConfig();
      ApplePayFac.onApplePayDeposit(
        applePayInstance,
        $scope.depositDataModel.amount,
        $scope.data.fee.fee,
        $scope.data.fee.feeDiscount,
        accountNumber,
        deviceData,
        context,
        _applePayDepositSuccessCallback,
        applePayErrorModalConfigParam,
        true
      );
    }

    /**
     * Should disable apple pay button
     * @return {boolean}
     */
    function _shouldDisableApplePayButton() {
      var iosApplePayInstanceFailure = ApplePayFac.iosApplePayInstanceFailure;
      var amount = $scope.data.fee.transactionTotal || 0;

      if ($rootScope.product === 'ios2' && _isQuickDeposit()) {
        return $scope.data.fee.calculatingFees ||
          amount === 0 ||
          iosApplePayInstanceFailure ||
          $scope.data.shouldDisableApplePayButton;
      }

      return $scope.data.fee.calculatingFees ||
          amount === 0 ||
          !applePayInstance ||
          !deviceData ||
          $scope.data.shouldDisableApplePayButton;
    }

    /**
     * Returns if a new account were created during deposit
     * @returns {Boolean}
     */
    function _isDepositWithNewAccount() {
      return !_isQuickDeposit() && $scope.data.depositSection === 'NEW';
    }

    /**
     * Whether is in quick-deposit?
     * @return {Boolean}
     */
    function _isQuickDeposit() {
      var isQuickDeposit = ($scope.data || {}).isQuickDeposit;
      $rootScope.isQuickDeposit = isQuickDeposit;
      return !!isQuickDeposit;
    }

    /**
     * Check if amount is a default value
     */
    function _isDefaultAmount() {
      var defaultAmountList = [50, 100, 300];
      return defaultAmountList.indexOf($scope.depositDataModel.amount) > -1
        ? 'Yes'
        : 'No';
    }

    /**
     * @return {string} the selector for the deposit form's first child.
     * Returns the selector either for quick deposit or normal deposit.
     */
    function _getDepositFormFirstChildSelector() {
      var selector = '';
      if (_isQuickDeposit()) {
        selector =
          'quick-deposit .tvg-deposit .deposit-form section-title.first-title';
      }

      return selector;
    }

    /**
     * Compile DEPOSIT payment options by mixing the available
     * deposit and credit types with the ones that the user owns.
     *
     * @param  {Object} data  Deposit initial data from API
     * @return {Object} data  Deposit initial data from API
     * @private
     */
    function _initQuickDepositOptions(data) {
      var depositOptions;

      $scope.data.forms = DepositSrv.getQuickDepositForms();

      // flatten payment options from different types
      depositOptions = data.quickDepositOptions.reduce(function (
        options,
        mainOption
      ) {
        options = options.concat(mainOption.onFile || []);
        return options;
      },
      []);

      if ($scope.isNewUser) {
        // filter sightline options if the user doesn't have account
        depositOptions = depositOptions.filter(function (option) {
          return option.ftype !== 'SLN';
        });
      }

      // check if any of the payment options was set as default one
      // or fallback to the first card available
      _selectInitialQuickDepositCard(depositOptions);

      return data;
    }

    /**
     * Select the initial payment card to show in quick-deposit-selector.html
     * @param {Array} depositOptions  Initial deposit options
     * @private
     */
    function _selectInitialQuickDepositCard(depositOptions) {
      var defaultPaymentCard = _getDefaultPaymentCard(depositOptions);
      if (defaultPaymentCard) {
        $scope.depositDataModel.isDefaultPayment = !!defaultPaymentCard;
        defaultPaymentCard.isDefaultPayment = true;
      } else if (!!depositOptions.length) {
        defaultPaymentCard = depositOptions.reduce(function (cardSelected, cardOnFile) {
          return !cardSelected ||
                 !_isSLNDeclinedCard(cardOnFile) &&
                 cardOnFile.lastUsedDate > cardSelected.lastUsedDate
                    ? cardOnFile
                    : cardSelected;
        });
        if (!!defaultPaymentCard) {
          defaultPaymentCard.isDefaultPayment = true;
        }
      }

      $scope.data.depositOptions = depositOptions;
      $scope.depositDataModel.selectedOnFile = defaultPaymentCard;
      $scope.data.defaultPaymentCard = defaultPaymentCard;

      if (defaultPaymentCard) {
        _updateSelectedDepositTypeInfo(defaultPaymentCard);
      } else {
        _resetDepositDataModel();
      }

      if (
        ConfigurationFac.getApplicationContextItem('wrapper') === 'true' &&
        !_.get($rootScope.activeFeatures, 'enableDepositOnSinglePage', false) &&
        !depositOptions.length
      ) {
        $scope.data.loading = true;
        $window.parent.postMessage(
          {
            type: 'quick_deposit_redirect_full_deposit'
          },
          '*'
        );
        $location.path('/deposit');
      }

      return null;
    }

    /**
     * Set the select deposit type limits calling the method specific limit endpoint
     * @param {String} depositOptions  Initial deposit options
     * @private
     */
    function _setDepositTypeLimits(depositType, methodCard) {
      var accountId = DepositSrv.user.get('accountNumber');
      var cardType = $scope.depositDataModel.selectedOnFile &&
      $scope.depositDataModel.selectedOnFile.type;
      var useUwtForPaymentOptionsOnDma = angular.isDefined(
        $rootScope.activeFeatures.useUwtForPaymentOptionsOnDma
      ) ? $rootScope.activeFeatures.useUwtForPaymentOptionsOnDma
        : false;
      if ($scope.depositDataModel.selectedOnFile &&
        $scope.depositDataModel.selectedOnFile.signed) {
        cardType += 'S';
      }

      if (methodCard) {
        cardType = methodCard;
      }

      if (depositType) {
        if (useUwtForPaymentOptionsOnDma) {
          DepositSrv.getCardPaymentOptions(accountId, depositType, cardType)
            .then(function (response) {
              var hardMinLimitDepositToggleActive = DMAFeatureTogglesHashContainerSvc
                .getBasedOnKey('dma')('hardMinLimitDepositOverride');
              var overrideMinimumForMethod = depositMinAmountOverrides.filter(function (override) {
                return override.depositType === depositType;
              });

              $scope.data.disabledCard = false;
              if (hardMinLimitDepositToggleActive && overrideMinimumForMethod.length) {
                $scope.depositDataModel.min = Math.max(
                  parseFloat(overrideMinimumForMethod[0].minLimit),
                  response.minSingleDepositLimit ?
                    parseFloat(response.minSingleDepositLimit) : $scope.depositDataModel.min);
              } else {
                $scope.depositDataModel.min = response.minSingleDepositLimit ?
                parseFloat(response.minSingleDepositLimit) : $scope.depositDataModel.min;
              }

              $scope.depositDataModel.max = (!response.remainingDepositLimit &&
                response.remainingDepositLimit !== 0) ?
                $scope.depositDataModel.max : parseFloat(response.remainingDepositLimit);

              if ($scope.depositDataModel.max === 0.00 ||
                $scope.depositDataModel.max < $scope.depositDataModel.min) {
                $scope.depositDataModel.max = 0;
                $scope.depositDataModel.maxOverflow = true;
                $scope.data.disabledCard = true;
                if (depositType === 'APPL') {
                  $scope.data.shouldDisableApplePayButton = true;
                  NotificationService.warning('Disabled Card',
                    getFromCMS('applePayDepositLimitExceeded'),
                    _getDepositFormFirstChildSelector(),
                    null,
                    true
                  );
                } else {
                  NotificationService.warning('Disabled Card',
                    $filter('CMSValue')('creditCardDepositLimitExceeded'),
                    _getDepositFormFirstChildSelector(),
                    null,
                    true
                  );
                }
              }
            })
            .catch(function () {
              //eslint-disable-next-line
              console.warn('unable to fetch deposit limits');
            });
        } else {
          DepositSrv.getPaymentTypeDepositLimit(accountId, depositType, cardType)
            .then(function (response) {
              $scope.data.disabledCard = false;
              $scope.depositDataModel.min = response.minSingleDepositLimit ?
                parseFloat(response.minSingleDepositLimit) : $scope.depositDataModel.min;
              $scope.depositDataModel.max = response.remainingDepositLimit ?
                parseFloat(response.remainingDepositLimit) : $scope.depositDataModel.max;

              if ($scope.depositDataModel.max === 0.00 ||
                $scope.depositDataModel.max < $scope.depositDataModel.min) {
                //  $scope.depositDataModel.min = $scope.depositDataModel.max;
                $scope.depositDataModel.max = 0;
                $scope.depositDataModel.maxOverflow = true;
                $scope.data.disabledCard = true;
                if (depositType === 'APPL') {
                  $scope.data.shouldDisableApplePayButton = true;
                  NotificationService.warning('Disabled Card',
                    getFromCMS('applePayDepositLimitExceeded'),
                    _getDepositFormFirstChildSelector(),
                    null,
                    true
                  );
                } else {
                  NotificationService.warning('Disabled Card',
                    $filter('CMSValue')('creditCardDepositLimitExceeded'),
                    _getDepositFormFirstChildSelector(), null, true);
                }
              }
            })
            .catch(function (obj) {
              if (obj && obj.useInitialDataDefault) {
                return null;
              }

              $scope.depositDataModel.min = 0;
              $scope.depositDataModel.max = 99999;
              //eslint-disable-next-line
              console.warn('unable to fetch deposit limits');
            });
        }
      }
    }

    /**
     * Set user ach accounts on file
     * @private
     */
    function _setUserCardsOnFile() {
      if ($scope.data.selectedPayOption.ftype !== 'CC' && !_isQuickDeposit()) {
        return {};
      }
      //eslint-disable-next-line
      var accountId = DepositSrv.user.get("accountNumber");
      //eslint-disable-next-line
      var cardOnFile = $location.search().cardOnFile;

      $scope.data.fetchingInfo = true;
      DepositSrv.getCardsOnFile(accountId)
        .then(function (data) {
          var optionsOnFile = [];
          var paramPaymentId = $location.search().paymentId;
          var cardIndexFromParamsFound;

          $scope.data.fetchingInfo = false;
          $scope.data.selectedPayOption.onFile = [];
          if (data.CardList && data.CardList.length > 0) {
            angular.forEach(data.CardList, function (card) {
              optionsOnFile.push({
                groupName: 'Cards On File',
                id: card.cardId,
                cardNumber: card.cardNumber,
                cardNumberExt: '****' + card.cardNumber,
                cardTypeId: DepositInitialDataFac.getCardType(card.cardType).id,
                limitTypeId:
                  DepositInitialDataFac.getDepositLimitType(card.cardType).id ||
                  DepositInitialDataFac.getDepositLimitTypeByAbbr(card.cardType)
                    .id,
                expirationDate: card.expDate,
                isExpired:
                  moment(card.expDate, 'MM/YY').add(1, 'month') < moment(),
                signed: card.signed,
                name:
                  '(****' +
                  card.cardNumber +
                  ') ' +
                  card.cardType +
                  ' ' +
                  card.expDate,
                ftype: 'CC',
                network: card.network,
                type: DepositInitialDataFac.getCardType(card.cardType).abbr,
                typeName: card.cardType,
                cardType: card.cardType,
                min: DepositInitialDataFac.getLimitType(
                  card.DepositLimitTypeId,
                  'min'
                ),
                max: DepositInitialDataFac.getLimitType(
                  card.DepositLimitTypeId,
                  'max'
                ),
                depositTypeId: DEPOSIT_TYPES.CARD_ON_FILE,
                lastUsedDate:
                  card.lastUsedDate || '1900-01-01T00:00:00.000-07:00'
              });
            });
            $scope.data.unableToFetchCardsOnFile = false;
            $scope.data.selectedPayOption.onFile = optionsOnFile;

            if (paramPaymentId && $location.search().initialTab) {
              cardIndexFromParamsFound = optionsOnFile.findIndex(function (
                card
              ) {
                return card.id.toString() === paramPaymentId;
              });

              if (cardIndexFromParamsFound >= 0) {
                $scope.data.selectedCard = cardIndexFromParamsFound;
                $scope.depositDataModel.selectedOnFile =
                  optionsOnFile[cardIndexFromParamsFound];
              }
            }

            if ($scope.data.depositSection !== 'STORED') {
              if (cardOnFile) {
                _toggleNewStoredMethods('NEW');
              } else {
                _toggleNewStoredMethods('STORED');
              }
            }
          } else {
            // Open new account section in case the user has no bank account associated
            if ($scope.data.depositSection !== 'NEW') {
              _toggleNewStoredMethods('NEW');
            }
            if ($scope.depositFrm && $scope.depositFrm.cardCvn) {
              $scope.depositFrm.cardCvn.$setPristine();
            }
            _clearCVN();
            _resetAllModels();
            _setDepositTypeLimits(
              $scope.depositDataModel.selectedCardType.ftype,
              $scope.depositDataModel.selectedCardType.type
            );
          }
          $scope.data.fetchingInfo = false;
        })
        .catch(function () {
          $scope.data.unableToFetchCardsOnFile = true;
          $scope.data.fetchingInfo = false;
        })
        .finally(function () {
          $scope.data.fetchingInfo = false;
        });

      return {};
    }

    /**
     * Set user ach accounts on file
     * @private
     */
    function _setUserBankAccounts() {
      var accountId = DepositSrv.user.get('accountNumber');
      var cardOnFile = $location.search().cardOnFile;
      if (
        !_isQuickDeposit() &&
        !(
          $scope.data.selectedPayOption.ftype === 'ACH' ||
          $scope.data.selectedPayOption.ftype === 'IBC'
        )
      ) {
        return {};
      }
      $scope.data.fetchingInfo = true;
      return DepositSrv.getUserBankAccounts(accountId)
        .then(function (data) {
          var paramPaymentId = $location.search().paymentId;
          var eCheckIndexFromParamsFound;
          var optionsOnFile = [];

          $scope.data.fetchingInfo = false;
          if (data.bankAccounts && data.bankAccounts.length > 0) {
            angular.forEach(data.bankAccounts, function (ach) {
              optionsOnFile.push({
                groupName: 'BetCash Accounts On File',
                achId: ach.id,
                bankAccNumber: ach.accountNumber,
                bankAcctType: ach.accountType,
                bankName: ach.name,
                bankRoutingNumber: ach.routingNumber,
                driversLicenseNumber: ach.dlNumber,
                driversLicenseState: ach.dlState,
                name:
                  '(****' +
                  ach.accountNumber.substr(ach.accountNumber.length - 4) +
                  ') ' +
                  ach.name,
                ftype: 'ACH',
                type: 'ACH',
                isPending: false,
                typeName: 'BetCash',
                isAvailable: true,
                cardType: undefined,
                limitTypeId:
                  DepositInitialDataFac.getLimitType('ACH', 'id') ||
                  DepositInitialDataFac.getDepositLimitTypeByAbbr('ACH').id,
                min: DepositInitialDataFac.getLimitType('ACH', 'min'),
                max: DepositInitialDataFac.getLimitType('ACH', 'max'),
                depositTypeId: DEPOSIT_TYPES.ACH_ON_FILE,
                lastUsedDate:
                  ach.lastUsedDate || '1900-01-01T00:00:00.000-07:00'
              });
            });

            $scope.data.unableToFetchBankAccounts = false;
            $scope.data.selectedPayOption.onFile = optionsOnFile;

            if (paramPaymentId && $location.search().initialTab === 'ACH') {
              eCheckIndexFromParamsFound = optionsOnFile.findIndex(function (
                eCheck
              ) {
                return eCheck.achId.toString() === paramPaymentId;
              });

              if (eCheckIndexFromParamsFound >= 0) {
                $scope.data.selectedCard = eCheckIndexFromParamsFound;
                $scope.depositDataModel.selectedOnFile =
                  optionsOnFile[eCheckIndexFromParamsFound];
              }
            }

            if ($scope.data.depositSection !== 'STORED') {
              if (cardOnFile) {
                _toggleNewStoredMethods('NEW');
              } else {
                _toggleNewStoredMethods('STORED');
              }
            }
          } else {
            // Open new account section in case the user has no bank account associated
            if ($scope.data.depositSection !== 'NEW') {
              _toggleNewStoredMethods('NEW');
            }
            if ($scope.depositFrm && $scope.depositFrm.cardCvn) {
              $scope.depositFrm.cardCvn.$setPristine();
            }
            _clearCVN();
            _resetAllModels();
          }
          $scope.data.fetchingInfo = false;
        })
        .catch(function () {
          $scope.data.unableToFetchBankAccounts = true;
          $scope.data.fetchingInfo = false;
        })
        .finally(function () {
          $scope.data.fetchingInfo = false;
        });
    }

    /**
     * Set user ach accounts on file on Quick deposit options
     * @private
     */
    function _getUserQuickDepositBankAccounts() {
      var accountId = DepositSrv.user.get('accountNumber');
      return DepositSrv.getUserBankAccounts(accountId)
        .then(function (data) {
          var optionsOnFile = [];
          if (data.bankAccounts && data.bankAccounts.length > 0) {
            angular.forEach(data.bankAccounts, function (ach) {
              optionsOnFile.push({
                groupName: 'BetCash Accounts On File',
                achId: ach.id,
                bankAccNumber: ach.accountNumber,
                bankAcctType: ach.accountType,
                bankName: ach.name,
                bankRoutingNumber: ach.routingNumber,
                driversLicenseNumber: ach.dlNumber,
                driversLicenseState: ach.dlState,
                name:
                  '(****' +
                  ach.accountNumber.substr(ach.accountNumber.length - 4) +
                  ') ' +
                  ach.name,
                ftype: 'ACH',
                type: 'ACH',
                isPending: false,
                limitTypeId: DepositInitialDataFac.getLimitType('ACH', 'id'),
                min: DepositInitialDataFac.getLimitType('ACH', 'min'),
                max: DepositInitialDataFac.getLimitType('ACH', 'max'),
                depositTypeId: DEPOSIT_TYPES.ACH_ON_FILE,
                lastUsedDate:
                  ach.lastUsedDate || '1900-01-01T00:00:00.000-07:00'
              });
            });

            return optionsOnFile;
          }
        })
        .catch(function () {
          $scope.data.unableToFetchBankAccounts = true;
          return null;
        });
    }

    /**
     * Set user ach accounts on file on Quick deposit options
     * @private
     */
    function _getUserQuickDepositCardsOnFile() {
      var accountId = DepositSrv.user.get('accountNumber');
      var optionsOnFile = [];

      return DepositSrv.getCardsOnFile(accountId)
        .then(function (data) {
          if (data.CardList && data.CardList.length > 0) {
            angular.forEach(data.CardList, function (card) {
              optionsOnFile.push({
                groupName: 'Cards On File',
                id: card.cardId,
                cardNumber: card.cardNumber,
                cardNumberExt: '****' + card.cardNumber,
                cardTypeId: DepositInitialDataFac.getCardType(card.cardType).id,
                limitTypeId: DepositInitialDataFac.getDepositLimitType(
                  card.cardType
                ).id,
                expirationDate: card.expDate,
                isExpired:
                  moment(card.expDate, 'MM/YY').add(1, 'month') < moment(),
                signed: card.signed,
                name:
                  '(****' +
                  card.cardNumber +
                  ') ' +
                  card.cardType +
                  ' ' +
                  card.expDate,
                ftype: 'CC',
                type: DepositInitialDataFac.getCardType(card.cardType).abbr,
                typeName: card.cardType,
                cardType: card.cardType,
                network: card.network,
                min: DepositInitialDataFac.getLimitType(
                  card.DepositLimitTypeId,
                  'min'
                ),
                max: DepositInitialDataFac.getLimitType(
                  card.DepositLimitTypeId,
                  'max'
                ),
                depositTypeId: DEPOSIT_TYPES.CARD_ON_FILE,
                lastUsedDate:
                  card.lastUsedDate || '1900-01-01T00:00:00.000-07:00'
              });
            });
          }
          return optionsOnFile;
        })
        .catch(function () {
          $scope.data.unableToFetchCardsOnFile = true;
          return null;
        });
    }

    function _getUserQuickDepositSLNCards() {
      var accountId = DepositSrv.user.get('accountNumber');
      var optionsOnFile = [];

      return DepositSrv.getPrepaidCardsOnFile(accountId)
        .then(function (userData) {
          if (userData) {
            $scope.depositDataModel.sightlineUser_v2 = userData;
            if (userData.cards && userData.cards.length > 0) {
              angular.forEach(userData.cards, function (card) {
                var expDate =
                  card.expirationMonth.toString() +
                  '/' +
                  card.expirationYear.toString().slice(-2);
                optionsOnFile.push({
                  groupName: 'Cards On File',
                  id: card.id,
                  cardNumber: card.number,
                  cardNumberExt: '****' + card.number,
                  cardTypeId: 1,
                  limitTypeId: 2,
                  expirationDate: expDate,
                  isExpired:
                    moment(expDate, 'MM/YY').add(1, 'month') < moment(),
                  signed: false,
                  name: '(****' + card.number + ') ' + expDate,
                  ftype: 'SLN',
                  type: 'SLN',
                  typeName: card.cardType || 'Credit',
                  network: card.network,
                  cardType: card.cardType || 'Credit',
                  min: false,
                  max: false,
                  depositTypeId: DEPOSIT_TYPES.SIGHTLINE_V2,
                  lastUsedDate:
                    card.lastUsedDate || '1900-01-01T00:00:00.000-07:00'
                });
              });
            }
            return optionsOnFile;
          }
        })
        .catch(function () {
          $scope.data.unableToFetchPrepaidCards = true;
          return null;
        });
    }

    /**
     * Get image for card in selector
     */
    // TODO change default image for credit cards (VISA, MasterCard, Discover)
    function _getCardImage(card) {
      if (card.network === 'VISA') {
        return 'visa-card';
      }

      if (card.network === 'MASTERCARD') {
        return 'master-card';
      }

      if (card.network === 'DISCOVER') {
        return 'discover-card';
      }

      if (card.type === 'ACH') {
        return 'betCash-card';
      }

      if (card === 'PAYPAL') {
        return 'paypal-card';
      }

      if (card.ftype === 'APPL') {
        return '';
      }

      return 'generic-credit-card';
    }

    /**
     * Get label for card in selector based on network property
     */
    function _getCardLabel(card) {
      var slnCardsTypes = ['DISCOVER', 'MASTERCARD', 'VISA'];
      var defaultLabel = 'Credit/Debit Card';
      if (card.network) {
        return slnCardsTypes.includes(card.network.toUpperCase())
          ? card.network
          : defaultLabel;
      }
      return defaultLabel;
    }

    /**
     * Get label for SLP card in selector based on network property
     * @param {Object} card               Card Object
     */
    function _getSLPLabel(card) {
      var declinedLabel;
      var network = _getCardLabel(card);
      var labelSLP = $rootScope.isFdrApp ? network.toLowerCase() : network;
      if (_isSLNDeclinedCard(card)) {
        declinedLabel = $filter('CMSLabels')('dmaCardDeclinedWarning', 'cardErrorRedirect');
        labelSLP += ' - ' + declinedLabel;
      }


      return labelSLP;
    }


    /**
     *
     */

    function _shouldShowOption(option) {
      var toggles = {
        IBC: !$rootScope.activeFeatures.pawsACH,
        CC: !$rootScope.activeFeatures.pawsCC,
        PNM: !$rootScope.activeFeatures.pawsPNM,
        PAY: !$rootScope.activeFeatures.pawsPAY,
        MPAK: !$rootScope.activeFeatures.pawsMPAK,
        BC: !$rootScope.activeFeatures.pawsACH,
        OTHER: !$rootScope.activeFeatures.pawsWalletAvailable
      };

      // eslint-disable-next-line angular/definedundefined
      return toggles[option] !== undefined && !$rootScope.isFdrApp &&
      $rootScope.activeFeatures.pawsWalletAvailable &&
      $rootScope.shouldShowWallet ? toggles[option] : true;
    }

    /**
     * Compile DEPOSIT payment options by mixing the available
     * deposit and credit types with the ones that the user owns.
     *
     * @param  {Object} data  Deposit initial data from API
     * @return {Object} data  Deposit initial data from API
     * @private
     */
    function _initFullDepositOptions(data, receivedLandingDepositTab) {
      var options = data.depositOptions.slice(0);
      var depositOptions = options.filter(function (option) {
        return _shouldShowOption(option.ftype);
      }
     );
      var selectedOptionIdx = null;
      var shouldLoadSightline = false;
      var shouldLoadPaypal = false;
      var depositLandingTab =
        receivedLandingDepositTab === 'IBC' ||
        receivedLandingDepositTab === 'ACH'
          ? 'IBC'
          : receivedLandingDepositTab;

      if ($scope.fromOption) {
        shouldLoadSightline =
          $scope.fromOption.tla === 'SLN' ||
          SightlineSrv.isRedirectingToSightlineAddFunds() ||
          $scope.redirectFrom === 'SLN';
        shouldLoadPaypal =
          $scope.fromOption.tla === 'PAY' || $scope.redirectFrom === 'PAY';
      }

      $scope.data.depositOptions = depositOptions;
      $scope.data.showingFallback = !depositOptions.length;
      $scope.data.forms = DepositSrv.getDepositForms();

      if (shouldLoadSightline) {
        _initSightlineOnStartup();
      } else if (shouldLoadPaypal) {
        _initPaypalOnStartup();
      } else {
        selectedOptionIdx = _getPayOptionIndex(
          depositOptions,
          depositLandingTab
        );
        $scope.data.selectedPayOption =
          selectedOptionIdx > -1
            ? depositOptions[selectedOptionIdx]
            : depositOptions[0];
        $rootScope.selectedPayOption = 0;
      }

      _resetDepositDataModel();

      return data;
    }

    function _getPayOptionIndex(data, option) {
      if (angular.isString(option)) {
        return _.findIndex(data, function (el) {
          return el.ftype === option;
        });
      }

      return option;
    }

    /**
     * Open sightline's tab on startup.
     * If redirected from quick-deposit "add funds" button, open the add funds
     * iframe.
     * @private
     */
    function _initSightlineOnStartup() {
      var isRedirecting = SightlineSrv.isRedirectingToSightlineAddFunds();

      if (isRedirecting) {
        SightlineSrv.isRedirectingToSightlineAddFunds(false);
        $scope.isAddingFunds = true;
      }

      _selectOption(SightlineDepositConfig, false);
    }

    /**
     * Open paypal's tab on startup.
     * If redirected from quick-deposit "add funds" button, open the add funds
     * iframe.
     * @private
     */
    function _initPaypalOnStartup() {
      _selectOption(PaypalDepositConfig, false);
    }

    function _selectOptionByName(optionName) {
      var opt = _.find($scope.data.depositOptions, function (option) {
        return option.name === optionName;
      });
      if (opt) {
        _selectOption(opt, true);
      }
    }

    /**
     * Show loaders while loading sightline user information
     * @private
     */
    function _startSightlineLoaders() {
      $scope.data.sightlineLoading = true;
      $scope.loadSightlineiFrame = false;
      $scope.loadSightlineInfo = false;
    }

    /**
     * Hide loaders after loading sightline user information
     * @private
     */
    function _stopSightlineLoaders() {
      $scope.data.sightlineLoading = false;
      $scope.loadSightlineiFrame = true;
      $scope.loadSightlineInfo = true;
    }

    /**
     * If there was a default payment card set in cookies,
     * check if type_id and id (or achId) match with any available payment
     * options.
     *
     * @private
     * @param {Array} depositOptions  Deposit payment options
     * @return {Object}               Default payment option
     */
    function _getDefaultPaymentCard(depositOptions) {
      var defaultCard = {};
      var selectedCard;
      var defaultCardId;

      Utilities.attempt(function () {
        defaultCard = angular.fromJson(
          $window.localStorage.getItem('defaultPaymentMethod')
        );
      });

      // stop
      if (!defaultCard) {
        return null;
      }

      defaultCardId = _getIdFromPaymentOption(defaultCard);

      selectedCard = _.find(depositOptions || [], function (card) {
        var cardId = _getIdFromPaymentOption(card);
        return cardId === defaultCardId;
      });

      return selectedCard;
    }

    /**
     * Extract the ID from payment option
     * (some payment types use the achId instead of id).
     *
     * @private
     * @param {Object} option            Payment options
     * @param {Number} [option.type_id]  Payment type ID
     * @param {String} [option.type]     Payment type
     * @param {String} [option.ftype]    Payment ftype
     * @param {Number} [option.id]       Payment ID
     * @param {Number} [option.achId]    Betcash payment ID
     * @return {Number}                  Correct payment ID
     */
    function _getIdFromPaymentOption(option) {
      var isBetcash = false;
      var paymentOption = option || {};

      if (
        paymentOption.type_id === 1 ||
        paymentOption.type === 'ACH' ||
        paymentOption.ftype === 'ACH'
      ) {
        isBetcash = true;
      }

      return isBetcash ? option.achId || option.id : option.id;
    }

    /**
     * Clear card verification number
     */
    function _clearCVN() {
      $scope.depositDataModel.cardSecurityNumber = '';
    }

    function _clearIBC() {
      if ($scope.depositDataModel) {
        $scope.depositDataModel.cardNumber = '';
        $scope.depositDataModel.cardSecurityNumber = '';
        $scope.depositDataModel.expirationMonth = '';
        $scope.depositDataModel.expirationYear = '';
        _resetAllModels();
      }
    }

    /**
     * Trigger goto_new_deposit event
     */
    function _goToFullDeposit() {
      if (isNative) {
        if ($window && $window.handleNativeMessages) {
          $window.handleNativeMessages('GO_TO_DEPOSITS');
        }
      }

      if (ConfigurationFac.getApplicationContextItem('product') !== 'njx') {
        $rootScope.$broadcast('goto_new_deposit');

        /* Redirect for For TVG3 */
        Utilities.attempt(function () {
          if (
            $window.document.domain === $window.parent.document.domain &&
            angular.isDefined($window.parent.GoToDeposit)
          ) {
            $window.parent.GoToDeposit(); // eslint-disable-line
          }
        });
        /* Redirect for FDR */
        if ($rootScope.isFdrApp) {
          $window.parent.location.href =
            '/deposit/deposit?location=' +
            ConfigurationFac.getApplicationContextItem('location') +
            '&product=' +
            $rootScope.product +
            '&wrapper=true&callback=' +
            $location.search().callback +
            '/more&fullPage=true&more=true';
        }
      }
    }

    /**
     * Open Invalid Card Modal
     * @params {string} type                  Card type
     * @return {string} cardName              Card name
     */
    function _getCardNameByType(type) {
      return Utilities.attempt(
        function () {
          var selectionTypeCAPI = {
            CC: 'Another Card',
            IBC: 'eCheck',
            PAY: 'Paypal'
          };

          return _.get(selectionTypeCAPI, type, 'Unknown');
        },
        function () {
          return 'Unknown';
        }
      );
    }

    /**
     * Open Invalid Card Modal
     * @param {boolean} openRedirectModal               Open redirect modal
     */
    function invalidCardModal(openRedirectModal) {
      var closeRedirectModal = function (sendGtm) {
        $window.parent.postMessage(
          {
            type: 'sightline_redirect',
            payload: false
          },
          '*'
        );

        // GTM
        if (sendGtm) {
          if (!openRedirectModal) {
            UserActionEventsService.emit(
              'CcpCardDeclinedRedirectSightline',
              {
                isOpen: false,
                module: 'My Funds',
                depositAmount: $scope.depositDataModel.amount
              }
            );
          } else {
            UserActionEventsService.emit(
              'CcpCardDeclinedRedirectBlackListCard',
              {
                isOpen: false
              }
            );
          }
        }
      };

      var modalScope = $scope.$new();
      var defaultSelection = 'CC';
      modalScope.areTermsAccepted = false;

      modalScope.proceed = function (closeFn) {
        _makeDepositInvalidCreditCardError(false);
        closeRedirectModal(false);
        closeFn({ fromProceed: true });
      };

      modalScope.openPrivacyPolicy = function (evt) {
        evt.preventDefault();
        ModalDialogService.openLarge(
          $filter('CMSValue')('sightlinePrivacyTitle'),
          $filter('CMSValue')('sightlinePrivacyTemplate'),
          'sightlinePrivacyPolicyModal'
        );
      };

      modalScope.openTermsConditions = function (evt) {
        evt.preventDefault();
        ModalDialogService.openLarge(
          $filter('CMSValue')('prepaidCardTermsTitle'),
          $filter('CMSValue')('prepaidCardTermsTemplate'),
          'sightlineTermsConditionModal'
        );
      };

      // Define
      modalScope.depositOptions = $scope.data.depositOptions.reduce(
        function (depositOptionsAvailable, depositOption) {
          var availableCards = ['IBC', 'PAY', 'CC'];
          if (availableCards.includes(depositOption.ftype)) {
            depositOptionsAvailable.push(depositOption.ftype);
          }
          return depositOptionsAvailable;
        }, []);

      modalScope.type = defaultSelection;

      modalScope.changeType = function (type) {
        var selection = _getCardNameByType(type || defaultSelection);
        modalScope.type = type || defaultSelection;

        // GTM
        UserActionEventsService.emit(
          'CcpCardDeclinedRedirectBlackListCard',
          {
            selection: selection,
            isFinished: false
          }
        );
      };

      modalScope.redirectTo = function (close, type) {
        var method;
        var selection = _getCardNameByType(type || defaultSelection);

        _clearIBC();

        if (type) {
          method = _getPaymentMethod(type);
          $scope.events.selectOption(method, true, false);
        }

        // GTM
        UserActionEventsService.emit(
          'CcpCardDeclinedRedirectBlackListCard',
          {
            selection: selection,
            isFinished: true
          }
        );

        close();
      };

      modalScope.cardList = Utilities.attempt(
        function () {
          var capiMessages = angular.fromJson(
            $filter('CMSValue')('cardErrorRedirect')
          );
          return _.get(capiMessages, 'cardList', []);
        },
        function () {
          return [];
        }
      );

      if (openRedirectModal) {
        UserActionEventsService.emit(
          'CcpCardDeclinedRedirectBlackListCard',
          {
            isOpen: true
          }
        );
      }

      $uibModal
        .open({
          templateUrl: openRedirectModal ? 'src/templates/ccp_visa_sightline_redirect.html' : 'src/templates/ccp_sightline_redirect.html',
          scope: modalScope,
          windowTemplateUrl: 'src/templates/modal-window.html',
          backdropClass: 'tvgmodal-backdrop',
          windowClass: 'tvg-ui-modal-dialog tvgmodal-dma-redesign'
        })
        .result.then(function (res) {
          if (res && res.fromProceed) {
            closeRedirectModal(false);
          } else {
            closeRedirectModal(!openRedirectModal);
          }
        })
        .catch(function () {
          closeRedirectModal(!openRedirectModal);
        });
    }

    function _getUsedCardType() {
      var bankNumber;
      var firstDigit;
      var secondDigit;

      if ($scope.depositDataModel.routingNumber) {
        bankNumber = $scope.depositDataModel.routingNumber;
        firstDigit = bankNumber % 1000;
        if (firstDigit === 4) {
          return 'Visa';
        } else if (firstDigit === 5) {
          secondDigit = bankNumber % 100;
          if (secondDigit > 0 && secondDigit < 6) {
            return 'Mastercard';
          }
        }
      }
      return undefined;
    }

    function _mapLabelToPaymentMethod(paymentType) {
      switch (paymentType) {
        case DEPOSIT_TYPES.ACH_ON_FILE:
        case DEPOSIT_TYPES.ACH_NEW:
          return 'betCashDepositMessages';

        case DEPOSIT_TYPES.CARD_ON_FILE:
        case DEPOSIT_TYPES.CARD_NEW:
        case DEPOSIT_TYPES.CREDIT_CARD_NEW:
          return 'ccpDepositMessages';

        case DEPOSIT_TYPES.SIGHTLINE:
          return 'sightlineDepositMessages';

        default:
          return 'sightlineDepositMessages';
      }
    }

    function _initiateDepositStatusPoller(
      data,
      context,
      messages,
      successCb,
      errorCb
    ) {
      Utilities.depositStatusPoller(
        function () {
          $scope.data.activePoller = true;
          return DepositSrv.getDepositStatus(data.headers('Location'))
            .then(function (response) {
              return response.status;
            })
            .catch(errorCb);
        },
        10000,
        2000
      )
        .then(successCb)
        .catch(errorCb)
        .finally(function () {
          $scope.data.activePoller = false;
        });
    }

    function _slpSuccessPollerCb(
      messages,
      depositType,
      isSightline,
      data,
      context,
      success
    ) {
      if (success) {
        NotificationService.success(
          'Poller!',
          messages.scenario5,
          context,
          null,
          true
        );
        _makeDepositSuccess(data, isSightline, false);
      } else {
        NotificationService.warning(
          'Poller!',
          messages.scenario3a,
          context,
          null,
          true
        );
        _makeDepositError(data.data, isSightline);
      }
    }

    function _slpErrorPollerCb(context, messages, isSightlineSelected) {
      if (isSightlineSelected) {
        NotificationService.warning(
          'Deposit Poller',
          messages.scenario3c,
          context,
          null,
          true
        );
      }
    }

    function _achSuccessPollerCb(
      messages,
      depositType,
      isAch,
      data,
      context,
      success
    ) {
      if (success) {
        NotificationService.success(
          'Poller!',
          messages.scenario5,
          context,
          null,
          true
        );
        _makeDepositSuccess(data, false, isAch);
      } else {
        NotificationService.warning(
          'Poller!',
          messages.scenario3a,
          context,
          null,
          true
        );
        _makeDepositError(data.data, isAch);
      }
    }

    function _achErrorPollerCb(context, messages, isAchSelected) {
      if (isAchSelected) {
        NotificationService.warning(
          'Deposit Poller',
          messages.scenario3c,
          context,
          null,
          true
        );
      }
    }

    function _newCardSuccessPollerCb(
      messages,
      depositType,
      isNewCard,
      data,
      context,
      success
    ) {
      if (success) {
        NotificationService.success(
          'Poller!',
          messages.scenario5,
          context,
          null,
          true
        );
        // update balance
        if (data.data && data.data.balance) {
          $rootScope.$emit(
            'accountBalance_changed',
            parseFloat(data.data.balance)
          );
        }
        _makeDepositSuccess(data, false, isNewCard);
      } else {
        NotificationService.warning(
          'Poller!',
          messages.scenario3a,
          context,
          null,
          true
        );
        _makeDepositError(data.data, isNewCard);
      }
    }

    function _newCardErrorPollerCb(context, messages, isCc) {
      if (isCc) {
        NotificationService.warning(
          'Deposit Poller',
          messages.scenario3c,
          context,
          null,
          true
        );
      }
    }

    function _cardsOnFileSuccessPollerCb(
      messages,
      depositType,
      isCardOnFile,
      data,
      context,
      success
    ) {
      if (success) {
        NotificationService.success(
          'Poller!',
          messages.scenario5,
          context,
          null,
          true
        );
        // update balance
        if (data.data && data.data.balance) {
          $rootScope.$emit(
            'accountBalance_changed',
            parseFloat(data.data.balance)
          );
        }
        _makeDepositSuccess(data, false, isCardOnFile);
      } else {
        NotificationService.warning(
          'Poller!',
          messages.scenario3a,
          context,
          null,
          true
        );
        _makeDepositError(data.data, isCardOnFile);
      }
    }

    function _achNewAccountSuccessPollerCb(
      messages,
      depositType,
      isAch,
      data,
      context,
      success
    ) {
      if (success) {
        NotificationService.success(
          'Poller!',
          messages.scenario5,
          context,
          null,
          true
        );
        // update balance
        if (data.data && data.data.balance) {
          $rootScope.$emit(
            'accountBalance_changed',
            parseFloat(data.data.balance)
          );
        }
        _makeDepositSuccess(data, false, isAch);
        // change page and update list of cards
        showStoredBetcashAccounts();
      } else {
        NotificationService.warning(
          'Poller!',
          messages.scenario3a,
          context,
          null,
          true
        );
        _makeDepositError(data.data, isAch);
      }
    }

    function _achNewAccountErrorPollerCb(context, messages, isAchSelected) {
      if (isAchSelected) {
        NotificationService.warning(
          'Deposit Poller',
          messages.scenario3c,
          context,
          null,
          true
        );
      }
    }

    function _cardsOnFileErrorPollerCb(context, messages, isCc) {
      if (isCc) {
        NotificationService.warning(
          'Deposit Poller',
          messages.scenario3c,
          context,
          null,
          true
        );
      }
    }

    function showStoredBetcashAccounts() {
      // REMOVE THE TIMEOUT PLS
      $scope.data.fetchingInfo = true;
      $timeout(function () {
        _setUserBankAccounts().then(function () {
          _toggleNewStoredMethods('STORED');
          $scope.data.fetchingInfo = false;
        });
      }, 5000);
    }


    /**
     * Make deposit function. It calls deposit service passing it
     * depositDataModel as argument
     * @private
     */
    function _makeDeposit(form) {
      var accountNumber = $scope.accountDetails.accountDetails.accountNumber; //eslint-disable-line
      var isQuickDeposit = _isQuickDeposit();
      var gtmDepositAmount =
        $scope.depositDataModel.amount ||
        Utilities.prop('depositFrm.amount.$viewValue', $scope);

      UserActionEventsService.emit('depositAttempt', {
        depositType: _getCurrentDepositTypeString(),
        depositAmount: gtmDepositAmount,
        amountOption: _isDefaultAmount(),
        module: isQuickDeposit ? 'Quick Deposit' : 'My Funds'
      });

      if (!form.$valid) {
        if ($scope.notifyErrors) {
          // TODO: send first invalid field name
          $scope.$emit('depositFormValidationError', 'TODO');
        } else {
          FeedbackFac.scrollIntoFirstError();

          $scope.data.showInvalidFormMessage = true;
          $timeout.cancel(invalidFormLabelTimer);
          invalidFormLabelTimer = $timeout(function () {
            $scope.data.showInvalidFormMessage = false;
          }, 3000);
        }

        _saveGTMDepositError('Missing Fields/Invalid Fields');

        angular.forEach(form.$error.required, function (field) {
          if (form[field.$name] && form[field.$name].hasOwnProperty('$dirty')) {
            form[field.$name].$dirty = true;
          }
        });
        return 0;
        /* eslint-disable */
      } else {
        /* eslint-enable */
        if ($scope.data.fee.calculatingFees || $scope.data.makingDeposit) {
          return 0;
        }
        $scope.data.makingDeposit = true;
        $scope.data.showInvalidFormMessage = false;
        $scope.data.showGreenDotInvalidCardNumberMessage = false;
        $scope.data.showIBCInvalidPinOrPasswordMessage = false;

        if (_isSightlinePayment()) {
          $scope.depositDataModel.sightlineUser = angular.extend(
            {},
            $scope.basicSightlineUsr,
            {
              last4SSN: DepositSrv.user.get('last4SSN')
            }
          );
        }

        DepositSrv.makeDeposit($scope.depositDataModel)
          .then(function (data) {
            var depositType = $scope.depositDataModel.depositTypeId;
            var isSightline = depositType === 12;
            var isSightlineV2 = depositType === 13;
            var isAch =
              depositType === DEPOSIT_TYPES.ACH_ON_FILE ||
              depositType === DEPOSIT_TYPES.ACH_NEW;
            var isCardOnFile = depositType === DEPOSIT_TYPES.CARD_ON_FILE;
            var isNewCc =
              depositType === DEPOSIT_TYPES.CARD_NEW ||
              depositType === DEPOSIT_TYPES.CREDIT_CARD_NEW;
            var statusCode = data.status;
            var context = _getDepositFormFirstChildSelector();
            var label = _mapLabelToPaymentMethod(depositType);
            var messagesObj = $filter('CMSValue')(label);
            var messages = {};
            var newCcFlow = isCardOnFile || isNewCc;
            var isSightlineSelected = $scope.data.selectedPayOption
              ? $scope.data.selectedPayOption.ftype === 'SLN'
              : false;
            var isAchSelected = $scope.data.selectedPayOption
              ? $scope.data.selectedPayOption.ftype === 'IBC' ||
                $scope.data.selectedPayOption.ftype === 'ACH'
              : false;
            var isCC = !isQuickDeposit
              ? $scope.data.selectedPayOption.ftype === 'CC'
              : $scope.depositDataModel.selectedOnFile &&
                $scope.depositDataModel.selectedOnFile.ftype === 'CC';
            var isAchNewAccount =
              !isQuickDeposit && $scope.data.depositSection === 'NEW';
            var has207Error = false;
            var depositSuccessMessage;
            var successMessage;
            var depositSuccessFallbackMsg =
              'You successfully deposited <strong>$XXX</strong> into your TVG account through your Pre Paid Card.';
            var depositCode; //eslint-disable-line
            if (isQuickDeposit && !isAchSelected) {
              isAchSelected = $scope.depositDataModel.selectedOnFile
                ? $scope.depositDataModel.selectedOnFile.ftype === 'ACH' ||
                  $scope.depositDataModel.selectedOnFile.ftype === 'IBC'
                : false;
            }
            $scope.data.lastDepositStatus = statusCode;

            if (isAchSelected) {
              depositCode = 'ACH';
            }

            if (isSightlineSelected) {
              depositCode = 'SLN';
            }

            if (isCC) {
              depositCode =
                $scope.depositDataModel.selectedCardType.type;
            }

            try {
              messages = angular.fromJson(messagesObj);
            } catch (err) {
              // Prevent test failure
            }


            if ($rootScope.activeFeatures.isDMAInjectDepositSuccessModalEnabled) {
              if ($window.ReactInjector) {
                $window.ReactInjector.renderDepositSuccess(
                    document.getElementById('injected-modal'),// eslint-disable-line
                  {
                    title: SUCCESS_MODAL_LABELS.title,
                    text: SUCCESS_MODAL_LABELS.textTemplate.replace(
                      '@@@deposit_amount@@@',
                        data &&
                      data.config &&
                      data.config.data &&
                      data.config.data.amount),
                    buttonText: SUCCESS_MODAL_LABELS.buttonText,
                    sharedState: { isOpen: true },
                    buttonCallback: successModalButtonCallback,
                    closeCallback: successModalCloseCallback,
                    onOpenCallback: successModalOnOpenCallback
                  }
                );
              }
            }


            if (data.data && data.status === 200 && isSightlineV2) {
              // sightline v2 fund and deposit success

              depositSuccessMessage =
                $filter('CMSValue')('slpDepositSuccess') ||
                depositSuccessFallbackMsg;
              successMessage =
                'Deposit Successful! ' +
                depositSuccessMessage.replace('XXX', data.config.data.amount);
              NotificationService.success(
                'Deposit Successful!',
                successMessage,
                context,
                $scope.callback,
                true
              );

              // gtm success event
              _saveSuccessfulDepositOnGTM();

              _resetAllModels();
              _resetFeesInfo();

              $scope.$emit('onDepositEventSuccess', data);
              $rootScope.$broadcast('accountBalance_update');

              $scope.depositDataModel.amount = null;
            }

            if (data.data && data.data.tvgBalance && isSightlineV2) {
              $rootScope.$emit(
                'accountBalance_changed',
                parseFloat(data.data.tvgBalance)
              );
            }

            if (data.data && data.data.balance && isAch) {
              $rootScope.$emit('accountBalance_changed', data.data.balance);
            }

            if (
              statusCode &&
              statusCode === 207 &&
              (isSightline || isSightlineV2)
            ) {
              if (_.isArray(data.data)) {
                // eslint-disable-next-line
                var slpWithdrawal = data.data.filter(function(item) {
                  return item.id === 'SIGHTLINE_WITHDRAWAL';
                });
                // eslint-disable-next-line
                var firstStep =
                  slpWithdrawal.length === 1 ? slpWithdrawal[0] : null;
                // eslint-disable-next-line
                var toteDeposit = data.data.filter(function(item) {
                  return item.id === 'TOTE_DEPOSIT';
                });
                // eslint-disable-next-line
                var secondStep =
                  toteDeposit.length === 1 ? toteDeposit[0] : null;
                if (firstStep && firstStep.body) {
                  $scope.sightlineBalance = parseFloat(
                    firstStep.body.sightlineBalance
                  );
                }

                if (secondStep && secondStep.body) {
                  // eslint-disable-next-line
                  var status = secondStep.body.status;
                  // eslint-disable-next-line
                  var errorCode = secondStep.body.exception;
                  has207Error = true;

                  if (!status || !errorCode) {
                    NotificationService.error(
                      'Deposit Poller',
                      _defaultErrorMessage(),
                      context,
                      null,
                      true
                    );
                  } else {
                    switch (status) {
                      case 504:
                      case 502:
                        NotificationService.error(
                          'Deposit Poller',
                          messages.scenario2,
                          context,
                          null,
                          true
                        );
                        break;
                      case 500:
                        if (errorCode === 'SLP_WITHDRAW_FROM_SLP_DECLINED') {
                          NotificationService.error(
                            'Deposit Poller',
                            messages.scenario1,
                            context,
                            null,
                            true
                          );
                        } else if (errorCode === 'SLP_TOTE_DEPOSIT_FAILED') {
                          NotificationService.warning(
                            'Deposit Poller',
                            messages.scenario3a,
                            context,
                            null,
                            true
                          );
                        } else {
                          // generic message
                          NotificationService.error(
                            'Deposit Poller',
                            _defaultErrorMessage(),
                            context,
                            null,
                            true
                          );
                        }
                        break;
                      default:
                        NotificationService.error(
                          'Deposit Poller',
                          messages.scenario3c,
                          context,
                          null,
                          true
                        );
                        break;
                    }
                  }
                }
              }
            }

            if (
              statusCode &&
              statusCode === 202 &&
              (isSightline || isSightlineV2)
            ) {
              NotificationService.warning(
                'Poller!',
                messages.scenario3b,
                context,
                null,
                true
              );
              _initiateDepositStatusPoller(
                data,
                context,
                messages,
                _slpSuccessPollerCb.bind(
                  // eslint-disable-next-line
                  this,
                  messages,
                  depositType,
                  isSightline,
                  data,
                  context
                ),
                _slpErrorPollerCb.bind(
                  // eslint-disable-next-line
                  this,
                  context,
                  messages,
                  isSightlineSelected || isSightlineV2
                )
              );
            }

            if (statusCode && statusCode === 202 && isAch) {
              NotificationService.warning(
                'Poller!',
                messages.scenario3b,
                context,
                null,
                true
              );
              _initiateDepositStatusPoller(
                data,
                context,
                messages,
                _achSuccessPollerCb.bind(
                  // eslint-disable-next-line
                  this,
                  messages,
                  depositType,
                  isAch,
                  data,
                  context
                ),
                // eslint-disable-next-line
                _achErrorPollerCb.bind(this, context, messages, isAchSelected)
              );
            }

            if (
              statusCode &&
              statusCode === 202 &&
              isAchNewAccount &&
              isAchSelected
            ) {
              NotificationService.warning(
                'Poller!',
                messages.scenario3b,
                context,
                null,
                true
              );
              _initiateDepositStatusPoller(
                data,
                context,
                messages,
                _achNewAccountSuccessPollerCb.bind(
                  // eslint-disable-next-line
                  this,
                  messages,
                  depositType,
                  isAch,
                  data,
                  context
                ),
                _achNewAccountErrorPollerCb.bind(
                  // eslint-disable-next-line
                  this,
                  context,
                  messages,
                  isAchSelected
                )
              );
            }

            if (statusCode && statusCode === 202 && isCardOnFile) {
              NotificationService.warning(
                'Poller!',
                messages.scenario3b,
                context,
                null,
                true
              );
              _initiateDepositStatusPoller(
                data,
                context,
                messages,
                _cardsOnFileSuccessPollerCb.bind(
                  // eslint-disable-next-line
                  this,
                  messages,
                  depositType,
                  isCardOnFile,
                  data,
                  context
                ),
                // eslint-disable-next-line
                _cardsOnFileErrorPollerCb.bind(this, context, messages, isCC)
              );
            }

            if (statusCode && statusCode === 202 && isNewCc) {
              NotificationService.warning(
                'Poller!',
                messages.scenario3b,
                context,
                null,
                true
              );
              _initiateDepositStatusPoller(
                data,
                context,
                messages,
                _newCardSuccessPollerCb.bind(
                  // eslint-disable-next-line
                  this,
                  messages,
                  depositType,
                  isNewCc,
                  data,
                  context
                ),
                // eslint-disable-next-line
                _newCardErrorPollerCb.bind(this, context, messages, isCC)
              );
            }

            if (statusCode === 200 && isSightline && isSightlineSelected) {
              if (!_showNewDepositSuccessModal()) {
                NotificationService.success(
                  'Poller!',
                  messages.scenario5,
                  context,
                  null,
                  true
                );
              }
            }

            if (statusCode === 200 && isAch && isAchSelected) {
              if (data.data && data.data.balance) {
                $rootScope.$emit(
                  'accountBalance_changed',
                  parseFloat(data.data.balance)
                );
              }
              if (!_showNewDepositSuccessModal() ||
                data.status !== 200
              ) {
                NotificationService.success(
                  'Poller!',
                  messages.scenario5,
                  context,
                  null,
                  true
                );
              }
            }

            if (statusCode === 200 && isCardOnFile) {
              if (data.data && data.data.balance) {
                $rootScope.$emit(
                  'accountBalance_changed',
                  parseFloat(data.data.balance)
                );
              }
              if (!_showNewDepositSuccessModal() ||
                data.status !== 200
              ) {
                NotificationService.success(
                  'Poller!',
                  messages.scenario5,
                  context,
                  null,
                  true
                );
              }
            }

            if (statusCode === 200 && isAchNewAccount && isAchSelected) {
              // update balance
              if (data.data && data.data.balance) {
                $rootScope.$emit(
                  'accountBalance_changed',
                  parseFloat(data.data.balance)
                );
              }
              if (!_showNewDepositSuccessModal() ||
                data.status !== 200) {
                NotificationService.success(
                  'Poller!',
                  messages.scenario5,
                  context,
                  null,
                  true
                );
              }
              $scope.data.fetchingInfo = true;
              // change page and update list of cards
              showStoredBetcashAccounts();
            }

            if (statusCode === 200 && isNewCc) {
              if (data.data && data.data.balance) {
                $rootScope.$emit(
                  'accountBalance_changed',
                  parseFloat(data.data.balance)
                );
              }
              if (!_showNewDepositSuccessModal() ||
                data.status !== 200) {
                NotificationService.success(
                  'Poller!',
                  messages.scenario5,
                  context,
                  null,
                  true
                );
              }
            }

            if (statusCode !== 202 && !isSightlineV2) {
              if (!has207Error) {
                _makeDepositSuccess(data, isSightline, isAch || newCcFlow);
              } else {
                _makeDepositError(data, isSightline || isAch || newCcFlow);
              }
            }

            if (statusCode === 207 && (isCardOnFile || isNewCc)) {
              if (
                data.data &&
                data.data[1] &&
                data.data[1].body.code === 107505
              ) {
                // deposit will happen via CS
                NotificationService.warning(
                  '',
                  $filter('CMSLabels')('scenario3a', 'ccpDepositMessages'),
                  context,
                  null,
                  true
                );
              }
            }

            if (statusCode === 200 || statusCode === 202 || statusCode === 207) {
              $scope.data.responsibleGamingDelay = true;

              $timeout(function () {
                $scope.data.responsibleGamingDelay = false;
              }, parseInt($filter('CMSValue')('debounceAfterDeposit'), 10) || 0);
            }

            DepositSrv._setHasMadeInitialDeposit(true);
            $scope.defaultParams.customerStatus = DepositSrv.getCustomerStatus();
            DepositSrv.updateCustomerStatus();
          })
          .catch(function (data) {
            var depositType = $scope.depositDataModel.depositTypeId;
            var isSightline = depositType === 12;
            var isAch =
              depositType === DEPOSIT_TYPES.ACH_ON_FILE ||
              depositType === DEPOSIT_TYPES.ACH_NEW;
            var context = _getDepositFormFirstChildSelector();
            var isCardOnFile = depositType === DEPOSIT_TYPES.CARD_ON_FILE;
            var label = _mapLabelToPaymentMethod(depositType);
            var isNewCc =
              depositType === DEPOSIT_TYPES.CARD_NEW ||
              depositType === DEPOSIT_TYPES.CREDIT_CARD_NEW;
            var newCcFlow = isCardOnFile || isNewCc;
            var messagesObj = $filter('CMSValue')(label);
            var messages = {};
            var isSightlineSelected =
              !isQuickDeposit && $scope.data.selectedPayOption
                ? $scope.data.selectedPayOption.ftype === 'SLN'
                : false;
            var isAchSelected = $scope.data.selectedPayOption
              ? $scope.data.selectedPayOption.ftype === 'IBC' ||
                $scope.data.selectedPayOption.ftype === 'ACH'
              : false;
            var isCC = !isQuickDeposit
              ? $scope.data.selectedPayOption.ftype === 'CC'
              : $scope.depositDataModel.selectedOnFile &&
              $scope.depositDataModel.selectedOnFile.ftype === 'CC';
            var depositCode; //eslint-disable-line

            var isSightlineV2 = $scope.depositDataModel.sightlineUser_v2;
            var VISA_INITIAL = '4';
            var errorMessage;
            var notifType = 'error';
            var notifTitle = '';
            var depositMessages;
            var fundSuccessDepositFailMessage;
            var fundSuccessMsg =
              'You funded your Prepaid Card with <strong>$XXX</strong>. You now need to transfer this amount to your TVG Account.';
            var isFundSuccessDepositFail =
              data.name && data.name === 'fundSuccessDepositFail';
            //eslint-disable-next-line
            var defaultSLPErrorMessage =
              'Please review the deposit details and try again.' +
              'If problem persists, please contact customer support at 1-888-PLAY-TVG (752-9884).';
            var exceptionCode = data.exceptionCode || data.errorCode;
            var RGLimitsExceededErrorCode = [107417, 101417];
            var isRGException = RGLimitsExceededErrorCode.includes(exceptionCode);
            var isVisa = isCardOnFile ?
              $scope.depositDataModel &&
              $scope.depositDataModel.selectedOnFile &&
              $scope.depositDataModel.selectedOnFile.network === 'VISA' :
              form.cardNumber &&
              form.cardNumber.$viewValue &&
              form.cardNumber.$viewValue[0] === VISA_INITIAL;

            if (isQuickDeposit && !isAchSelected) {
              isAchSelected = $scope.depositDataModel.selectedOnFile
                ? $scope.depositDataModel.selectedOnFile.ftype === 'ACH' ||
                  $scope.depositDataModel.selectedOnFile.ftype === 'IBC'
                : false;
            }

            if (isAchSelected) {
              depositCode = 'ACH';
            }

            if (isSightlineSelected) {
              depositCode = 'SLN';
            }

            if (isCC) {
              depositCode =
                $scope.depositDataModel.selectedCardType.type;
            }

            try {
              messages = angular.fromJson(messagesObj);
            } catch (err) {
              // Prevent test failure
            }
            if (isSightlineSelected && data && !isSightlineV2) {
              if ((data && data.status === 504) || data.status === 502) {
                NotificationService.error(
                  'Deposit Poller',
                  messages.scenario2,
                  context,
                  null,
                  true
                );
              } else if (data && data.status === 500) {
                if (data.code === 'SLP_WITHDRAW_FROM_SLP_DECLINED') {
                  NotificationService.error(
                    'Deposit Poller',
                    messages.scenario1,
                    context,
                    null,
                    true
                  );
                } else if (data.code === 'SLP_TOTE_DEPOSIT_FAILED') {
                  NotificationService.warning(
                    'Deposit Poller',
                    messages.scenario3a,
                    context,
                    null,
                    true
                  );
                } else {
                  // generic message
                  NotificationService.error(
                    'Deposit Poller',
                    _defaultErrorMessage(),
                    context,
                    null,
                    true
                  );
                }
              } else if (data.code === 'RESP_GAMING_LIMITS_EXCEEDED') {
                _handleRGLimitsExceeded(data);
              } else if (!data.status || !data.code) {
                NotificationService.error(
                  'Deposit Poller',
                  _defaultErrorMessage(),
                  context,
                  null,
                  true
                );
              } else {
                NotificationService.warning(
                  'Deposit Poller',
                  messages.scenario3c,
                  context,
                  null,
                  true
                );
              }
            }

            if (isSightlineV2 && data) {
              if (isFundSuccessDepositFail) {
                notifType = 'warning';
                notifTitle = 'Fund success! ';
                fundSuccessDepositFailMessage =
                  $filter('CMSValue')('slpFundSuccessDepositFail') ||
                  fundSuccessMsg;
                errorMessage = fundSuccessDepositFailMessage.replace(
                  'XXX',
                  +$scope.depositDataModel.sightlineUser_v2.depositFee +
                    $scope.depositDataModel.amount
                );
              }

              if (data.message && data.message.indexOf('scenario') !== -1) {
                notifType =
                  data.message.indexOf('scenario1') !== -1
                    ? 'error'
                    : 'warning';
                depositMessages = $filter('CMSValue')(
                  'sightlineDepositMessages'
                );
                errorMessage = angular.fromJson(depositMessages)[data.message];
              } else if (!isFundSuccessDepositFail) {
                notifType = 'error';
                notifTitle = 'Deposit Failed! ';
                errorMessage =
                  _.attempt(function () {
                    $filter('CMSValue')(data.code || data.errorCode);
                  }) || $filter('CMSValue')('SLP_GENERIC_ERROR');
                if (!errorMessage) {
                  errorMessage = defaultSLPErrorMessage;
                }
              }
              NotificationService[notifType](
                'Deposit Failed!',
                notifTitle + errorMessage,
                context,
                null,
                true
              );
            }

            if (isAchSelected) {
              if (data.code === 'ACH_TOTE_DEPOSIT_FAILED') {
                NotificationService.warning(
                  'Deposit Poller',
                  messages.scenario3a,
                  context,
                  null,
                  true
                );
              } else if (data.code === 'ACH_DEPOSIT_DECLINED') {
                NotificationService.error(
                  'Deposit Poller',
                  messages.scenario1,
                  context,
                  null,
                  true
                );
              } else {
                NotificationService.error(
                  'Deposit Poller!',
                  _defaultErrorMessage(),
                  context,
                  null,
                  true
                );
              }
            }

            if (!isSightlineSelected && !isAchSelected) {
              switch (exceptionCode) {
                case 107701:
                case 107501:
                case 306:
                case 'OLD_CCP_DISCOVER_CARD':
                  if ($rootScope.activeFeatures.showCardDeclinedModal &&
                    (isVisa ||
                      ($rootScope.sightlineFlowVersion === '2'
                        && !isCardOnFile)) &&
                    !_isQuickDeposit()
                  ) {
                    invalidCardModal(true);
                  } else {
                    _oldDepositCardDeclinedFlow();
                  }
                  break;
                default:
                  if (
                    !$filter('CMSLabels')(
                      data.exceptionCode,
                      'depositErrorCodes'
                    ) ||
                    data.exceptionCode === 'generic'
                  ) {
                    NotificationService.error(
                      '',
                      $filter('CMSLabels')('generic', 'depositErrorCodes'),
                      context,
                      null,
                      true
                    );
                  } else {
                    NotificationService.error(
                      '',
                      $filter('CMSLabels')(
                        data.exceptionCode,
                        'depositErrorCodes'
                      ),
                      context,
                      null,
                      true
                    );
                  }
              }
            }

            if (isRGException) {
              _handleRGLimitsExceeded(data);
            }

            _makeDepositError(
              data,
              isSightline ||
                isAch ||
                newCcFlow ||
                data.oldCardDepositFlow ||
                isSightlineV2 ||
                exceptionCode === 'OLD_CCP_DISCOVER_CARD' ||
                exceptionCode === 306
            );
          })
          .finally(function () {
            $scope.data.makingDeposit = false;
            $scope.depositDataModel.lastAmount = null;
            if ($scope.data.lastDepositStatus !== 202) {
              _setDepositTypeLimits(
                isQuickDeposit
                  ? $scope.depositDataModel.selectedOnFile.type
                  : $scope.data.selectedPayOption.ftype
              );
            }
          });
      }

      return undefined;
    }

    /**
     * Notify the user after successful deposit
     * @param  {Object} data Data returned from the server
     */

    function _makeDepositSuccess(data, isSightline, preventNotification) {
      var context = _getDepositFormFirstChildSelector();
      var cmsDescription = $filter('CMSValue')('globalDepositSuccess');
      var customerStatus = DepositSrv.getCustomerStatus();
      var isAchSelected;
      var depositType = ($scope.data.selectedPayOption || {}).ftype;
      var appsflyerEvent;
      if (_isQuickDeposit()) {
        depositType = $scope.depositDataModel.selectedOnFile
          ? $scope.depositDataModel.selectedOnFile.ftype
          : '';
      }
      isAchSelected = depositType === 'ACH' || depositType === 'IBC';
      if (customerStatus === 'First Time') {
        if (data.config.data.amount) {
          appsflyerEvent = {
            type: 'APPSFLYER_EVENT',
            payload: {
              appsflyer: {
                key: 'af_first_deposit',
                values: {
                  account_id: $rootScope.user.accountNumber,
                  af_firstdeposit_amount:
                    $filter('currency')(data.config.data.amount)
                }
              }
            }
          };
        }
        if (appsflyerEvent) {
          // RN native appsflyer event call
          if ($window && $window.handleNativeMessages) {
            $window.handleNativeMessages('FIRST_DEPOSIT', appsflyerEvent.payload);
          }
          // Send AppsFlyer event for iOS app
          if (
            $window.webkit &&
            $window.webkit.messageHandlers &&
            $window.webkit.messageHandlers.APPSFLYER_EVENT
          ) {
            $window.webkit.messageHandlers.APPSFLYER_EVENT.postMessage(appsflyerEvent);
            // Send AppsFlyer event for Android app
          } else if (
            $window.mediatorChannels &&
            $window.mediatorChannels.ios
          ) {
            $window.mediatorChannels.ios.dispatch(appsflyerEvent);
          }
        }
      }
      $scope.$emit('onDepositEventSuccess', data);
      $rootScope.$broadcast('accountBalance_update');

      if (data.hasOwnProperty('sightlineBalance')) {
        $scope.sightlineBalance = angular.isString(data.sightlineBalance)
          ? parseFloat(data.sightlineBalance)
          : data.sightlineBalance;
      } else if (data.data && data.data.hasOwnProperty('sightlineBalance')) {
        $scope.sightlineBalance = angular.isString(data.data.sightlineBalance)
          ? parseFloat(data.data.sightlineBalance)
          : data.data.sightlineBalance;
      }

      if (_isQuickDeposit()) {
        $scope.callback = function () {
          _closeQuickDepositModal();
        };
      }

      if (_showNewDepositSuccessModal() && data.status === 200) {
        DepositSrv.getSuccessDepositModal(isAchSelected);
      } else if (!isSightline && !preventNotification) {
        NotificationService.success(
          'Success!',
          '<strong>Your transaction was successful.</strong><br/>' +
          cmsDescription,
          context,
          $scope.callback,
          true
        );
      }
      _saveSuccessfulDepositOnGTM();
      _resetAllModels();
      _resetFeesInfo();

      $scope.depositDataModel.amount = null;

      return null;
    }

    /**
     * Handle errors during deposits
     * Note that there are two error codes objects handled here
     * (from microservices or api?), one with "error.code" and other
     * "error.errorCode".
     *
     * @param  {Object} error  Error occurred while making deposit
     */
    function _makeDepositError(error, preventNotification) {
      var err = error || {};
      var handlers = {
        50009: _makeDepositInvalidPinOrPasswordError,
        306: _makeDepositInvalidCreditCardError,
        500: _handleMicroServiceError,
        308: _handleBetcashExceeded,
        ResponsibleGamingLimitsExceededException: _handleRGLimitsExceeded,
        RESP_GAMING_LIMITS_EXCEEDED: _handleRGLimitsExceeded,
        SLN_InsufficientFunds: _makeSlnInsufficientFundsError,
        BridgepayException: _makeDepositInvalidCreditCardError,
        default: _makeDepositDefaultError
      };
      var errorKey = err.code || err.errorCode || ''; // make sure we read the error code
      var errorHandler;
      var errorMessageForGtm;
      var isAchOrIbc =
        $scope.depositDataModel.depositTypeId === DEPOSIT_TYPES.ACH_ON_FILE ||
        $scope.depositDataModel.depositTypeId === DEPOSIT_TYPES.ACH_NEW;

      if (_isSightlinePayment()) {
        errorKey = 'SLN_' + (err.code || '');
      }

      errorHandler = handlers[errorKey] || handlers.default;

      if (_isDepositWithNewAccount() && isAchOrIbc) {
        UserActionEventsService.emit(
          'UnsuccessfullyAddNewAccount',
          err.message
        );
      }

      errorMessageForGtm =
        $rootScope.sightlineFlowVersion === '2' ? err.code : err.message;

      _saveGTMDepositError(errorMessageForGtm);

      if (preventNotification) {
        return null; // already has notification in place
      }

      errorHandler(err);

      return null;
    }

    function _handleBetcashExceeded() {
      var message =
        'No further BetCash deposits are permitted for this period.';
      $scope.data.achDepositLimitExceeded = true;
      NotificationService.warning(
        'Error!',
        message,
        _getDepositFormFirstChildSelector()
      );
    }

    /**
     * Handle errors processed by deposits micro services returning CMS default msg for this error
     *
     * FYI: After Pedro Silva search for this response with code 500 on node and deposit micro
     * services he didn't find any reference to this error code number. Best guess it's that
     * we are no longer using this error.
     *
     * @return {String}
     */
    function _handleMicroServiceError() {
      NotificationService.error(
        'Error!',
        _defaultErrorMessage(),
        _getDepositFormFirstChildSelector()
      );
    }

    /**
     * Handle error of Responsible Gaming when limit Exceeded
     */
    function _handleRGLimitsExceeded(error) {
      var message;
      var limit;
      var context = _getDepositFormFirstChildSelector();
      var floatRegex = new RegExp(/\d*\.\d*/g);
      var CMSMessage = $filter('CMSValue')('RGLimitsExceededError');
      if (error.message && CMSMessage) {
        limit = Number(error.message.match(floatRegex)[0]).toFixed(2);
        message = CMSMessage.replace('[limit]', limit);
      } else {
        message = _defaultErrorMessage();
      }

      NotificationService.error('Error!', message, context, null, true);
      return null;
    }

    /**
     * Handle "InvalidPinOrPassword" error during deposit
     */
    function _makeDepositInvalidPinOrPasswordError() {
      $scope.data.showIBCInvalidPinOrPasswordMessage = true;
      return null;
    }

    function _oldDepositCardDeclinedFlow() {
      var context = _getDepositFormFirstChildSelector();
      var ftype1 = Utilities.prop(
        'depositDataModel.selectedOnFile.type',
        $scope
      );
      var ftype2 = Utilities.prop(
        'depositDataModel.selectedCardType.type',
        $scope
      );
      var errorMsg = '';

      if (ftype1 === 'DEB' || ftype2 === 'DEB') {
        errorMsg = $filter('CMSValue')('depositsErrorDebitCardDeclined');
      } else if (ftype1 === 'CC' || ftype2 === 'CC') {
        errorMsg = $filter('CMSValue')('depositsErrorCreditCardDeclined');
      }

      NotificationService.error('Error!', errorMsg, context, null, true);
    }

    /**
     * Handle "onDepositEventFailure" error during deposit
     */
    function _makeDepositInvalidCreditCardError(isDiscoverCard) {
      if (!_isQuickDeposit() && $rootScope.sightlineFlowVersion === '2') {
        $rootScope.showRedirectMessage = true;
        $rootScope.cardDataToReactSightline = {
          cardNumber: $scope.depositDataModel.cardNumber,
          expirationMonth: $scope.depositDataModel.expirationMonth,
          expirationYear: $scope.depositDataModel.expirationYear, // This will break in the year 3000
          amount: $scope.depositDataModel.amount,
          cvv: $scope.depositDataModel.cardSecurityNumber
        };

        if (typeof isDiscoverCard === 'boolean' && isDiscoverCard) {
          $rootScope.cardDataToReactSightline.isDiscoverCard = true;
          UserActionEventsService.emit('DiscoverCardRedirect', {
            depositAmount: $scope.depositDataModel.amount,
            amountOption: _isDefaultAmount(),
            cardType: $scope.depositDataModel.selectedCardType,
            module: _isQuickDeposit() ? 'Quick Deposit' : 'My Funds'
          });
        }

        _addQuickDepositFunds('SLN', true);
      } else {
        _oldDepositCardDeclinedFlow();
      }

      $scope.data.makingDeposit = false;
      $scope.depositDataModel.lastAmount = null;
    }

    /**
     * Handle sightline "InsufficientFundsError" error during deposit
     * @param  {Object} error  API error
     */
    function _makeSlnInsufficientFundsError(error) {
      var context = _getDepositFormFirstChildSelector();
      var errorMsg = error.message || _defaultErrorMessage();

      NotificationService.error('Error!', errorMsg, context, null, true);

      return null;
    }

    /**
     * Handle unexpected errors during deposit
     */
    function _makeDepositDefaultError() {
      var context = _getDepositFormFirstChildSelector();
      var errorMsg = _defaultErrorMessage();

      NotificationService.error('Error!', errorMsg, context, null, true);

      return null;
    }

    /**
     * Generate the default error message for deposit module
     * @return {String} Default error message
     */
    function _defaultErrorMessage() {
      return (
        "<strong>This method of payment doesn't seem " +
        'to be going through.</strong><br/>' +
        $filter('CMSValue')('depositsErrorDefault')
      );
    }

    /**
     * Check in the current scope if we're dealing with sightline
     * payment option.
     *
     * @return {Boolean}
     */
    function _isSightlinePayment() {
      return !!$scope.data.isSightlineSelected;
    }

    function _isSightlineInvalid() {
      return $scope.sightlineBalance < $scope.depositFrm.amount.$viewValue;
    }

    /**
     * Get the max deposit amount according to card type and
     * current card balance, if possible (e.g: sightline).
     * @return {Number} Max allowed deposit amount
     */
    function _getMax() {
      return !isNaN($scope.depositDataModel.max)
        ? $scope.depositDataModel.max
        : $scope.depositDataModel.max || 99999;
    }

    /**
     * Fetch fees after 1 sec of being called. If called again in less
     * than 1sec, restart timer
     *  - update fees object if success and response data matches user current
     *  amount and selected option
     * @param dataModel
     * @return {Promise} promise resolved with the deposit fee object.
     * @private
     */
    function _updateTotalCosts(dataModel, forceRetry) {
      var isSLNSelected = false;
      var amount = dataModel.amount;
      var depositLimitTypeId = dataModel.limitTypeId;
      if (!depositLimitTypeId) {
        depositLimitTypeId = DepositInitialDataFac.getDepositLimitTypeByAbbr(
          dataModel.selectedOnFile && dataModel.selectedOnFile.ftype
        ).id;
      }

      if (
        $scope.depositDataModel &&
        $scope.depositDataModel.selectedOnFile &&
        $scope.depositDataModel.selectedOnFile.ftype === 'SLN'
      ) {
        isSLNSelected = true;
      }

      // Update current amount
      $scope.depositDataModel.amount = amount;

      if (
        (!isSLNSelected &&
          $scope.depositDataModel.lastAmount === amount &&
          !forceRetry) ||
        amount > $scope.depositDataModel.max ||
        amount < $scope.depositDataModel.min
      ) {
        return $q.when({});
      }

      // stop
      if (!amount || !depositLimitTypeId) {
        _resetFeesInfo(false);
        return $q.when({});
      }

      $scope.depositDataModel.lastAmount = amount;

      $scope.data.retryFetchingFees = false;

      // Clear Fees object and show calculating fees label
      _resetFeesInfo(true);

      if (
        isSLNSelected &&
        _isQuickDeposit() &&
        dataModel.sightlineUser_v2 &&
        $rootScope.sightlineFlowVersion === '2'
      ) {
        $scope.data.fee = {
          netAmount: parseFloat(amount),
          fee: parseFloat(dataModel.sightlineUser_v2.depositFee),
          feeDiscount: 0,
          transactionTotal:
            parseFloat(amount) +
            parseFloat(dataModel.sightlineUser_v2.depositFee),
          calculatingFees: false
        };
      } else {
        return DepositSrv.getDepositFee(depositLimitTypeId, amount).then(
          function (data) {
            if (data && data.useNewFeeFlow) {
              $scope.data.fee = {
                netAmount: parseFloat(data.netAmount),
                fee: parseFloat(data.fee),
                feeDiscount: parseFloat(data.feeDiscount),
                transactionTotal: parseFloat(data.transactionTotal),
                calculatingFees: false
              };
            } else if (
              $scope.depositDataModel.amount &&
              $scope.depositDataModel.amount.toFixed(2) ===
                data.netAmount.toFixed(2)
            ) {
              $scope.data.fee = {
                netAmount: parseFloat(data.netAmount),
                fee: parseFloat(data.fee),
                feeDiscount: parseFloat(data.feeDiscount),
                transactionTotal: parseFloat(data.transactionTotal),
                calculatingFees: false
              };
            } else {
              // Clear Fees object and hide calculating fees label
              _resetFeesInfo(false);
            }
          },
          function () {
            // Clear Fees object and hide calculating fees label
            _resetFeesInfo(false);
            $scope.data.retryFetchingFees = true;
          }
        );
      }
    }

    /**
     * Clear Fees object and show/hide calculating fees label
     * @private
     */
    function _resetFeesInfo(isCalculatingFee) {
      $scope.data.fee = {
        calculatingFees: isCalculatingFee
      };
    }

    /**
     * Handles routing number changed event
     * (only fires when valid routing number)
     * Updates bank name labels for customer feedback
     * @param routingNumber
     * @private
     */
    function _routingNumberOnChange(routingNumber) {
      var currentTimestamp;

      // stop
      if (!routingNumber) {
        return;
      }

      currentTimestamp = toggleTimestamp;
      $scope.data.bankNameMessage = bankNameInfoMessages.FETCHING;
      $scope.data.bankNameDisabled = true;
      $scope.depositDataModel.bankName = null;
      $scope.data.errorBankName = false;

      DepositSrv.getBankName(routingNumber)
        .then(function (data) {
          // Only updates if is still the same routing number and
          // cancel message updates if tab has changed
          if (
            $scope.depositDataModel.routingNumber === data.routingNumber &&
            currentTimestamp === toggleTimestamp
          ) {
            $scope.depositDataModel.bankName = data.bankName;
            $scope.data.bankNameDisabled = false;
          }

          $scope.data.bankNameMessage = null;
        })
        .catch(function () {
          $scope.data.bankNameDisabled = false;

          if (currentTimestamp === toggleTimestamp) {
            $scope.data.bankNameMessage = bankNameInfoMessages.ERROR;
            $scope.data.errorBankName = true;
          } else {
            $scope.data.bankNameMessage = bankNameInfoMessages.DEFAULT;
          }
        });
    }

    /**
     * Save the payment card/method information
     * @param {Object} method  Payment card/method
     */
    function _setPaymentData(method) {
      var firstTime = DepositSrv.getHasMadeInitialDeposit();
      var min =
        method.min || DepositInitialDataFac.getLimitType(method.ftype, 'min');
      var max =
        method.max || DepositInitialDataFac.getLimitType(method.ftype, 'max');
      method = method || {};
      $scope.depositDataModel.selectedCardType = method;
      //eslint-disable-next-line
      $scope.depositDataModel.min = firstTime
        ? 0.1
        : !isNaN(parseFloat(min))
        ? parseFloat(min)
        : 0;
      $scope.depositDataModel.max = !isNaN(parseFloat(max))
        ? parseFloat(max)
        : 99999;
      $scope.depositDataModel.limitTypeId =
        method.limitTypeId ||
        DepositInitialDataFac.getLimitType(method.ftype, 'id');
      $scope.depositDataModel.depositTypeId = method.depositTypeId;

      return null;
    }

    /**
     * Update min and max values based on each payment method specific values
     * Update total costs
     * @param card
     * @private
     */
    function _subTypeCardChanged(card) {
      _resetNotification();
      _setPaymentData(card);
      _setDepositTypeLimits(card.ftype, card.type);

      // Fetch fees for selected card sub type and current amount
      _updateTotalCosts($scope.depositDataModel);
    }

    /**
     * Update the deposit type information saved in model, accordig to
     * the selected card.
     *
     * @param  {Object} depositInfo  Deposit type info
     */
    function _updateSelectedDepositTypeInfo(depositInfo) {
      if (depositInfo) {
        _setPaymentData(depositInfo);
        $scope.depositDataModel.isPending = depositInfo.isPending;
        $scope.depositDataModel.isAvailable = depositInfo.isAvailable;
        $scope.data.isSightlineSelected = depositInfo.ftype === 'SLN';

        $scope.data.showAchDepositLimitExceeded =
          depositInfo.max === 0 &&
          depositInfo.type === 'ACH' &&
          $scope.data.achDepositLimitExceeded;

        _setDepositTypeLimits(depositInfo.type || depositInfo.ftype);

        if (depositInfo.depositTypeId && $scope.depositDataModel.amount) {
          DepositSrv.getDepositFee(
            depositInfo.depositTypeId,
            $scope.depositDataModel.amount
          ).then(
            function (data) {
              if (data && data.useNewFeeFlow) {
                $scope.data.fee = {
                  netAmount: parseFloat(data.netAmount),
                  fee: parseFloat(data.fee),
                  feeDiscount: parseFloat(data.feeDiscount),
                  transactionTotal: parseFloat(data.transactionTotal),
                  calculatingFees: false
                };
              } else if (
                $scope.depositDataModel.amount &&
                $scope.depositDataModel.amount.toFixed(2) ===
                  data.netAmount.toFixed(2)
              ) {
                $scope.data.fee = {
                  netAmount: parseFloat(data.netAmount),
                  fee: parseFloat(data.fee),
                  feeDiscount: parseFloat(data.feeDiscount),
                  transactionTotal: parseFloat(data.transactionTotal),
                  calculatingFees: false
                };
              } else {
                // Clear Fees object and hide calculating fees label
                _resetFeesInfo(false);
              }
            },
            function () {
              // Clear Fees object and hide calculating fees label
              _resetFeesInfo(false);
              $scope.data.retryFetchingFees = true;
            }
          );
        }
      }
    }

    /**
     * Handle changes to the selected payment option
     * @param  {Object} card  Selected card
     * @public
     */
    function _selectOnFileChanged(card) {
      if (card) {
        _resetNotification();
        _updateSelectedDepositTypeInfo(card);
      }

      // Fetch fees for selected card sub type and current amount
      _updateTotalCosts($scope.depositDataModel);
      _updateDefaultPayment($scope.depositDataModel);
    }

    function _toggleNewStoredMethods(method) {
      var selectedPayOption = $scope.data.selectedPayOption;
      var currentAmount = $scope.depositDataModel.amount;
      var onFile = selectedPayOption.onFile || [];
      var subTypes = selectedPayOption.subTypes || [];
      var selCardType;

      _resetNotification();

      if ($scope.data.selectedPayOption.ftype === 'CC') {
        UserActionEventsService.emit('ChangeCreditMethod', method);
      }
      if ($scope.data.selectedPayOption.ftype === 'IBC') {
        if (method === 'NEW') {
          UserActionEventsService.emit('AddNewAccountClick');
        } else {
          UserActionEventsService.emit('AccountsOnFileClick');
        }
      }

      toggleTimestamp = new Date().getTime();
      $scope.data.bankNameMessage = bankNameInfoMessages.DEFAULT;

      $scope.depositDataModel = {
        limitTypeId: selectedPayOption.limitTypeId,
        depositTypeId: selectedPayOption.depositTypeId,
        amount: currentAmount,
        min: parseFloat(selectedPayOption.min),
        max: parseFloat(selectedPayOption.max),
        isAvailable: null,
        isPending: null,
        toSaveOnFile: true
      };

      $scope.data.depositSection = method;

      if (method === 'STORED' && onFile.length) {
        _resetDepositActionModel();
      } else {
        $scope.depositDataModel.selectedOnFile = null;
        $scope.depositDataModel.isAvailable = selectedPayOption.isAvailable;

        if (subTypes.length) {
          selCardType = subTypes[0];
          _setPaymentData(selCardType);
        }
      }
      _setDepositTypeLimits(
        selectedPayOption.ftype,
        selCardType && selCardType.type
      );
      _updateTotalCosts($scope.depositDataModel);
      if (method === 'STORED') {
        _setUserBankAccounts();
        _setUserCardsOnFile();
      }
    }

    function _resetDepositActionModel() {
      $scope.depositDataModel.selectedOnFile = null;
      $scope.depositDataModel.limitTypeId = null;
      $scope.depositDataModel.depositTypeId = null;
      $scope.depositDataModel.min = 0;
      $scope.depositDataModel.max = 99999;
      $scope.depositDataModel.isPending = null;
    }

    function _existSelectedOnFile() {
      return (
        $scope.data.selectedPayOption &&
        _existsOnFile($scope.data.selectedPayOption.onFile)
      );
    }

    function _existsOnFile(onFile) {
      return (onFile || []).some(function (file) {
        return file.isPending === false;
      });
    }

    /**
     * Get sightline user from API
     *
     * 1) get user from TVG deposit
     * 2) check if user has sightline account
     * 3) get full sightline details for the user
     *
     * (previous _handleSightLine() cont.)
     *
     * @param  {Object} depositUser
     * @return {Promise}
     */
    function _getSightlineUser(depositUser) {
      var basicSightlineUsr = SightlineSrv.createSightlineAccount(depositUser);
      $scope.depositDataModel.sightlineNoBalance = false;

      $scope.basicSightlineUsr = basicSightlineUsr;
      if (
        $rootScope.sightlineFlowVersion &&
        $rootScope.sightlineFlowVersion === '1'
      ) {
        return _getSightlineUserWithFallback(basicSightlineUsr)
          .then(function (data) {
            // mark users without sightline and update balance
            $scope.isNewUser = !data.enrolled;
            $scope.sightlineBalance = data.balance || 0;

            $scope.depositDataModel.max = $scope.sightlineBalance;
            if ($scope.sightlineBalance === 0) {
              $scope.depositDataModel.maxOverflow = true;
              $scope.depositDataModel.sightlineNoBalance = true;
            }

            // needed to make deposit...
            DepositSrv.user.set('last4SSN', '0000');

            return data;
          })
          .then(function (data) {
            // @TODO check if we should always get full merchant data
            return $scope.isAddingFunds || !data.exists
              ? _getMerchantData(depositUser)
              : depositUser;
          });
      }
      return null;
    }

    /**
     * To comply with returning 404 when the user does not exist,
     * we need to catch 404 and treat it as a success (like the backend used to do).
     *
     * @param {Object} basicSightlineUsr
     * @return {Promise} User data request
     */
    function _getSightlineUserWithFallback(basicSightlineUsr) {
      return SightlineSrv.isSightlineUser(basicSightlineUsr).catch(function (
        err
      ) {
        var error = err || {};
        var errorCode = error.data ? error.data.code : error.code;

        // handle "NO_SIGHTLINE_ACCOUNT_FOUND" known errors as success
        // (to be compliant with previous api)
        if (errorCode === ERRORS.NO_SIGHTLINE_ACCOUNT_FOUND) {
          return {
            exists: false,
            balance: 0
          };
        }

        return $q.reject(err);
      });
    }

    /**
     * Get sightline user data using the TVG account.
     * Sightline enrollment, deposits and withdrawals are done using
     * sightline API.
     *
     * (previous _getSightlineUser())
     *
     * @param  {Object}  depositUser  TVG user data
     * @return {Promise}              Get sightline from API promise
     */
    function _getMerchantData(depositUser) {
      return SightlineSrv.getToken(depositUser, 'Deposit').then(
        _loadSightlineIframe
      );
    }

    /**
     * Load sightline if any process is forcing the iframe loading
     * (e.g. adding funds).
     *
     * (previous _getSightlineUserData())
     *
     * @param  {Object} data  TVG user data
     */
    function _loadSightlineIframe(data) {
      var forced = $scope.isAddingFunds;

      if (
        forced &&
        $scope.sightlineFlowVersion &&
        $scope.sightlineFlowVersion === '1'
      ) {
        // @TODO please remove when db bug of saving postal codes
        // with extra 4 0000 is fixed
        data.postalCode = data.postalCode.substring(0, 5);
        $scope.sglUser = data;

        $timeout(function () {
          document.getElementById("sightline__user-form").submit(); // eslint-disable-line
          $scope.loadSightlineInfo = true;
          $scope.data.loading = false;
          $scope.loadSightlineiFrame = true;
        }, 300);
      }

      return data;
    }

    /**
     * Select a deposit payment options (tab)
     *
     * @param {Object} opt                              An option present in the depositOptions array.
     * @param {Boolean} [doNotSendGTMClickEvent=false]  True to avoid sending a "Site Click" GTM event.
     * @private
     */
    function _selectOption(opt, doNotSendGTMClickEvent, force) {
      var types;
      // to avoid resetDataModel if the tab doesn't change
      if ($scope.data.selectedPayOption !== opt || force) {
        $scope.data.selectedPayOption = opt;
        _resetDepositDataModel();
        _resetNotification();

        if (!doNotSendGTMClickEvent) {
          _selectOptionGtmEvents(opt.name);
        }

        types = {
          BC: null,
          CC: null,
          ACH: null,
          IBC: null,
          OTHER: null,
          PNM: null,
          APPL: null,
          SLN: _selectOptionSightline,
          PAY: null
        };

        $scope.data.isSightlineSelected = opt.ftype === 'SLN';

        // clear is adding funds flag when moving to other tabs
        if (!$scope.data.isSightlineSelected) {
          $scope.isAddingFunds = false;
        }

        if (types[opt.ftype]) {
          return types[opt.ftype]();
        }
      }
      return undefined;
    }

    /**
     * DO NOT CALL THIS DIRECTLY!
     * (use _selectOption(sightline) instead...)
     *
     * Initialize the sightline as deposit method when opening
     * "TVG Pre Paid Card" in deposits page.
     * (previous _handleSightLine())
     *
     * @return {Promise}
     */
    function _selectOptionSightline() {
      var depositUser = DepositSrv.user;
      if (
        $rootScope.sightlineFlowVersion &&
        $rootScope.sightlineFlowVersion === '1'
      ) {
        _startSightlineLoaders();
        return _getSightlineUser(depositUser)
          .catch(_selectOptionSightlineError)
          .finally(function () {
            $scope.data.loading = false;
            _stopSightlineLoaders();
          });
      }
    }

    /**
     * Handle errors while selecting sightline as the deposit method in
     * deposit page.
     * @param  {Object} error  API error
     */
    function _selectOptionSightlineError(error) {
      var errorMessage = error.message || _defaultErrorMessage();
      var target = _getDepositFormFirstChildSelector();

      return NotificationService.error('Error!', errorMessage, target);
    }

    /**
     * Reset deposit data model and set selected option and current amount;
     * Update total costs
     * @private
     */
    function _resetDepositDataModel() {
      var selectedPayOption = $scope.data.selectedPayOption;
      var currentAmount = $scope.depositDataModel.amount;
      var makeTransfer = !!(
        $scope.fromOption &&
        ($scope.fromOption.tla === 'registration' ||
          $scope.fromOption === 'registration') &&
        ConfigurationFac.getApplicationContextItem('product') === 'njx'
      );
      var selectCardType;

      _resetAllModels();

      if (selectedPayOption) {
        $scope.depositDataModel = {
          limitTypeId: selectedPayOption.limitTypeId,
          depositTypeId: selectedPayOption.depositTypeId,
          amount: currentAmount,
          min: parseFloat(selectedPayOption.min),
          max: parseFloat(selectedPayOption.max),
          isAvailable: selectedPayOption.isAvailable,
          toSaveOnFile: true,
          makeTransfer: makeTransfer
        };
      }

      if (selectedPayOption) {
        if (selectedPayOption.subTypes && selectedPayOption.subTypes.length) {
          selectCardType = selectedPayOption.subTypes[0];
          _setPaymentData(selectCardType);
        }

        // @HACK
        // to render sightline in quick deposit, we simulated a onFile entry...
        if (
          selectedPayOption.ftype !== 'SLN' &&
          selectedPayOption.onFile &&
          selectedPayOption.onFile.length &&
          !$rootScope.dmaShowAddNewCardForm
        ) {
          $scope.data.depositSection = 'STORED';
          _resetDepositActionModel();
        } else {
          $scope.data.depositSection = 'NEW';
          $rootScope.dmaShowAddNewCardForm = false;
        }

        if (
          (selectedPayOption.ftype === 'ACH' ||
            selectedPayOption.ftype === 'IBC') &&
          !$scope.data.achDepositLimitExceeded
        ) {
          _setUserBankAccounts();
        }

        if (selectedPayOption.ftype === 'CC') {
          _setUserCardsOnFile();
        }
      }

      if (
        $scope.fromOption &&
        ($scope.fromOption.tla === 'quick_deposit' ||
          $scope.fromOption === 'quick_deposit')
      ) {
        $scope.data.depositSection = 'NEW';
      }

      // Fetch fees for selected payment method and current amount
      _updateTotalCosts($scope.depositDataModel);

      $scope.$emit('selectedPayOption', {
        depositType: _getCurrentDepositTypeString()
      });

      return undefined;
    }

    /**
     * Clear the notifcation service banner
     * (used when switching tabs in deposit)
     * @private
     */
    function _resetNotification() {
      NotificationService.clearBanner();
    }

    /**
     * Get the selected deposit "name"
     * @return {String} Current deposit type name
     */
    function _getCurrentDepositTypeString() {
      var depositType = ($scope.data.selectedPayOption || {}).ftype;
      var types = {
        IBC: 'BetCash',
        ACH: 'BetCash',
        CC: 'Card',
        MPAK: 'MoneyPak',
        SLN: 'Sightline',
        PNM: 'PayNearMe',
        APPL: 'Apple Pay',
        PAY: 'PayPal',
        OTHER: 'OtherPaymentMethod'
      };

      if (_isQuickDeposit()) {
        depositType = $scope.depositDataModel.selectedOnFile
          ? $scope.depositDataModel.selectedOnFile.ftype
          : '';
      }

      return types[depositType] || 'Unknown';
    }

    /**
     * Handle "TVG default deposit amount" button click by updating the
     * selected amount in model, updating fees from server and notifying GTM.
     *
     * (was _availableAmountOptionClicked())
     *
     * @param  {String} amount  Updated amount from view
     */
    function _handleDefaultAmountButtonClick(amount) {
      // set the value in model
      $scope.depositDataModel.amount = parseInt(amount, 10);

      _updateDepositFeesAndSendGTM({
        isDefaultValue: true,
        silent: false
      });
    }

    /**
     * Handle "deposit amount" input change by updating the
     * selected amount in model and updating fees from server.
     */
    function _handleAmountInputChange() {
      _updateDepositFeesAndSendGTM({
        isDefaultValue: false,
        silent: true // do not send gtm events!
      });
    }

    /**
     * Handle "deposit amount" input blur by updating the
     * selected amount in model, updating fees from server and notifying GTM.
     *
     * (was _otherAmountBlur())
     *
     * @return {Promise}
     */
    function _handleAmountInputBlur() {
      // must be async because the blur triggers before change events
      $timeout(function () {
        _updateDepositFeesAndSendGTM({
          isDefaultValue: false,
          silent: false
        });
      }, 10);
    }

    /**
     * Update the selected amount in model and fees from server.
     * By default, we may notify this change using GTM, but may be silenced
     * using silentGTM as true.
     *
     * @param {Object}  [opts]                 Update options
     * @param {Boolean} [opts.isDefaultValue]  Is the value a default one from TVG?
     * @param {Boolean} [opts.silent]          Prevent sending events through GTM
     * @return {Promise}
     */
    function _updateDepositFeesAndSendGTM(opts) {
      opts = opts || {};

      // stop if no amount is inserted
      // (amount is undefined if the value is not valid)
      if (
        !$scope.depositDataModel ||
        !$scope.depositDataModel.amount ||
        $scope.depositDataModel.amount > $scope.depositDataModel.max
      ) {
        $scope.data.shouldDisableApplePayButton = true;
        return $q.reject('Invalid deposit amount');
      }

      if (
        $scope.depositDataModel &&
        $scope.depositDataModel.selectedOnFile &&
        $scope.depositDataModel.selectedOnFile.ftype === 'SLN'
      ) {
        _updateTotalCosts($scope.depositDataModel);
        if (!opts.silent) {
          _sendGTMAmountChanged();
        }
        return null;
      }

      if ($scope.data.shouldDisableApplePayButton) {
        $scope.data.shouldDisableApplePayButton = false;
      }

      // update fees and notify via GTM
      return _updateTotalCosts($scope.depositDataModel).then(function () {
        if (!opts.silent) {
          _sendGTMAmountChanged();
        }
        return null;
      });
    }

    /**
     * Notify GTM when a "default deposit amount" button was clicked
     * (must only be triggered after fees recalculation)
     */
    function _sendGTMAmountChanged() {
      var eventData = {
        gaEventLabel:
          _isDefaultAmount() === 'Yes' ? 'Default Amount' : 'Other Amount',
        depositAmount: $scope.depositDataModel.amount,
        depositFee: $scope.data.fee.fee,
        depositType: _getCurrentDepositTypeString(),
        cardType: _getUsedCardType()
      };

      return _isQuickDeposit()
        ? UserActionEventsService.emit('QuickDepositStart', eventData)
        : UserActionEventsService.emit('StandardDepositStart', eventData);
    }

    /**
     * Handle "This is your TVG Quick Deposit default?" value change
     * @param  {Boolean} isDefaultPayment
     * @public
     */
    function _defaultPaymentChanged(isDefaultPayment) {
      var selectedPayment = $scope.depositDataModel.selectedOnFile;
      var defaultPaymentCard;
      var eventData = {
        depositType: _getCurrentDepositTypeString(),
        gaEventLabel: isDefaultPayment,
        amountType: _isDefaultAmount()
      };
      UserActionEventsService.emit('selectDefaultAmount', eventData);
      if (isDefaultPayment) {
        defaultPaymentCard = {
          type_id: selectedPayment.depositTypeId,
          id: _getIdFromPaymentOption(selectedPayment)
        };

        DepositSrv.setUserPaymentDefault(defaultPaymentCard).then(function (
          result
        ) {
          if (result) {
            $scope.data.defaultPaymentCard = defaultPaymentCard;
            $scope.depositDataModel.isDefaultPayment = true;
            Utilities.attempt(function () {
              $window.localStorage.setItem(
                'defaultPaymentMethod',
                angular.toJson(defaultPaymentCard)
              );
            });
          } else {
            $scope.depositDataModel.isDefaultPayment = false;
          }
        });
      } else {
        DepositSrv.setUserPaymentDefault(null).then(function (result) {
          if (result) {
            $scope.depositDataModel.isDefaultPayment = false;
            $scope.data.defaultPaymentCard = false;
            Utilities.attempt(function () {
              $window.localStorage.removeItem('defaultPaymentMethod');
            });
          } else {
            $scope.depositDataModel.isDefaultPayment = true;
          }
        });
      }
    }

    /**
     * Check if the current selected payment in dataModel is the default one
     * @param  {Object}  dataModel  View's data model
     * @return {Boolean}            Whether is default
     */
    function _updateDefaultPayment(dataModel) {
      var defaultCard = {};
      var defaultCardId;
      var selectedCardId;
      var isDefaultPayment;

      Utilities.attempt(function () {
        defaultCard = angular.fromJson(
          $window.localStorage.getItem('defaultPaymentMethod')
        );
        defaultCardId = (defaultCard || {}).id;
      });

      if (dataModel.selectedOnFile) {
        selectedCardId = _getIdFromPaymentOption(dataModel.selectedOnFile);
      }
      isDefaultPayment = defaultCardId && selectedCardId === defaultCardId;

      // must cast to boolean!
      dataModel.isDefaultPayment = !!isDefaultPayment;

      return null;
    }

    /**
     * Revert all form fields to a pristine, untouched state.
     */
    function _resetAllModels() {
      if ($scope.depositFrm) {
        angular.forEach($scope.depositFrm, function (value, key) {
          if (!key.match(/\$/)) {
            value.$setUntouched();
            value.$setPristine();
          }
        });
        $scope.depositFrm.$setUntouched();
        $scope.depositFrm.$setPristine();
      }
    }

    /**
     * Open terms modal window
     * @private
     */
    function _openTerms() {
      UserActionEventsService.emit('TermsAndConditionsClick');
      return ModalDialogService.open(
        $filter('CMSValue')('depositBetCashUserAgreementTitle'),
        $filter('CMSValue')('depositBetCashUserAgreementHTML')
      );
    }

    /**
     * Close the quick deposit window
     * @private
     */
    function _closeQuickDepositModal() {
      $scope.$emit('onCloseSuccessWindow');
      return;
    }

    //
    // ADD FUNDS
    //

    /**
     * Load sightline funds iframe
     * @return {Object}
     */
    function _addSightlineFunds() {
      // @TODO should we fetch user information if already loaded?
      _startSightlineLoaders();
      _resetNotification();

      // add funds does not exist with sightline API,
      // so it must always be processed with iframe
      $scope.isAddingFunds = true;
      _addFundsGtmEvent();
      _getSightlineUser(DepositSrv.user)
        .catch(_loadSightlineAddFundsIframeError)
        .finally(function () {
          $scope.data.loading = false;
          _stopSightlineLoaders();
        });

      return;
    }

    /**
     * Show a notification.error when the user tries to add funds from betslip
     * explaining how the user may proceed to add funds manually
     */
    function _showAddFundsInBetslipWarning(ftype) {
      var options = {
        PAY: 'PayPal',
        SLN: 'TVG Pre Paid Card'
      };
      var message = $filter('CMSValue')('addFundsInBetslipWarning');
      var target = _getDepositFormFirstChildSelector();
      return NotificationService.error(
        'Error!',
        Utilities.supplant(message, {
          method: options[ftype]
        }),
        target
      );
    }

    /**
     * Redirect to sightline/paypal deposits from quick deposit window
     * (because of angular router and the routing scheme from touch and
     * desktop being different, we use several methods to redirect users to
     * sightline/paypal ----> @HACK xD)
     *
     * 1) is in deposit? -> emit a global event to swith tabs
     *                      (from quick-deposit to deposit ctrl instance)
     * 2) is not touch?  -> use url redirects
     * 3) otherwise?     -> emit a global event to be handled by wrapper app
     *
     * @private
     */
    function _addQuickDepositFunds(ftype, newSightline) {
      var options = {
        PAY: 'Paypal',
        APPL: 'Apple Pay',
        SLN: 'Sightline'
      };
      UserActionEventsService.emit('navigatedTo', {
        url:
          'http://tvg.com/my-funds/deposit?activeTab=' +
          options[ftype].toLowerCase() +
          '+Deposit',
        name: options[ftype]
      });
      if (ftype) {
        // if is betslip,
        // show a warning explaining how to add funds in sightline
        if (_isBetSlip()) {
          _showAddFundsInBetslipWarning(ftype);
        } else {
          if (ftype === 'SLN' && !newSightline) {
            // set the redirecting flag through the SightlineSrv (like it was a
            // global variable), to be used when opening the deposit
            // screen after redirecting
            SightlineSrv.isRedirectingToSightlineAddFunds(true);
          }

          // when inside deposit routes,
          // emit a global event to be handled by depositCtrl
          // (full deposit instance)
          if (isDepositSubRoute()) {
            _closeQuickDepositModal();
            $rootScope.$emit('redirectFrom' + options[ftype] + 'UsingTabs');

            // in all environments except touch,
            // use url redirects handled by angular router
          } else if (useUrlRedirects()) {
            _closeQuickDepositModal();
            if (ftype === 'PAY') {
              _selectOption(PaypalDepositConfig, false);
            } else {
              _selectOption(SightlineDepositConfig, false);
            }

            // in mobile,
            // emit a global event to be handled by tvg4 wrapper app, that will open
            // the deposit tab from the sidebar and focus on sightline's add funds
          } else {
            // emit a global event to be handled by tvg-touch-angular project
            // this will open the deposit tab from the sidebar and focus on the method
            // add funds option
            // $rootScope.$broadcast('redirectFrom' + options[ftype], 'Deposit'); - this is not correct as it will open a modal
            $rootScope.$emit('redirectFrom' + options[ftype] + 'UsingTabs');
          }

          return;
        }
      }
    }

    /**
     * Is the user inside a deposit subroute?
     * @return {Boolean}
     */
    function isDepositSubRoute() {
      return $location.path().indexOf('my-funds/deposit') > -1;
    }

    /**
     * Can we use url to redirect users throghout the app?
     * This is true for evrything but the touch environment
     * (e.g. DMA standalone and desktop environments)
     *
     * @return {Boolean}
     */
    function useUrlRedirects() {
      return $rootScope.productContext !== 'touch2';
    }

    /**
     * Handle errors while loading sightline information to be used as
     * quick deposit option.
     * @param  {Object} error  API error
     */
    function _loadSightlineAddFundsIframeError(error) {
      var errorMessage = error.message;
      var target = _getDepositFormFirstChildSelector();
      var description;

      if (!errorMessage) {
        description = $filter('CMSValue')('depositsErrorDefault');
        errorMessage =
          '<strong>' +
          "Sightline's method of payment doesn't seem to be going" +
          ' through.</strong><br/>' +
          description;
      }

      return NotificationService.error('Error!', errorMessage, target);
    }

    function _onlyNumbers(evt) {
      var charCode = evt.which || evt.keyCode;
      if (charCode > 31 && (charCode < 48 || charCode > 57)) {
        evt.preventDefault();
      }
    }

    function _FieldFilled(field, module) {
      if (!field.$error) {
        UserActionEventsService.emit('FieldFill', {
          field: field,
          module: module
        });
      } else {
        $timeout(function () {
          UserActionEventsService.emit('FieldFillError', {
            field: field,
            module: module
          });
        }, 200);
      }
    }

    function _selectAccount(card) {
      if (card.ftype === 'APPL') {
        ApiDepositsGTMFac.sendGTMEvent('siteClick', {
          event: 'deposit',
          gaEventCategory: 'Deposit',
          gaEventAction: 'Selected Account',
          gaEventLabel: 'Apple Pay',
          depositType: 'Apple Pay',
          module: 'Quick Deposit',
          depositAmount: $scope.depositDataModel.amount
        });
      }

      UserActionEventsService.emit('selectAccount', {
        type: card.cardType || card.bankName.trim() || card.type,
        ftype: card.ftype
      });
    }

    function _clickTooltip() {
      UserActionEventsService.emit('CreditTooltip');
    }

    function _changeCard(selected) {
      UserActionEventsService.emit('CreditChangeCard', selected);
      _resetNotification();
      _setPaymentData(selected);
      _setDepositTypeLimits(selected.type);
    }

    //
    // GTM
    //

    /**
     * Get the currently selected payment's name/identification to be
     * used in GTM
     * @return {String} Payment name
     */
    //eslint-disable-next-line
    function _getCurrentPaymentName() {
      var paymentName;
      if (_isQuickDeposit()) {
        paymentName = $scope.depositDataModel.selectedOnFile
          ? $scope.depositDataModel.selectedOnFile.typeName
          : '';
      } else {
        paymentName = $scope.depositDataModel.selectedCardType
          ? $scope.depositDataModel.selectedCardType.typeName
          : $scope.depositDataModel.depositTypeId;
      }
      return paymentName;
    }

    function _saveSuccessfulDepositOnGTM() {
      var isAchOrIbc =
        $scope.depositDataModel.depositTypeId === DEPOSIT_TYPES.ACH_ON_FILE ||
        $scope.depositDataModel.depositTypeId === DEPOSIT_TYPES.ACH_NEW;

      UserActionEventsService.emit('depositSuccess', {
        depositType: _getCurrentDepositTypeString(),
        depositAmount: $scope.depositDataModel.amount,
        amountOption: _isDefaultAmount(),
        module: _isQuickDeposit() ? 'Quick Deposit' : 'My Funds',
        isFeePaid: parseFloat($scope.data.fee.fee) > 0
      });

      if (_isDepositWithNewAccount() && isAchOrIbc) {
        UserActionEventsService.emit('SuccessfullyAddNewAccount');
      }
    }

    function _saveGTMDepositError(errorMessage) {
      var isAchOrIbc =
        $scope.depositDataModel.depositTypeId === DEPOSIT_TYPES.ACH_ON_FILE ||
        $scope.depositDataModel.depositTypeId === DEPOSIT_TYPES.ACH_NEW;

      UserActionEventsService.emit('depositError', {
        errorMessage: errorMessage || 'Generic Error',
        depositType: _getCurrentDepositTypeString(),
        depositAmount:
          $scope.depositDataModel.amount ||
          Utilities.prop('depositFrm.amount.$viewValue', $scope),
        amountOption: _isDefaultAmount(),
        module: _isQuickDeposit() ? 'Quick Deposit' : 'My Funds'
      });

      if (_isDepositWithNewAccount() && isAchOrIbc) {
        UserActionEventsService.emit('SuccessfullyAddNewAccount');
      }
    }

    function _addFundsGtmEvent() {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        eventLabel: 'MyFunds-SightlineAddFunds',
        gaEventCategory: 'Site Click',
        gaEventAction: 'My Funds Page Click',
        gaEventLabel: 'MyFunds | Sightline Add Funds',
        productVersion: productVersion,
        screenName: ApiDepositsGTMFac.tvg4ScreenName(),
        sectionName: ApiDepositsGTMFac.tvg4SectionName(),
        siteVersion: siteVersion,
        accountId: DepositSrv.user.get('accountNumber')
      });
    }

    function _closeSuccessfulRegistrationModal() {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        event: 'siteClick',
        gaEventCategory: 'Site click',
        gaEventAction: 'Close',
        gaEventLabel: 'Deposit After Registration',
        module: 'Registration',
        siteVersion: siteVersion,
        productVersion: productVersion
      });
    }

    function _selectOptionGtmEvents(tabName) {
      var ga = $window.ga || Utilities.noop;

      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        eventLabel: 'My Funds-Deposits' + tabName,
        gaEventCategory: 'Site Click',
        gaEventAction: 'My Funds Page Click',
        gaEventLabel: 'My Funds | Deposits | ' + tabName,
        screenName: ApiDepositsGTMFac.tvg4ScreenName(),
        sectionName: ApiDepositsGTMFac.tvg4SectionName(),
        productVersion: productVersion,
        siteVersion: siteVersion,
        accountId: DepositSrv.user.get('accountNumber'),
        navigationPosition: $rootScope.showLeftBar ? 'Left Nav' : 'Top Nav',
        residenceState: $rootScope.user
          ? $rootScope.user.homeAddress.StateAbbr
          : ''
      });

      ga('send', 'pageview', { title: 'Deposit| ' + tabName });
    }

    function _anyCardsExpired() {
      var disabled = false;
      var selectedCard = $scope.depositDataModel.selectedOnFile || {};
      var stored =
        $scope.data.depositSection === 'STORED' && !_isQuickDeposit();
      var creditCard = selectedCard.ftype === 'CC';
      var sightlineCardSelected = selectedCard.ftype === 'SLN';

      if (
        (_isQuickDeposit() || stored) &&
        (creditCard || sightlineCardSelected)
      ) {
        if (selectedCard.isExpired) {
          disabled = true;
        }
      }
      return disabled;
    }

    /**
     * Check if is declined card
     * @param {Object} card               Card Object
     */
    function _isSLNDeclinedCard(card) {
      var SLPDeclinedCardToggle = $rootScope.activeFeatures &&
        $rootScope.activeFeatures.showCardDeclinedModal;
      return SLPDeclinedCardToggle && card && card.network === 'VISA' && card.ftype === 'SLN';
    }

    /**
     * Check if is all declined cards in scope
     */
    function _allCardsDeclined() {
      var depositOptions = $scope.data.depositOptions ? $scope.data.depositOptions : [];
      var SLPDeclinedCardToggle = $rootScope.activeFeatures &&
        $rootScope.activeFeatures.showCardDeclinedModal;
      var isAllDeclined = SLPDeclinedCardToggle && depositOptions.length > 0 &&
        depositOptions.findIndex(function (card) {
          return (_isApplePayInQuickDepositEnabled() || card.ftype !== 'APPL') &&
           !_isSLNDeclinedCard(card);
        }) === -1;
      $scope.data.disabledCard = $scope.data.disabledCard || isAllDeclined;
      return isAllDeclined;
    }

    /* GTM triggers */

    function _registerAccountSelectionOnGTM(bankName) {
      _updateTotalCosts($scope.depositDataModel, true);
      UserActionEventsService.emit('SelectedAuthorizedAccount', bankName);
    }

    function _depositAttemptGtm() {
      UserActionEventsService.emit('attemptedDepositQuick', {
        amountOption: _isDefaultAmount(),
        cardType: $scope.depositDataModel.selectedOnFile.cardType,
        depositAmount: $scope.depositDataModel.amount,
        netDepositFee: $scope.depositDataModel.fee,
        depositType: $scope.depositDataModel.selectedOnFile.type
      });
    }

    function _sendOtherAmountErrorToGTM(errorText, data) {
      var ftype = _isQuickDeposit()
        ? 'Quick'
        : $scope.data.selectedPayOption.ftype;
      if (data) {
        errorText =
          errorText + ' ' + $filter('currency')($scope.depositDataModel[data]);
      }
      UserActionEventsService.emit(
        'AttemptToCompleteOtherAmount' + ftype,
        errorText
      );
    }

    function _completedFieldAndBlursAway(fieldName, field) {
      $timeout(function () {
        if (field.$valid) {
          UserActionEventsService.emit('CompletedFieldAndBlursAway', fieldName);
        }
      });
    }

    function _newAccountFieldError(fieldName, errorMsg) {
      UserActionEventsService.emit('NewAccountFormFieldError', {
        fieldName: fieldName,
        errorText: errorMsg
      });
    }

    //
    // VISUAL FLAGS
    //

    /**
     * Is "toggle-new-onfile" section visible for non IBC deposits?
     * @return {Boolean}
     */
    function _isNewOnFileVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var isAvailable = $scope.depositDataModel.isAvailable !== false;
      var existsOnFile = $scope.events.existsOnFile();
      var isIBC = selectedPayOption.ftype === 'IBC';

      return (isAvailable || existsOnFile) && !isIBC;
    }

    /**
     * Is "toggle-new-onfile" section visible for IBC deposits?
     * @return {Boolean}
     */
    function _isIBCNewOnFileVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var isAvailable = $scope.depositDataModel.isAvailable !== false;
      var existsOnFile = $scope.events.existsOnFile();
      var isIBC = selectedPayOption.ftype === 'IBC';
      var bothACHAndIBCAvailable = selectedPayOption.bothACHAndIBCAvailable;
      var achDepositLimitExceeded = $scope.data.achDepositLimitExceeded;

      return (
        (isAvailable || existsOnFile) &&
        isIBC &&
        bothACHAndIBCAvailable &&
        !achDepositLimitExceeded
      );
    }

    /**
     * Is deposit section visible?
     * - available payment
     * - not stored or not IBC or not exceeded
     *
     * @return {Boolean}
     */
    function _isDepositFormVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var isAvailable = $scope.depositDataModel.isAvailable !== false;
      var existsOnFile = $scope.events.existsOnFile();
      var isIBC = selectedPayOption.ftype === 'IBC';
      var isACH = selectedPayOption.ftype === 'ACH';
      var isCC = selectedPayOption.ftype === 'CC';
      var isStored = $scope.data.depositSection === 'STORED';
      var achDepositLimitExceeded = $scope.data.achDepositLimitExceeded;
      var unableToFetchBankAccounts =
        (isIBC || isACH) && isStored && $scope.data.unableToFetchBankAccounts;
      var unableToFetchCardsOnFile =
        isCC && isStored && $scope.data.unableToFetchCardsOnFile;

      return (
        (isAvailable || existsOnFile || selectedPayOption.isAvailable ||
          ($rootScope.activeFeatures &&
            _.get($rootScope, 'activeFeatures.showApplePayQuickDeposit', false) &&
            $window.ApplePaySession && $window.ApplePaySession.canMakePayments())) &&
        (!isStored || !isIBC || !achDepositLimitExceeded) &&
        !unableToFetchBankAccounts &&
        !unableToFetchCardsOnFile
      );
    }

    /**
     * Is section visible?
     * - is IBC
     * - is not available
     * - is not exceeded
     *
     * @return {Boolean}
     */
    function _isIBCInvalidVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var existsOnFile = $scope.events.existsOnFile();
      var isIBC = selectedPayOption.ftype === 'IBC';
      var isNew = $scope.data.depositSection === 'NEW';
      var isStored = $scope.data.depositSection === 'STORED';
      var isNotValidNew = isNew && !selectedPayOption.isAvailable;
      var isNotValidStored = isStored && !existsOnFile;
      var achDepositLimitExceeded = $scope.data.achDepositLimitExceeded;

      return (
        isIBC && (isNotValidNew || isNotValidStored) && !achDepositLimitExceeded
      );
    }

    /**
     * Is section visible?
     * - is not IBC
     * - is available
     * - is not exceeded
     *
     * @return {Boolean}
     */
    function _isNotIBCValidVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var existsOnFile = $scope.events.existsOnFile();
      var isIBC = selectedPayOption.ftype === 'IBC';
      var isNew = $scope.data.depositSection === 'NEW';
      var isStored = $scope.data.depositSection === 'STORED';
      var isValidNew = isNew && selectedPayOption.isAvailable;
      var isValidStored = isStored && existsOnFile;
      var achDepositLimitExceeded = $scope.data.achDepositLimitExceeded;

      return (
        !isIBC || (isValidNew && !achDepositLimitExceeded) || isValidStored
      );
    }

    /**
     * Is section visible?
     * - is not calculating
     * - is pending
     * - is IBC or CC
     * @return {Boolean}
     */
    function _isPendingNotCalculatingVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var calculatingFees = $scope.data.calculatingFees;
      var isPending = $scope.depositDataModel.isPending !== true;
      var isIBC = selectedPayOption.ftype === 'IBC';
      var isCC = selectedPayOption.ftype === 'CC';

      return !calculatingFees && isPending && (isIBC || isCC);
    }

    /**
     * Is section visible?
     * - is IBC
     * - is available
     * - is exceeded
     *
     * @return {Boolean}
     */
    function _isIBCValidExceededVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var isAvailable = $scope.depositDataModel.isAvailable !== false;
      var isIBC = selectedPayOption.ftype === 'IBC';
      var achDepositLimitExceeded = $scope.data.achDepositLimitExceeded;

      return isAvailable && isIBC && achDepositLimitExceeded;
    }

    /**
     * Is Deposit Loaded ?
     * @return {Boolean}
     */
    function _isDepositLoaded() {
      return !$scope.data.errorLoadingData && !$scope.data.loading;
    }

    function _isAllRequestCardsFailed() {
      return (
        $scope.data.unableToFetchBankAccounts &&
        $scope.data.unableToFetchCardsOnFile &&
        $scope.data.unableToFetchPrepaidCards
      );
    }

    /**
     * Is "betcash Limit Exceeded"?
     * @return {Boolean}
     */
    function _isBetcashLimitExceeded() {
      var isAvailable = $scope.depositDataModel.isAvailable !== false;
      var isBetcash =
        Utilities.prop('depositDataModel.selectedOnFile.ftype', $scope) ===
        'ACH';
      var limitExceeded = $scope.data.achDepositLimitExceeded;
      return _isDepositLoaded() && isAvailable && isBetcash && limitExceeded;
    }

    /**
     * Is "Add New Deposit Option" visible?
     * @return {Boolean}
     */
    function _isAddNewDepositOptionsVisible() {
      var isDesktop = $rootScope.layout === 'desktop';
      var hasOptions = !!(
        $scope.data.depositOptions && $scope.data.depositOptions.length
      );
      var showAddNewDepositOptions = $scope.data.showAddNewDepositOptions;
      var hideOptions = $rootScope.hideDepositOptions;

      return (
        !isDesktop &&
        _isDepositLoaded() &&
        hasOptions &&
        showAddNewDepositOptions &&
        !hideOptions
      );
    }

    /**
     * Is the feature "paypal in quick-deposit" enabled?
     * @return {Boolean}
     */
    function _isPaypalInQuickDepositEnabled() {
      return (
        $rootScope.activeFeatures &&
        $rootScope.activeFeatures.showPaypalQuickDeposit
      );
    }

    /**
     * Is the feature "paypal in quick-deposit" enabled?
     * @return {Boolean}
     */
    function _isApplePayInQuickDepositEnabled() {
      return (
        _isQuickDeposit() &&
        $rootScope.activeFeatures &&
        $rootScope.activeFeatures.showApplePayQuickDeposit &&
        $window.ApplePaySession &&
        $window.ApplePaySession.supportsVersion(3)
      );
    }

    /**
     * Is the Quick Deposit Button Disabled?
     * @return {Boolean}
     */
    function _disableQuickDepositButton() {
      var makingDeposit = $scope.data.makingDeposit;
      var calculatingFees = $scope.data.fee.calculatingFees;
      var exists = $scope.depositDataModel.depositTypeId;
      var sightlineError =
        Utilities.prop('depositDataModel.selectedOnFile.ftype', $scope) ===
          'SLN' && $scope.quickDepositSightlineError;

      return makingDeposit || calculatingFees || !exists || sightlineError;
    }

    /**
     * Whether we're running the app in the MicroApp environment
     * @return {Boolean}
     */
    function _isDepositMicroApp() {
      return (
        $rootScope.productContext !== 'tvg4' &&
        $rootScope.productContext !== 'touch2'
      );
    }

    function _isBetSlip() {
      return $location.path().indexOf('/betslip') !== -1;
    }

    function _showNewDepositSuccessModal() {
      return $rootScope.activeFeatures &&
        $rootScope.activeFeatures.showDepositSuccessModal &&
        $scope.fromOption && $scope.fromOption.tla !== 'registration';
    }

    function _isIos() {
      return ConfigurationFac.getApplicationContextItem('product') === 'ios';
    }
    /**
     * Is sightline deposit over balance?
     * @return {Boolean}
     */
    function _sightlineBalanceExceeded() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var isSLN = selectedPayOption.ftype === 'SLN';
      var overLimit =
        $scope.data.fee.transactionTotal > $scope.sightlineBalance;

      return isSLN && overLimit;
    }

    /**
     * Is section visible?
     * - is IBC
     * - is available
     * - is not exceeded
     *
     * @return {Boolean}
     */
    function _isIBCValidVisible() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var existsOnFile = $scope.events.existsOnFile();
      var isIBC = selectedPayOption.ftype === 'IBC';
      var isNew = $scope.data.depositSection === 'NEW';
      var isStored = $scope.data.depositSection === 'STORED';
      var isValidNew = isNew && selectedPayOption.isAvailable;
      var isValidStored = isStored && existsOnFile;
      var achDepositLimitExceeded = $scope.data.achDepositLimitExceeded;

      return isIBC && (isValidNew || isValidStored) && !achDepositLimitExceeded;
    }

    /**
     * Is section visible?
     * - achNewDepositFlow toggle on
     * - failed request to fetch bank accounts
     *
     * @return {Boolean}
     */
    function _unableToFetchBankAccounts() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var unableToFetchBankAccounts =
        $scope.data.unableToFetchBankAccounts || false;
      var isStored = $scope.data.depositSection === 'STORED';
      var isIBC = selectedPayOption.ftype === 'IBC';
      var isACH = selectedPayOption.ftype === 'ACH';

      return (isIBC || isACH) && isStored && unableToFetchBankAccounts;
    }

    /**
     * Is section visible?
     * - failed request to fetch cards on file
     *
     * @return {Boolean}
     */
    function _unableToFetchCardsOnFile() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var unableToFetchCardsOnFile =
        $scope.data.unableToFetchCardsOnFile || false;
      var isStored = $scope.data.depositSection === 'STORED';
      var isCC = selectedPayOption.ftype === 'CC';

      return isCC && isStored && unableToFetchCardsOnFile;
    }

    /**
     * Is CC or Betcash and New Card
     * to only show three titles
     * @return {Boolean}
     */
    function _hasThreeTitles() {
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var isBetCash = selectedPayOption.ftype === 'IBC';
      var isCC = selectedPayOption.ftype === 'CC';
      var isNewCard = $scope.data.depositSection !== 'STORED';
      return isBetCash || (isCC && isNewCard);
    }

    /**
     * Toggle all the CMS keys for the CC
     * and betcash titles
     * @return {Boolean}
     */
    function _toggleTitles() {
      var title;
      var selectedPayOption = $scope.data.selectedPayOption || {};
      var isBetCash = selectedPayOption.ftype === 'IBC';
      var isCC = selectedPayOption.ftype === 'CC';
      var isNewCard = $scope.data.depositSection === 'NEW';
      if (isBetCash) {
        title = isNewCard
          ? 'deposit-betcash-card-add-title'
          : 'deposit-betcash-cards-title';
      } else if (isCC) {
        title = isNewCard
          ? 'deposit-credit-card-add-title'
          : 'deposit-credit-cards-title';
      }
      return title;
    }

    /**
     * If is TVG3 show a paragraph and not paypal deposits
     * @return {Boolean}
     */
    function _isTVG3() {
      return (
        ConfigurationFac.getApplicationContextItem('product') === 'tvg' &&
        ConfigurationFac.getApplicationContextItem('application') === 'deposit'
      );
    }

    //
    // START MODULE
    //

    init();

    /* eslint-disable angular/on-watch */
    unbind.push(
      $rootScope.$on('reloadDeposit', function () {
        $scope.data.selectedPayOption = $rootScope.selectedPayOption;
        $scope.data.selectedCard = $rootScope.selectedCard;
        init();
      })
    );

    unbind.push(
      $rootScope.$on('sightlineUserEnrolled', function () {
        _addSightlineFunds();
        $scope.firstTimeAddFunds = true;
      })
    );

    unbind.push(
      $rootScope.$on('goToSln', function () {
        UserActionEventsService.emit('Deposit', {
          gaEventAction: 'Card Declined Redirect',
          gaEventLabel: 'Card Declined Redirect | Sightline',
          depositAmount: $scope.depositDataModel.amount,
          depositType: $scope.data.fee.fee,
          netDepositFee: _getCurrentDepositTypeString()
        });

        DepositSrv.setGoToSln(true);
        if (_isDepositMicroApp()) {
          $location.path('/deposit');
        }

        // TODO : emit to depositCtrl that we need to change to prePaidCard
      })
    );

    unbind.push(
      $rootScope.$on('redirectFromPaypalUsingTabs', function () {
        if (!_isQuickDeposit()) {
          _selectOption(PaypalDepositConfig, false);
        }
      })
    );

    unbind.push(
      $rootScope.$on('redirectFromSightlineUsingTabs', function () {
        if (!_isQuickDeposit()) {
          $scope.isAddingFunds = true;
          _selectOption(SightlineDepositConfig, false);
        }
      })
    );

    unbind.push(
      $rootScope.$on('redirectSightline-discCard', function () {
        _makeDepositInvalidCreditCardError(true);
      })
    );

    $scope.$on('$destroy', function () {
      if (invalidFormLabelTimer) {
        $timeout.cancel(invalidFormLabelTimer);
      }

      _.forEach(unbind, function (bind) {
        bind();
      });
    });

    function _slicedCard(bankAccNumber) {
      return bankAccNumber
        .toString()
        .slice(bankAccNumber.length - 4, bankAccNumber.length);
    }
    /* eslint-enable */
  }

  angular
    .module('TVG.Deposit')
    .controller('DepositController', DepositController);
}());

(function () {
  'use strict';

  WithdrawCancelDesktopController.$inject = ['$window', '$scope', 'WithdrawFac', 'SightlineSrv', '$rootScope', 'ApiWithdrawGTMFac', 'ConfigurationFac', 'Utilities', '$filter'];
  function WithdrawCancelDesktopController(
    $window,
    $scope,
    WithdrawFac,
    SightlineSrv,
    $rootScope,
    ApiWithdrawGTMFac,
    ConfigurationFac,
    Utilities,
    $filter
  ) {
    $scope.model = {
      withdrawPendingList: [],
      isLoading: true,
      errorFetchingPending: false
    };

    $scope.events = {
      cancelPendingWithdraw: _cancelPendingWithdraw
    };

    getWithdrawPendingList();

    $scope.showPendingWithdrawls = !$rootScope.activeFeatures.pawsWalletAvailable ||
      !$rootScope.shouldShowWallet;

    $scope.$on('WithdrawSuccessful::UpdatePendingRequests', function () {
      getWithdrawPendingList();
    });

    $rootScope.$on('PendingWithdrawCancelClick', function (event, withdrawId) { // eslint-disable-line
      var pendingWithdraw = _getPendingWithdraw(withdrawId);

      _sendGTMEvent('pendingWithdrawCancel', {
        eventAction: 'Cancel Withdraw button Click',
        withdrawAmount: pendingWithdraw.amount,
        withdrawType: _getBetTypeName(pendingWithdraw.paymentType)
      });
    });

    $rootScope.$on('PendingWithdrawUndoCancelClick', function (event, withdrawId) { // eslint-disable-line
      var pendingWithdraw = _getPendingWithdraw(withdrawId);

      _sendGTMEvent('pendingWithdrawCancel', {
        eventAction: 'Cancel Pending Withdraw | Cancel',
        withdrawAmount: pendingWithdraw.amount,
        withdrawType: _getBetTypeName(pendingWithdraw.paymentType)
      });
    });

    //eslint-disable-next-line
    var cancelWithdrawalMockedMessages = {
      success: 'Your withdraw has been cancelled successfully.',
      accepted: 'Almost done, it is taking a little longer to cancel your withdrawal. ',
      toteFailure: 'Almost done, it is taking a little longer to cancel your withdrawal.',
      toteUnknown: 'Almost done, it is taking a little longer to cancel your withdrawal.',
      genericFailure: 'An error occurred while trying to cancel your withdraw.'
    };

    function _getPendingWithdraw(id) {
      var i;

      if (id) {
        for (i = 0; i < $scope.model.withdrawPendingList.length; i++) {
          if (id === $scope.model.withdrawPendingList[i].withdrawalId) {
            return $scope.model.withdrawPendingList[i];
          }
        }
      }

      return {};
    }

    function _shouldShowOption(option) {
      var toggles = {
        ACH: !$rootScope.activeFeatures.pawsACH,
        VIWD: !$rootScope.activeFeatures.pawsCC,
        CHK: !$rootScope.activeFeatures.pawsCHK,
        PAY: !$rootScope.activeFeatures.pawsPAY
      };

      // eslint-disable-next-line angular/definedundefined
      return toggles[option] !== undefined && !$rootScope.isFdrApp &&
      $rootScope.activeFeatures.pawsWalletAvailable &&
      $rootScope.shouldShowWallet ? toggles[option] : true;
    }

    function _getBetTypeName(key) {
      switch (key) {
        case 'ACH':
          return 'TVG BetCash';
        case 'CHK':
          return 'Check Request';
        case 'SPL':
          return 'Sightline';
        case 'VIWD':
          return 'Debit Card';
        case 'MZM':
          return 'Online Banking';
        default:
          return '';
      }
    }

    function _sendGTMCancelWithdraw(withdrawId, success) {
      var pendingWithdraw = _getPendingWithdraw(withdrawId);
      var event = success ?
        'pendingWithdrawCancel' : 'pendingWithdrawCancelError';

      _sendGTMEvent(event, {
        success: success,
        eventName: 'WithdrawCancelled',
        eventScreenName: 'My account | Withdraw',
        eventAction: 'Cancel Pending Withdraw ' +
        (success ? 'Success' : 'Error'),
        gaEventLabel: success ? '' : 'Generic Error',
        errorType: success ? '' : 'Cancel Pending Withdraw Error',
        errorMessage: success ? '' : 'Generic Error',
        logged: true,
        withdrawAmount: pendingWithdraw.Amount,
        withdrawType: _getBetTypeName(pendingWithdraw.PaymentType)
      });
    }

    function _cancelPendingWithdraw(withdrawId) {
      var pendingWithdraw = _getPendingWithdraw(withdrawId);
      var action = _cancelGenericPendingWithdrawal;

      _sendGTMEvent('pendingWithdrawCancel', {
        eventAction: 'Cancel Pending Withdraw | Confirm',
        withdrawAmount: pendingWithdraw.amount,
        withdrawType: _getBetTypeName(pendingWithdraw.paymentType)
      });

      $scope.model.isLoading = true;

      return action(pendingWithdraw)
        .then(function (response) {
          var messagesObj = $filter('CMSValue')('cancelWithdrawalMessages');
          var messages = {};
          try {
            messages = angular.fromJson(messagesObj);
          } catch (error) {
              // Prevent test failure
          }

          if (response && response.data && response.data.status
            && response.data.status === 202) {
            $scope.$emit('onWithdrawalCancelSuccess', {});
            $scope.$broadcast('PendingWithdrawals::CancelWarning',
              { withdrawalId: withdrawId,
                message: messages && messages.accepted ? messages.accepted :
                cancelWithdrawalMockedMessages.accepted });
            $rootScope.$broadcast('accountBalance_update');
            _sendGTMCancelWithdraw(withdrawId, true);
          } else {
            if (response.succeeded) {
              $scope.$emit('onWithdrawalCancelSuccess', {});
              $scope.$broadcast('PendingWithdrawals::CancelSuccess',
                { withdrawalId: withdrawId,
                  message: messages && messages.success ? messages.success :
                cancelWithdrawalMockedMessages.success });
              $rootScope.$broadcast('accountBalance_update');
              _sendGTMCancelWithdraw(withdrawId, true);
            } else {
              $scope.$emit('onWithdrawalCancelError', {});
              $scope.$broadcast('PendingWithdrawals::CancelError',
                { withdrawalId: withdrawId,
                  message: messages && messages.genericFailure ? messages.genericFailure
                : cancelWithdrawalMockedMessages.genericFailure });
              _sendGTMCancelWithdraw(withdrawId, false);
            }
          }
        })
        .catch(function (err) {
          var messagesObj = $filter('CMSValue')('cancelWithdrawalMessages');
          var messages = {};
          try {
            messages = angular.fromJson(messagesObj);
          } catch (error) {
              // Prevent test failure
          }

          $scope.$emit('onWithdrawalCancelError', {});

          if (err && err.data && err.data.exception) {
            switch (err.data.exception) {
              case 'TOTE_DEPOSIT_FAILURE':
                $scope.$broadcast('PendingWithdrawals::CancelWarning',
                  { withdrawalId: withdrawId,
                    message: messages && messages.toteFailure ? messages.toteFailure :
                     cancelWithdrawalMockedMessages.toteFailure });
                break;
              case 'TOTE_DEPOSIT_UNKNOWN':
                $scope.$broadcast('PendingWithdrawals::CancelWarning',
                  { withdrawalId: withdrawId,
                    message: messages && messages.toteUnknow ? messages.toteUnknow :
                    cancelWithdrawalMockedMessages.toteUnknown });
                break;
              default:
                $scope.$broadcast('PendingWithdrawals::CancelError',
                  { withdrawalId: withdrawId,
                    message: messages && messages.genericFailure ? messages.genericFailure :
                    cancelWithdrawalMockedMessages.genericFailure });
                break;
            }
          } else {
            $scope.$broadcast('PendingWithdrawals::CancelError',
              { withdrawalId: withdrawId,
                message: messages && messages.genericFailure ? messages.genericFailure :
                cancelWithdrawalMockedMessages.genericFailure });
          }
          _sendGTMCancelWithdraw(withdrawId, false);
        })
        .finally(function () {
          $scope.model.isLoading = false;
        });
    }

    function _cancelGenericPendingWithdrawal(pendingWithdrawal) {
      return WithdrawFac.withdrawCancel(pendingWithdrawal.withdrawalId)
        .then(function (response) {
           // update balance
          if (response.data && response.data.balance) {
            $rootScope.$emit('accountBalance_changed', parseFloat(response.data.balance));
          }
          return { data: response, succeeded: response &&
            ((response[0] && response[0].CancellationSucceeded) ||
            response.data && response.data.hasOwnProperty('balance')) };
        });
    }

    //eslint-disable-next-line
    function _cancelSightlinePendingWithdraw(pendingWithdrawal) {
      return SightlineSrv.cancelWithdrawal(pendingWithdrawal.withdrawalId)
        .then(function () { return true; })
        .catch(function () { return false; });
    }

    function getWithdrawPendingList() {
      $scope.model.isLoading = true;
      return WithdrawFac.withdrawPendingList()
        .then(function (response) {
          var lastWithdrawalResult = $rootScope.lastWithdrawalResult;
          var updateLastWithdrawal;
          if (lastWithdrawalResult && lastWithdrawalResult.UUID) {
            updateLastWithdrawal = response.filter(function (item) {
              return item.transactionUUID === lastWithdrawalResult.UUID;
            }).length === 0;
            if (updateLastWithdrawal) {
              lastWithdrawalResult.processing = true;
              response.push(lastWithdrawalResult);
            }
          }

          $scope.model.withdrawPendingList = response.filter(function (withdraw) {
            return _shouldShowOption(withdraw.paymentType);
          });
          $rootScope.hasPendingWithdrawals = response.length > 0;
          $scope.model.withdrawPendingList.forEach(function (item) {
            item.DateInitiated = Utilities.toDateFormat('MM/DD/YYYY', item.transactionDate);
            item.amount = parseFloat(item.amount);
          });

          $scope.model.errorFetchingPending = false;
          $rootScope.lastWithdrawalResult = null;
        })
        .catch(function () {
          /* eslint-disable */
          $rootScope.hasPendingWithdrawals = false;
          /* eslint-enable */
          $scope.model.errorFetchingPending = true;
        })
        .finally(function () {
          $scope.model.isLoading = false;
        });
    }

    function _buildGTMEvent(params) {
      var p = {};
      var applicationContext = ConfigurationFac.getApplicationContextItem('application');

      if ($rootScope.user) {
        p.accountId = $rootScope.user.accountNumber;
        p.residenceState = $rootScope.user.homeAddress.StateAbbr;
      }

      p.gaEventCategory = 'Pending Withdraw';
      p.page = params.page || $window.location.pathname;
      p.gaEventAction = params.eventAction;
      p.gaEventLabel = params.withdrawType;
      p.loginStatus = !!p.accountId ? 'Logged In' : 'Logged Out';
      p.registrationStatus = 'Registered';
      p.screenName = ApiWithdrawGTMFac.isTVG4() ? 'My Account' : 'Withdraw';
      p.sectionName = ApiWithdrawGTMFac.isTVG4() ?
        'My Account | My Funds | Withdraw' :
        params.eventScreenName;
      p.siteVersion = ConfigurationFac.getSiteVersion(applicationContext);
      p.withdrawAmount = ApiWithdrawGTMFac.gtmCurrencyFormat(params.withdrawAmount);
      p.withdrawType = params.withdrawType;

      if (params.errorMessage) {
        p.errorMessage = params.errorMessage;
        p.errorType = params.errorType;
        p.gaEventAction = params.errorType;
        p.gaEventLabel = params.errorMessage;
      }

      if (p.siteVersion === 'TVG3') {
        p.screenName = 'Withdrawal';
        p.sectionName = undefined;
      }

      return p;
    }

    function _sendGTMEvent(event, params) {
      var obj = _buildGTMEvent(params);

      ApiWithdrawGTMFac.sendGTMEvent(event, obj);
    }
  }

  angular.module('TVG.Withdraw')
         .controller('WithdrawCancelDesktopController', WithdrawCancelDesktopController);
}());

(function () {
  'use strict';

  ManagePaymentMethodsController.$inject = ['$uibModal', '$q', '$scope', '$rootScope', '$timeout', '$location', '$window', '$sce', '$filter', 'DepositSrv', 'ConfigurationFac', 'CookieFac', 'ApiDepositsGTMFac', 'NotificationService', 'ManagePaymentMethodsSrv', 'DepositInitialDataFac', 'DEPOSIT_TYPES'];
  function ManagePaymentMethodsController(
    $uibModal,
    $q,
    $scope,
    $rootScope,
    $timeout,
    $location,
    $window,
    $sce,
    $filter,
    DepositSrv,
    ConfigurationFac,
    CookieFac,
    ApiDepositsGTMFac,
    NotificationService,
    ManagePaymentMethodsSrv,
    DepositInitialDataFac,
    DEPOSIT_TYPES
  ) {
    var editCardRedesignModule = (function () {
      function _performEditCard(card) {
        var accountId =
          ($rootScope.user && $rootScope.user.accountNumber) ||
          DepositSrv.accountId;
        $scope.data.loading = true;
        ManagePaymentMethodsSrv.updateCard(
          {
            bankName: card.bankName || '',
            cardID: card.id,
            ExpirationMonthYear: _buildExpirationMonthYear(
              card.expirationMonth,
              card.expirationYear
            ),
            selectedCardType: {
              cardTypeId: card.cardTypeId
            }
          },
          accountId
        )
          .then(
            function () {
              $rootScope.activePaymentMngTab =
                $scope.data.selectedPayOption &&
                $scope.data.selectedPayOption.ftype;
              NotificationService.success(
                'Success!',
                $filter('CMSValue')('managePaymentsUpdateCardsSuccess'),
                _getDepositFormFirstChildSelector()
              );

              $scope.events.resetDataModel();
              $scope.events.getPayMethodsInitialData('CC');
            },
            function () {
              // $scope.$emit('onDepositEventFailure');
              var message = $filter('CMSValue')(
                'managePaymentsUpdateCardsFailure'
              );

              NotificationService.error(
                'Error!',
                message,
                _getDepositFormFirstChildSelector()
              );

              $scope.data.loading = false;
            }
          )
          .catch(function () {
            var message = $filter('CMSValue')(
              'managePaymentsUpdateCardsFailure'
            );

            NotificationService.error(
              'Error!',
              message,
              _getDepositFormFirstChildSelector()
            );

            $scope.data.loading = false;
          });
      }

      function _getMonthAndYearFromExpirationDate(expirationDate) {
        if (!/^\d{1,2}\/\d{1,2}$/.test(expirationDate)) {
          return 0;
        }
        return {
          month: parseInt(expirationDate.split('/')[0], 10),
          year: parseInt(expirationDate.split('/')[1], 10)
        };
      }

      function _createEditCardInput(card) {
        var expirationMonthYear = _getMonthAndYearFromExpirationDate(
          card.expirationDate
        );
        card.expirationMonth = expirationMonthYear.month;
        card.expirationYear = expirationMonthYear.year;
        return card;
      }

      function _showEditCardConfirmModal(card) {
        var editCardModal;
        var modalScope = $scope.$new();
        modalScope.selectedCard = _createEditCardInput(card);

        editCardModal = $uibModal.open({
          templateUrl: 'src/templates/notification_edit_card.html',
          scope: modalScope,
          windowTemplateUrl: 'src/templates/modal-window.html',
          backdropClass: 'tvgmodal-backdrop',
          windowClass: 'account tvgmodal-dma-redesign'
        });

        editCardModal.result
          .then(function (editedCard) {
            if (editedCard) {
              _performEditCard(editedCard);
            }
          })
          .catch(function () {})
          .finally(function () {
            if (modalScope) {
              modalScope.$destroy();
            }
          });
      }

      return {
        openModal: _showEditCardConfirmModal
      };
    }());

    var removeCardRedesignModule = (function () {
      function _showRemoveCardConfirmModal(card) {
        var removeCardModal;
        var modalScope = $scope.$new();
        modalScope.selectedCard = card;
        modalScope.slicedCard = function (opt) {
          return _slicedCard(opt);
        };

        removeCardModal = $uibModal.open({
          templateUrl: 'src/templates/notification_delete_card.html',
          scope: modalScope,
          windowTemplateUrl: 'src/templates/modal-window.html',
          backdropClass: 'tvgmodal-backdrop',
          windowClass: 'account tvgmodal-dma-redesign'
        });

        removeCardModal.result
          .then(function (cardToRemove) {
            if (cardToRemove) {
              _removeCard(cardToRemove.id);
            }
          })
          .catch(function () {})
          .finally(function () {
            if (modalScope) {
              modalScope.$destroy();
            }
          });
      }

      return {
        openModal: _showRemoveCardConfirmModal
      };
    }());

    var today = new Date();

    var bankNameInfoMessages = {
      DEFAULT: '',
      ERROR: 'Please fill the bank name',
      FETCHING: 'Fetching bank name'
    };

    $scope.withPlaceholders = true;
    $scope.currentYear = parseInt($filter('date')(today, 'yy'), 10);
    $scope.currentMonth = parseInt($filter('date')(today, 'MM'), 10);

    $scope.data = {
      // Disables bank name input by default
      bankNameDisabled: true,
      // Default bank name label,
      bankNameMessage: bankNameInfoMessages.DEFAULT,
      errorBankName: false,
      numberPattern: /^[0-9]+$/,
      expirationDateValues: DepositSrv.getExpirationDateValues(),
      loading: true,
      savingCard: false,
      errorFormRestrictions: false,
      errorPaymentRestrictions: false,
      newCardForm: false,
      editCardForm: false,
      limitEditor: false,
      showLimits: true,
      showLimityTypes: {
        Credit: true,
        Debit: true,
        CreditSigned: true,
        DebitSigned: true,
        ACH: true,
        APPL: true
      },
      showLimitIntervals: { Daily: true, Monthly: true },
      limitError: false,
      limitErrorMessage: '',
      forms: ManagePaymentMethodsSrv.getPaymentForms(),
      paymentMethodsOptions: [
        {
          depositTypeId: 2,
          ftype: 'IBC',
          name: 'eCheck',
          paymentLimits: [
            {
              typeName: 'eCheck',
              limitInterval: {
                Daily: {
                  DepositLimitIntervalId: 2,
                  DepositLimitTypeId: 4,
                  Min: 0.1,
                  Effective: 0
                },
                Monthly: {
                  DepositLimitIntervalId: 4,
                  DepositLimitTypeId: 4,
                  Min: 0.1,
                  Effective: 0
                }
              }
            }
          ]
        },
        {
          depositTypeId: 4,
          ftype: 'CC',
          name: 'Credit/Debit Card',
          paymentLimits: [
            {
              typeName: 'Credit',
              limitInterval: {
                Daily: {
                  DepositLimitIntervalId: 2,
                  DepositLimitTypeId: 2,
                  Min: 3,
                  Effective: 0
                },
                Monthly: {
                  DepositLimitIntervalId: 4,
                  DepositLimitTypeId: 2,
                  Min: 3,
                  Effective: 0
                }
              }
            },
            {
              typeName: 'Debit',
              limitInterval: {
                Daily: {
                  DepositLimitIntervalId: 2,
                  DepositLimitTypeId: 3,
                  Min: 3,
                  Effective: 0
                },
                Monthly: {
                  DepositLimitIntervalId: 4,
                  DepositLimitTypeId: 3,
                  Min: 3,
                  Effective: 0
                }
              }
            },
            {
              typeName: 'CreditSigned',
              limitInterval: {
                Daily: {
                  DepositLimitIntervalId: 2,
                  DepositLimitTypeId: 5,
                  Min: 3,
                  Effective: 0
                },
                Monthly: {
                  DepositLimitIntervalId: 4,
                  DepositLimitTypeId: 5,
                  Min: 3,
                  Effective: 0
                }
              }
            },
            {
              typeName: 'DebitSigned',
              limitInterval: {
                Daily: {
                  DepositLimitIntervalId: 2,
                  DepositLimitTypeId: 6,
                  Min: 3,
                  Effective: 0
                },
                Monthly: {
                  DepositLimitIntervalId: 4,
                  DepositLimitTypeId: 6,
                  Min: 3,
                  Effective: 0
                }
              }
            }
          ]
        }
      ]
    };

    $scope.events = {
      resetDataModel: _resetDataModel,
      addNewCard: _addNewCard,
      editCard: _editCard,
      showEditCardConfirmModal: editCardRedesignModule.openModal,
      showRemoveCardConfirmModal: removeCardRedesignModule.openModal,
      redirectToAddNewCard: _redirectToAddNewCard,
      removeCard: _removeCard,
      editCardAction: _editCardAction,
      removeCardAction: _removeCardAction,
      editLimit: _editLimit,
      cancelLimitEdition: _cancelLimitEdition,
      validateLimitAmount: _validateLimitAmount,
      saveLimit: _saveLimit,
      subTypeCardChanged: _subTypeCardChanged,
      getPayMethodsInitialData: _getPayMethodsInitialData,
      goToDeposit: _goToDeposit,
      selectOption: _selectOption,
      slicedCard: _slicedCard,
      unableToFetchLimits: _unableToFetchLimits
    };

    function init() {
      var applePayManagement = false;

      // eslint-disable-next-line
      if (window.__TVG_GLOBALS__ && window.__TVG_GLOBALS__.FEATURE_TOGGLES) {
        // eslint-disable-next-line
        var toggles = JSON.parse(decodeURIComponent(window.__TVG_GLOBALS__.FEATURE_TOGGLES) || { featureToggles: [] }).featureToggles;
        // eslint-disable-next-line
        for (var i = 0; i < toggles.length; i++) {
          if (toggles[i].name === 'applePayPaymentManagement') {
            applePayManagement = toggles[i].enabled;
            break;
          }
        }
      }

      if (
        $scope.data.paymentMethodsOptions[0].ftype !== 'APPL' &&
        applePayManagement
      ) {
        $scope.data.paymentMethodsOptions.unshift({
          depositTypeId: 11,
          ftype: 'APPL',
          name: 'Apple Pay',
          paymentLimits: [
            {
              typeName: 'Apple Pay',
              limitInterval: {
                Daily: {
                  DepositLimitIntervalId: 2,
                  DepositLimitTypeId: 7,
                  Min: 3,
                  Effective: 0
                },
                Monthly: {
                  DepositLimitIntervalId: 4,
                  DepositLimitTypeId: 7,
                  Min: 3,
                  Effective: 0
                }
              }
            }
          ]
        });
      }
    }

    function _unableToFetchLimits() {
      return (
        $scope.data.unableToFetchLimits
      );
    }

    function _resetDepositDataModel() {
      $scope.depositDataModel = {
        cardNumber: '',
        bankName: '',
        selectedCardType: null
      };
    }

    function _resetDepositLimitModel() {
      $scope.depositLimitModel = {
        depositLimit: {},
        daily: false,
        depositLimitTypeName: '',
        amount: null,
        min: 0,
        max: 99999
      };
    }

    _resetDepositDataModel();
    _resetDepositLimitModel();

    function _resetDataModel() {
      $scope.data.loading = false;
      $scope.data.savingCard = false;
      $scope.data.errorFormRestrictions = false;
      $scope.data.errorPaymentRestrictions = false;
      $scope.data.newCardForm = false;
      $scope.data.editCardForm = false;
      $scope.data.limitEditor = false;
      $scope.data.limitError = false;

      _resetDepositDataModel();
      _resetDepositLimitModel();
    }

    function _buildExpirationMonthYear(expMonth, expYear) {
      var month =
        expMonth.toString().length === 1 ? '0' + expMonth : expMonth.toString();

      return month + '/' + expYear;
    }

    function _addNewCard(form) {
      var message;

      if (form.$valid) {
        $scope.data.loading = true;
        $scope.data.addingCard = true;

        $scope.depositDataModel.ExpirationMonthYear = _buildExpirationMonthYear(
          $scope.depositDataModel.expirationMonth,
          $scope.depositDataModel.expirationYear
        );

        ManagePaymentMethodsSrv.addCard($scope.depositDataModel).then(
          function () {
            NotificationService.success(
              'Success!',
              'Your card was successfully added.',
              _getDepositFormFirstChildSelector()
            );

            $scope.events.resetDataModel();
            $scope.events.getPayMethodsInitialData('CC');
          },
          function () {
            message =
              'We have not been able to add the card. Please try ' +
              'again if the problem persists.</br>' +
              $filter('CMSValue')('depositInitialDataErrorActionText');

            NotificationService.error(
              'Error!',
              message,
              _getDepositFormFirstChildSelector()
            );

            $scope.data.loading = false;
            $scope.data.savingCard = false;
          }
        );
      }
    }

    function _editCardAction(card) {
      $scope.data.editCardForm = true;
      $scope.depositDataModel.cardID = card.id;
      $scope.depositDataModel.cardNumber = card.cardNumberExt;
      $scope.depositDataModel.cardSecurityNumber = '';
      $scope.depositDataModel.ExpirationMonthYear = card.expirationDate;
      $scope.depositDataModel.expirationMonth = parseInt(
        card.expirationDate.split('/')[0],
        10
      );
      $scope.depositDataModel.expirationYear = parseInt(
        card.expirationDate.split('/')[1],
        10
      );
      $scope.depositDataModel.selectedCardType = {
        cardTypeId: card.cardTypeId,
        depositTypeId: card.depositTypeId,
        ftype: card.ftype,
        name: card.typeName,
        type: card.type
      };

      if ([
        'touch3',
        'ios2',
        'fdrmobile',
        'fdrios',
        'fdrandroid',
        'androidwrapper',
        'tvgandroid'
      ].indexOf($window.productContext) >= 0) {
        // prevent scroll to on ios iframe
        return;
      }

      $window.scrollTo(0, 0);
    }

    function _editCard(form) {
      var message;
      var accountId =
        ($rootScope.user && $rootScope.user.accountNumber) ||
        DepositSrv.accountId;

      if (form.$valid) {
        $scope.data.loading = true;
        $scope.data.editingCard = true;

        $scope.depositDataModel.ExpirationMonthYear = _buildExpirationMonthYear(
          $scope.depositDataModel.expirationMonth,
          $scope.depositDataModel.expirationYear
        );

        ManagePaymentMethodsSrv.updateCard($scope.depositDataModel, accountId)
          .then(
            function () {
              NotificationService.success(
                'Success!',
                $filter('CMSValue')('managePaymentsUpdateCardsSuccess'),
                _getDepositFormFirstChildSelector()
              );

              $scope.events.resetDataModel();
              $scope.events.getPayMethodsInitialData('CC');
            },
            function () {
              // $scope.$emit('onDepositEventFailure');
              message = $filter('CMSValue')('managePaymentsUpdateCardsFailure');

              NotificationService.error(
                'Error!',
                message,
                _getDepositFormFirstChildSelector()
              );

              $scope.data.loading = false;
              $scope.data.savingCard = false;
            }
          )
          .catch(function () {
            message = $filter('CMSValue')('managePaymentsUpdateCardsFailure');

            NotificationService.error(
              'Error!',
              message,
              _getDepositFormFirstChildSelector()
            );

            $scope.data.loading = false;
            $scope.data.savingCard = false;
          });
      }
    }

    function _removeCardAction(card) {
      var cardID = card.id;
      var accountId =
        ($rootScope.user && $rootScope.user.accountNumber) ||
        DepositSrv.accountId;

      NotificationService.confirm(
        'Remove Card',
        'Are you sure you want to remove this card?',
        _getDepositFormFirstChildSelector(),
        function () {
          $scope.events.removeCard(cardID, accountId);
        }
      );
    }

    function _removeCard(cardID) {
      var accountId =
        ($rootScope.user && $rootScope.user.accountNumber) ||
        DepositSrv.accountId;
      $scope.data.loading = true;
      $scope.data.savingCard = true;

      ManagePaymentMethodsSrv.removeCard(cardID, accountId)
        .then(
          function () {
            NotificationService.success(
              'Success!',
              $filter('CMSValue')('managePaymentsDeleteCardsSuccess'),
              _getDepositFormFirstChildSelector()
            );
            $scope.events.resetDataModel();
            $scope.events.getPayMethodsInitialData('CC');
          },
          function () {
            var message = $filter('CMSValue')(
              'managePaymentsDeleteCardsFailure'
            );

            NotificationService.error(
              'Error!',
              message,
              _getDepositFormFirstChildSelector()
            );

            $scope.data.loading = false;
            $scope.data.savingCard = false;
          }
        )
        .catch(function () {
          var message = $filter('CMSValue')('managePaymentsDeleteCardsFailure');

          NotificationService.error(
            'Error!',
            message,
            _getDepositFormFirstChildSelector()
          );

          $scope.data.loading = false;
          $scope.data.savingCard = false;
        });
    }

    function _editLimit(daily, depositLimit) {
      var limit;

      $scope.depositLimitModel.depositLimit = depositLimit;
      $scope.depositLimitModel.daily = daily;

      if (depositLimit) {
        $scope.depositLimitModel.depositLimitTypeName = depositLimit.typeName;

        limit = daily
          ? depositLimit.limitInterval.Daily
          : depositLimit.limitInterval.Monthly;
        $scope.depositLimitModel.amount = limit.Effective;
      }

      $scope.data.limitEditor = true;
      $scope.data.limitError = false;
    }

    function _cancelLimitEdition() {
      _resetDepositLimitModel();
      $scope.data.limitError = false;
      $scope.data.limitEditor = false;
    }

    function _validateLimitAmount() {
      var limit;
      var mapCardType = {
        Credit: 'CC',
        Debit: 'DEB',
        CreditSigned: 'CCS',
        DebitSigned: 'DEBS',
        ApplePay: 'APPL'
      };
      $scope.data.limitError = false;

      if (!$scope.depositLimitModel.amount) {
        $scope.data.limitError = true;
        $scope.data.limitErrorMessage = 'Limit amount is required';
        return;
      }

      if (isNaN($scope.depositLimitModel.amount)) {
        $scope.data.limitError = true;
        $scope.data.limitErrorMessage = 'Please, only enter numbers';
        return;
      }

      limit = $scope.depositLimitModel.daily
        ? $scope.depositLimitModel.depositLimit.limitInterval.Monthly
        : $scope.depositLimitModel.depositLimit.limitInterval.Daily;

      if (
        $scope.depositLimitModel.daily &&
        $scope.depositLimitModel.amount > limit.Effective
      ) {
        $scope.data.limitError = true;
        $scope.data.limitErrorMessage =
          'Daily limit can not be greater than monthly';
        return;
      }

      if (
        !$scope.depositLimitModel.daily &&
        $scope.depositLimitModel.amount < limit.Effective
      ) {
        $scope.data.limitError = true;
        $scope.data.limitErrorMessage =
          'Monthly limit can not be smaller than daily';
        return;
      }

      limit = $scope.depositLimitModel.daily
        ? $scope.depositLimitModel.depositLimit.limitInterval.Daily
        : $scope.depositLimitModel.depositLimit.limitInterval.Monthly;

      if ($scope.depositLimitModel.amount < limit.Min) {
        $scope.data.limitError = true;
        $scope.data.limitErrorMessage =
          'The limit has to be greater than ' + limit.Min;
      }

      //eslint-disable-next-line
      var isBetcash =
        $scope.data.selectedPayOption &&
        $scope.data.selectedPayOption.ftype &&
        ($scope.data.selectedPayOption.ftype === 'IBC' ||
          $scope.data.selectedPayOption.ftype === 'ACH');
      //eslint-disable-next-line
      var isApplePay =
        $scope.data.selectedPayOption &&
        $scope.data.selectedPayOption.ftype &&
        $scope.data.selectedPayOption.ftype === 'APPL';
      //eslint-disable-next-line
      var isCC =
        $scope.data.selectedPayOption &&
        $scope.data.selectedPayOption.ftype &&
        ($scope.data.selectedPayOption.ftype === 'CC' ||
          $scope.data.selectedPayOption.ftype === 'DEB');

      if ($scope.data.tvgLimits && isBetcash) {
        if ($scope.depositLimitModel.daily) {
          if (
            parseFloat($scope.depositLimitModel.amount) >
            parseFloat($scope.data.tvgLimits.dailyLimit)
          ) {
            $scope.data.limitError = true;
            $scope.data.limitErrorMessage =
              'Deposit limit chosen exceeds the maximum allowed';
          }
        } else if (
          parseFloat($scope.depositLimitModel.amount) >
          parseFloat($scope.data.tvgLimits.monthlyLimit)
        ) {
          $scope.data.limitError = true;
          $scope.data.limitErrorMessage =
            'Deposit limit chosen exceeds the maximum allowed';
        }
      }

      if ($scope.data.tvgLimits && (isCC || isApplePay)) {
        //eslint-disable-next-line
        var limitType =
          mapCardType[$scope.depositLimitModel.depositLimitTypeName];
        //eslint-disable-next-line
        var tvgLimit =
          limitType && $scope.data.tvgLimits[limitType]
            ? $scope.data.tvgLimits[limitType]
            : null;
        if (tvgLimit) {
          if ($scope.depositLimitModel.daily) {
            if (
              parseFloat($scope.depositLimitModel.amount) >
              parseFloat(tvgLimit.dailyLimit.depositLimit)
            ) {
              $scope.data.limitError = true;
              $scope.data.limitErrorMessage =
                'Deposit limit chosen exceeds the maximum allowed';
            }
          } else if (
            parseFloat($scope.depositLimitModel.amount) >
            parseFloat(tvgLimit.monthlyLimit.depositLimit)
          ) {
            $scope.data.limitError = true;
            $scope.data.limitErrorMessage =
              'Deposit limit chosen exceeds the maximum allowed';
          }
        }
      }
    }

    function _saveLimit() {
      var limit;
      var days;
      var futureDate;
      var isAchOrIbc;
      var isCC;
      var isApplePay;
      var limitAmounts;
      var accountId =
        ($rootScope.user && $rootScope.user.accountNumber) ||
        DepositSrv.accountId;

      if (!$scope.data.limitError) {
        $scope.data.loading = true;
        $scope.data.limitEditor = false;
        // $scope.data.savingCard = true;

        // Params: depositLimitTypeId, depositLimitIntervalId, maxLimit
        limit = $scope.depositLimitModel.daily
          ? $scope.depositLimitModel.depositLimit.limitInterval.Daily
          : $scope.depositLimitModel.depositLimit.limitInterval.Monthly;
        days =
          limit.Effective >= parseInt($scope.depositLimitModel.amount, 10)
            ? 0
            : 7;
        futureDate = moment()
          .add(days, 'd')
          .format('MM/DD/YYYY');
        // replace limit with object containing all limits if achNewDepositFlow
        isAchOrIbc =
          limit.DepositLimitTypeId === 1 || limit.DepositLimitTypeId === 4;
        isCC =
          limit.DepositLimitTypeId === 2 ||
          limit.DepositLimitTypeId === 3 ||
          limit.DepositLimitTypeId === 5 ||
          limit.DepositLimitTypeId === 6; // CCS, CC, DEB, DEBS
        isApplePay = limit.DepositLimitTypeId === 7;
        limitAmounts =
          isAchOrIbc ||
          (isCC || isApplePay)
            ? {
              daily: $scope.depositLimitModel.daily
                  ? $scope.depositLimitModel.amount
                  : null,
              weekly: null,
              monthly: $scope.depositLimitModel.daily
                  ? null
                  : $scope.depositLimitModel.amount
            }
            : $scope.depositLimitModel.amount;
        ManagePaymentMethodsSrv.updateLimit(
          limit.DepositLimitTypeId,
          limit.DepositLimitIntervalId,
          limitAmounts,
          accountId
        )
          .then(
            function () {
              var msg;
              $rootScope.activePaymentMngTab =
                $scope.data.selectedPayOption &&
                $scope.data.selectedPayOption.ftype;

              _setDepositTypeLimits();
              $scope.data.loading = false;
              $scope.data.errorPaymentRestrictions = false;
              msg =
                  'Your card limit was successfully updated.<br/> ' +
                  'The limit will be changed to ' +
                  $filter('currency')($scope.depositLimitModel.amount) +
                  ' at ' +
                  futureDate;
              NotificationService.success(
                  'Success!',
                  msg,
                  _getDepositFormFirstChildSelector()
                );
              $scope.data.message = msg;
            },
            function (data) {
              var error = data && data.response;
              var message =
                'We have not been able to update the card ' +
                'limit. Please try again if the problem persists.</br>' +
                $filter('CMSValue')('depositInitialDataErrorActionText');

              if ($scope.data.selectedPayOption.ftype === 'APPL') {
                message = $filter('CMSLabels')('applePayError', 'dmaManagementLabels') + '</br>' +
                  $filter('CMSValue')('depositInitialDataErrorActionText');
              }

              if (error && error.errorCode === 318) {
                message =
                  $filter('CMSLabels')('outOfRange', 'dmaManagementLabels') +
                  ' ' +
                  $filter('CMSValue')('depositInitialDataErrorActionText');
              }

              NotificationService.error(
                'Error!',
                message,
                _getDepositFormFirstChildSelector()
              );

              $scope.events.resetDataModel();
              $scope.data.loading = false;
            }
          )
          .then(_setDepositTypeLimits)
          .catch(function (error) {
            var message =
              'We have not been able to update the card ' +
              'limit. Please try again if the problem persists.</br>' +
              $filter('CMSValue')('depositInitialDataErrorActionText');

            if ($scope.data.selectedPayOption.ftype === 'APPL') {
              message = $filter('CMSLabels')('applePayError', 'dmaManagementLabels') + '</br>' +
                $filter('CMSValue')('depositInitialDataErrorActionText');
            }

            if (error && error.errorCode === 318) {
              message =
                $filter('CMSLabels')('outOfRange', 'dmaManagementLabels') +
                ' ' +
                $filter('CMSValue')('depositInitialDataErrorActionText');
            }

            NotificationService.error(
              'Error!',
              message,
              _getDepositFormFirstChildSelector()
            );

            $scope.events.resetDataModel();
            $scope.data.loading = false;
          });
      }
    }
    function _selectOption(opt) {
      $scope.data.selectedPayOption = opt;
      _setUserCardsOnFile();
      _setUserBankAccounts();
      NotificationService.clearBanner();
      $scope.data.limitEditor = false;

      _setDepositTypeLimits();
    }

    function _subTypeCardChanged(card) {
      $scope.depositDataModel.selectedCardType = card;
    }

    function _getBankAndCardsData(method) {
      var selectedOption;

      selectedOption = $scope.data.paymentMethodsOptions.indexOf(method);
      $scope.data.paymentMethodsOptions.map(function (item, index) {
        if (item.ftype === method) {
          selectedOption = index;
        }
        return item;
      });
      $scope.data.selectedPayOption =
        selectedOption === -1
          ? $scope.data.paymentMethodsOptions[0]
          : $scope.data.paymentMethodsOptions[selectedOption];

      _setUserBankAccounts();
      _setDepositTypeLimits();
      _setUserCardsOnFile();

      $scope.data.message = '';
      $scope.data.loading = false;
      $scope.data.errorPaymentRestrictions = false;
    }

    function _getPayMethodsInitialData(method) {
      if (
        !($rootScope.user && $rootScope.user.accountNumber) &&
        !DepositSrv.accountId
      ) {
        DepositSrv.getAccountNumber()
          .then(function () {
            $rootScope.loadedInitData = true;
            _getBankAndCardsData(method);
          })
          .catch(function (data) {
            var msg =
              'We encountered a problem. Please try again if the ' +
              'problem persists.</br>' +
              $filter('CMSValue')('depositInitialDataErrorActionText');
            if (data && data.response) {
              if (data.response.errorCode === 619) {
                msg =
                  'We encountered a problem. ' +
                  "It's required sign in the application";
              }
            }

            $scope.data.message = msg;
            $scope.data.loading = false;
            $scope.data.errorPaymentRestrictions = true;
          });
      } else {
        _getBankAndCardsData(method);
      }
    }

    function _slicedCard(bankAccNumber) {
      return bankAccNumber
        .toString()
        .slice(bankAccNumber.length - 4, bankAccNumber.length);
    }

    function _goToDeposit(card, index) {
      $rootScope.selectedPayOption =
        card.ftype === 'ACH' || card.ftype === 'IBC'
          ? $rootScope.betCashIndex
          : card.ftype;

      $rootScope.managePaymentMethodsRedirect = true;
      $rootScope.managePaymentMethodsTab = card.ftype;
      $rootScope.selectedCard = index;
      $rootScope.$broadcast('open', 'Deposit');
    }

    function _redirectToAddNewCard(option) {
      $rootScope.activeOption = undefined;
      $rootScope.dmaShowAddNewCardForm = true;
      $rootScope.managePaymentMethodsRedirect = true;
      $rootScope.managePaymentMethodsTab = option;
      $rootScope.selectedPayOption = option.toString();
      $rootScope.selectedCard = 0;
      $rootScope.$broadcast('open', 'Deposit');
    }

    /**
     * @return {string} the selector for the deposit form's first child.
     */
    function _getDepositFormFirstChildSelector() {
      return 'manage-payment-methods .tvg-deposit .before-notification';
    }

    /**
     * Set the select deposit type limits calling the method specific limit endpoint
     * @param {String} depositOptions  Initial deposit options
     * @private
     */
    function _setDepositTypeLimits() {
      var accountId =
        ($rootScope.user && $rootScope.user.accountNumber) ||
        DepositSrv.accountId;
      var depositType =
        $scope.data.selectedPayOption && $scope.data.selectedPayOption.ftype;
      var storedLimits;
      var useUwtForDepositLimitsOnDma = angular.isDefined(
        $rootScope.activeFeatures.useUwtForDepositLimitsOnDma
      ) ? $rootScope.activeFeatures.useUwtForDepositLimitsOnDma
        : false;

      if (!accountId || !depositType) {
        $scope.data.unableToFetchLimits = true;
        return {};
      }

      if (depositType === 'IBC' || depositType === 'CC' || depositType === 'APPL') {
        if (useUwtForDepositLimitsOnDma) {
          DepositSrv.getDepositLimits(accountId, depositType)
            .then(function (response) {
              processPaymentLimitsServiceResponse(response, depositType, storedLimits);
            })
            .catch(function () {
              $scope.data.unableToFetchLimits = true;
            });
        } else {
          return DepositSrv.getPaymentTypeDepositLimit(accountId, depositType)
            .then(function (response) {
              processPaymentLimitsServiceResponse(response, depositType, storedLimits);
            })
            .catch(function () {
              $scope.data.unableToFetchLimits = true;
            });
        }
      }

      return $q.defer().promise;
    }

    function processPaymentLimitsServiceResponse(response, depositType, storedLimits) {
      $scope.data.tvgLimits = {};
      if (depositType === 'IBC') {
        if (response && response.userLimits) {
          storedLimits = $scope.data.selectedPayOption.paymentLimits[0];
          if (storedLimits) {
            // set user daily limit
            storedLimits.limitInterval.Daily.Effective =
              response.userLimits && response.userLimits.dailyLimit
                ? parseFloat(response.userLimits.dailyLimit.depositLimit)
                : storedLimits.limitInterval.Daily.Effective;
            // set user weekly limit
            storedLimits.limitInterval.Weekly = {
              Effective:
                response.userLimits && response.userLimits.weeklyLimit
                  ? parseFloat(response.userLimits.weeklyLimit.depositLimit)
                  : '4000.00'
            };
            // set user monthly limit
            storedLimits.limitInterval.Monthly.Effective =
              response.userLimits && response.userLimits.monthlyLimit
                ? parseFloat(response.userLimits.monthlyLimit.depositLimit)
                : storedLimits.limitInterval.Monthly.Effective;

            storedLimits.limitInterval.Daily.ShowFuture = false;
            storedLimits.limitInterval.Monthly.ShowFuture = false;

            if (
              response.userLimits.dailyLimit.futureDate &&
              response.userLimits.dailyLimit.futureDepositLimit
            ) {
              storedLimits.limitInterval.Daily.Future =
                response.userLimits.dailyLimit.futureDepositLimit;
              storedLimits.limitInterval.Daily.FutureDateStr = moment(
                response.userLimits.dailyLimit.futureDate
              ).format('MM/DD/YYYY');
              storedLimits.limitInterval.Daily.ShowFuture = true;
            }

            if (
              response.userLimits.monthlyLimit.futureDate &&
              response.userLimits.monthlyLimit.futureDepositLimit
            ) {
              storedLimits.limitInterval.Monthly.Future =
                response.userLimits.monthlyLimit.futureDepositLimit;
              storedLimits.limitInterval.Monthly.FutureDateStr = moment(
                response.userLimits.monthlyLimit.futureDate
              ).format('MM/DD/YYYY');
              storedLimits.limitInterval.Monthly.ShowFuture = true;
            }

            $scope.data.unableToFetchLimits = false;
          }
        }

        if (response && response.tvgLimits) {
          $scope.data.tvgLimits = {
            dailyLimit: parseFloat(response.tvgLimits.dailyLimit.depositLimit),
            weeklyLimit: parseFloat(
              response.tvgLimits.weeklyLimit.depositLimit
            ),
            monthlyLimit: parseFloat(
              response.tvgLimits.monthlyLimit.depositLimit
            )
          };
        }
      }

      if (depositType === 'CC') {
        //eslint-disable-next-line
        var mapCardType = {
          CC: 'Credit',
          DEB: 'Debit',
          CCS: 'CreditSigned',
          DEBS: 'DebitSigned'
        };
        //eslint-disable-next-line
        var tvgLimits = {};
        //eslint-disable-next-line
        var newPaymentLimits = [];
        //eslint-disable-next-line
        var currentLimits = Object.assign(
          [],
          $scope.data.selectedPayOption.paymentLimits
        );

        response.cardLimits.map(function (type) {
          if (!type.limitsResponse.userLimits) {
            $scope.data.unableToFetchLimits = true;
            return {};
          }

          $scope.data.unableToFetchLimits = false;

          currentLimits.map(function (storedType) {
            if (mapCardType[type.cardType] === storedType.typeName) {
              //eslint-disable-next-line
              var userDailyLimit = type.limitsResponse.userLimits.dailyLimit;
              //eslint-disable-next-line
              var userMonthlyLimit =
                type.limitsResponse.userLimits.monthlyLimit;
              //eslint-disable-next-line
              var newStoredType = storedType;

              // set daily limits
              newStoredType.limitInterval.Daily.Effective = parseInt(
                userDailyLimit.depositLimit,
                10
              );
              newStoredType.limitInterval.Daily.ShowFuture = false;
              newStoredType.limitInterval.Monthly.ShowFuture = false;

              newStoredType.limitInterval.Daily.Future = userDailyLimit.futureDepositLimit
                ? parseInt(userDailyLimit.futureDepositLimit, 10)
                : newStoredType.limitInterval.Daily.Future;
              newStoredType.limitInterval.Daily.FutureDate = userDailyLimit.futureDate
                ? userDailyLimit.futureDate
                : newStoredType.limitInterval.Daily.FutureDate;

              if (
                userDailyLimit.futureDate &&
                userDailyLimit.futureDepositLimit
              ) {
                newStoredType.limitInterval.Daily.FutureDateStr = moment(
                  userDailyLimit.futureDate
                ).format('MM/DD/YYYY');
                newStoredType.limitInterval.Daily.ShowFuture = true;
              }

              if (
                userMonthlyLimit.futureDate &&
                userMonthlyLimit.futureDepositLimit
              ) {
                newStoredType.limitInterval.Monthly.FutureDateStr = moment(
                  userMonthlyLimit.futureDate
                ).format('MM/DD/YYYY');
                newStoredType.limitInterval.Monthly.ShowFuture = true;
              }

              // set monthly limits
              newStoredType.limitInterval.Monthly.Effective = parseInt(
                userMonthlyLimit.depositLimit,
                10
              );
              newStoredType.limitInterval.Monthly.Future = userMonthlyLimit.futureDepositLimit
                ? parseInt(userMonthlyLimit.futureDepositLimit, 10)
                : newStoredType.limitInterval.Monthly.Future;
              newStoredType.limitInterval.Monthly.FutureDate = userMonthlyLimit.futureDate
                ? userMonthlyLimit.futureDate
                : newStoredType.limitInterval.Monthly.FutureDate;
              newPaymentLimits.push(newStoredType);
            }

            return storedType;
          });

          // set tvg limits
          $scope.data.tvgLimits[type.cardType] = type.limitsResponse.tvgLimits;

          return type;
        });

        $scope.data.selectedPayOption.paymentLimits = newPaymentLimits;
      }


      if (depositType === 'APPL') {
        if (response && response.limitsUser) {
          storedLimits = $scope.data.selectedPayOption.paymentLimits[0];
          if (storedLimits) {
            // set user daily limit
            storedLimits.limitInterval.Daily.Effective =
              response.limitsEffective && response.limitsEffective.limits.dailyLimit
                ? parseFloat(response.limitsEffective.limits.dailyLimit)
                : storedLimits.limitInterval.Daily.Effective;
            // set user weekly limit
            storedLimits.limitInterval.Weekly = {
              Effective:
                response.limitsEffective && response.limitsEffective.limits.weeklyLimit
                  ? parseFloat(response.limitsEffective.limits.weeklyLimit)
                  : '100000.00'
            };
            // set user monthly limit
            storedLimits.limitInterval.Monthly.Effective =
              response.limitsEffective && response.limitsEffective.limits.monthlyLimit
                ? parseFloat(response.limitsEffective.limits.monthlyLimit)
                : storedLimits.limitInterval.Monthly.Effective;

            storedLimits.limitInterval.Daily.ShowFuture = false;
            storedLimits.limitInterval.Monthly.ShowFuture = false;

            if (
              response.limitsFuture.futureDailyDate &&
              response.limitsFuture.limits.dailyLimit
            ) {
              storedLimits.limitInterval.Daily.Future =
                response.limitsFuture.limits.dailyLimit;
              storedLimits.limitInterval.Daily.FutureDateStr = moment(
                response.limitsFuture.futureDailyDate
              ).format('MM/DD/YYYY');
              storedLimits.limitInterval.Daily.ShowFuture = true;
            }

            if (
              response.limitsFuture.futureMonthlyDate &&
              response.limitsFuture.limits.monthlyLimit
            ) {
              storedLimits.limitInterval.Monthly.Future =
                response.limitsFuture.limits.monthlyLimit;
              storedLimits.limitInterval.Monthly.FutureDateStr = moment(
                response.limitsFuture.futureMonthlyDate
              ).format('MM/DD/YYYY');
              storedLimits.limitInterval.Monthly.ShowFuture = true;
            }

            $scope.data.unableToFetchLimits = false;
          }
        }

        if (response && response.limitsTvg) {
          $scope.data.tvgLimits = {
            dailyLimit: parseFloat(response.limitsTvg.limits.dailyLimit),
            weeklyLimit: parseFloat(
              response.limitsTvg.limits.weeklyLimit
            ),
            monthlyLimit: parseFloat(
              response.limitsTvg.limits.monthlyLimit
            )
          };
        }
      }
    }

    /**
     * Set user ach accounts on file
     * @private
     */
    function _setUserCardsOnFile() {
      if ($scope.data.selectedPayOption.ftype !== 'CC') {
        return {};
      }
        //eslint-disable-next-line
        var accountId =
          ($rootScope.user && $rootScope.user.accountNumber) ||
          DepositSrv.accountId;
      if (!accountId) {
        $scope.data.unableToFetchCardsOnFile = true;
        return {};
      }
      $scope.data.fetchingInfo = true;
      DepositSrv.getCardsOnFile(accountId)
          .then(function (data) {
            var optionsOnFile = [];
            if (data.CardList && data.CardList.length > 0) {
              angular.forEach(data.CardList, function (card) {
                optionsOnFile.push({
                  groupName: 'Cards On File',
                  id: card.cardId,
                  cardNumber: card.cardNumber,
                  cardNumberExt: '************' + card.cardNumber,
                  cardTypeId: DepositInitialDataFac.getCardType(card.cardType)
                    .id,
                  limitTypeId: DepositInitialDataFac.getDepositLimitType(
                    card.cardType
                  ).id,
                  expirationDate: card.expDate,
                  isExpired:
                    moment(card.expDate, 'MM/YY').add(1, 'month') < moment(),
                  signed: card.signed,
                  name:
                    '(************' +
                    card.cardNumber +
                    ') ' +
                    card.cardType +
                    ' ' +
                    card.expDate,
                  ftype: 'CC',
                  type: DepositInitialDataFac.getCardType(card.cardType).abbr,
                  typeName: card.cardType,
                  cardType: card.cardType,
                  min: DepositInitialDataFac.getLimitType(
                    card.DepositLimitTypeId,
                    'min'
                  ),
                  max: DepositInitialDataFac.getLimitType(
                    card.DepositLimitTypeId,
                    'max'
                  ),
                  depositTypeId: DEPOSIT_TYPES.CARD_ON_FILE
                });
              });
            }

            $scope.data.unableToFetchCardsOnFile = false;
            $scope.data.selectedPayOption.onFile = optionsOnFile;
          })
          .catch(function () {
            $scope.data.unableToFetchCardsOnFile = true;
          })
          .finally(function () {
            $scope.data.fetchingInfo = false;
          });

      return {};
    }

    /**
     * Set user ach accounts on file
     * @private
     */
    function _setUserBankAccounts() {
      var accountId =
        ($rootScope.user && $rootScope.user.accountNumber) ||
        DepositSrv.accountId;
      if (!accountId) {
        $scope.data.unableToFetchBankAccounts = true;
        return {};
      }

      if ($scope.data.selectedPayOption.ftype !== 'IBC' &&
        $scope.data.selectedPayOption.ftype !== 'ACH') {
        return {};
      }
      $scope.data.loading = true;
      return DepositSrv.getUserBankAccounts(accountId)
        .then(function (data) {
          var optionsOnFile = [];
          if (data.bankAccounts && data.bankAccounts.length > 0) {
            angular.forEach(data.bankAccounts, function (ach) {
              optionsOnFile.push({
                groupName: 'BetCash Accounts On File',
                achId: ach.id,
                bankAccNumber: ach.accountNumber,
                bankAcctType: ach.accountType,
                bankName: ach.name,
                bankRoutingNumber: ach.routingNumber,
                driversLicenseNumber: ach.dlNumber,
                driversLicenseState: ach.dlState,
                name:
                  '(*****' +
                  ach.accountNumber.substr(ach.accountNumber.length - 4) +
                  ') ' +
                  ach.name,
                ftype: 'ACH',
                type: 'ACH',
                isPending: false,
                typeName: 'BetCash',
                isAvailable: true,
                cardType: undefined,
                limitTypeId: false,
                min: false,
                max: false
              });
            });
          }

          $scope.data.unableToFetchBankAccounts = false;
          $scope.data.selectedPayOption.onFile = optionsOnFile;
        })
        .catch(function () {
          $scope.data.unableToFetchBankAccounts = true;
        })
        .finally(function () {
          $scope.data.loading = false;
        });
    }

    /**
     * Fills data object with:
     *  - States
     *  - New deposit options (NEW)
     *  - Deposit options on file (STORED)
     *  - Deposit forms object
     *
     * Sets default deposit option to the first in STORED option
     */

    if (!$rootScope.loadedInitData) {
      $scope.data.loading = true;
      $scope.events.getPayMethodsInitialData(
      $rootScope.activePaymentMngTab ? $rootScope.activePaymentMngTab : null
    );
      $scope.njxIntegration =
      ConfigurationFac.getApplicationContextItem('product') === 'njx';
    }

    init();
  }

  angular
    .module('TVG.ManagePaymentMethods')
    .controller(
      'ManagePaymentMethodsController',
      ManagePaymentMethodsController
    );
}());

(function () {
  'use strict';

  PayNearMeController.$inject = ['$scope', 'PayNearMeFac', '$sce', '$filter', 'NotificationService', 'ApiDepositsGTMFac', 'ConfigurationFac', 'DepositSrv', '$uibModal', '$templateCache', 'ModalDialogService'];
  function PayNearMeController($scope, PayNearMeFac, $sce, $filter,
                               NotificationService, ApiDepositsGTMFac,
                               ConfigurationFac, DepositSrv,
                               $uibModal, $templateCache, ModalDialogService) {
    $scope.data = {
      userPnmId: null,
      loading: true,
      showPnmIframe: false,
      orderTrackingUrl: '',
      payNearMeLogoUrl: $filter('CMSValue')('pnmLogo'),
      familyDollarLogoUrl: $filter('CMSValue')('pnmFamilyDollarLogo'),
      sevenElevenLogoUrl: $filter('CMSValue')('pnmSevenElevenLogo'),
      currentUserAccount: DepositSrv.user.get('accountNumber'),
      genericErrorMessage: $filter('CMSValue')('pnmGenericErrorMessage')
    };

    $scope.events = {
      getPayNearMeId: _getPayNearMeId,
      createPayNearMeId: _createPayNearMeId,
      toggleFaq: _toggleFaq,
      toggleLocations: _toggleLocations
    };

    function _getPayNearMeId() {
      $scope.data.loading = true;
      if (!$scope.data.currentUserAccount) {
        $scope.data.loading = false;
        _displayErrorDialog($scope.data.genericErrorMessage);
      } else {
        PayNearMeFac.getPayNearMeId($scope.data.currentUserAccount)
          .then(function (response) {
            $scope.data.userPnmId = response.data.payNearMeId;
            $scope.data.orderTrackingUrl =
              $sce.trustAsResourceUrl(response.data.orderTrackingUrl);
            $scope.data.showPnmIframe = true;
          })
          .catch(function (error) {
            if (error.status !== 404) {
              _displayErrorDialog($scope.data.genericErrorMessage);
            }
          })
          .finally(function () {
            $scope.data.loading = false;
          });
      }
    }

    function _createPayNearMeId() {
      _createGtmEvent();
      if (!$scope.data.currentUserAccount) {
        $scope.data.loading = false;
        _displayErrorDialog($scope.data.genericErrorMessage);
      } else {
        $scope.data.loading = true;

        PayNearMeFac.createPayNearMeId($scope.data.currentUserAccount)
          .then(function (response) {
            $scope.data.userPnmId = response.data.payNearMeId;
            $scope.data.orderTrackingUrl =
              $sce.trustAsResourceUrl(response.data.orderTrackingUrl);
            $scope.data.showPnmIframe = true;
          }).catch(function () {
            _displayErrorDialog($scope.data.genericErrorMessage);
          })
          .finally(function () {
            $scope.data.loading = false;
          });
      }
    }

    function _toggleFaq() {
      return ModalDialogService.openLarge(
        $filter('CMSValue')('pnmFaqTitle'),
        $filter('CMSValue')('pnmFaqTemplate')
      );
    }

    function _toggleLocations() {
      /* eslint-disable */
      $scope.locationsModal = $uibModal.open({
        template: $templateCache.get('src/templates/deposit/types/payNearMe/locations-modal.html'),
        windowTemplateUrl: 'js/common/modules/Utilities/templates/modal-window.html',
        backdropClass: 'tvgmodal-backdrop',
        windowClass: 'paynearme-locations',
        scope: $scope
      });
      /* eslint-enable */
    }

    function _displayErrorDialog(errorMessage) {
      NotificationService.error('Error', errorMessage,
        '.payNearMe__container .before-notification');
    }

    (function init() {
      _getPayNearMeId();
    }());

    /**
     * Modal $scope values
     */
    $scope.locationsTemplate = '<iframe src="' +
      $filter('CMSValue')('pnmLocationsPageUrl') + '"> </iframe>';

    $scope.closeLocationsModal = function () {
      $scope.locationsModal.close();
    };

    /**
     * GTM EVENTS
     */
    function _createGtmEvent() {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        eventLabel: 'Create PayNearMe PayCode',
        gaEventCategory: 'Site Click',
        gaEventAction: 'Deposit Click',
        gaEventLabel: 'Deposit-Click PayNearMe create pay code button ',
        productVersion:
          ApiDepositsGTMFac.getProduct(ConfigurationFac.getApplicationContextItem('product')),
        screenName: ApiDepositsGTMFac.tvg4ScreenName(),
        sectionName: ApiDepositsGTMFac.tvg4SectionName(),
        siteVersion:
          ApiDepositsGTMFac.getSiteVersion(ConfigurationFac.getApplicationContextItem('product')),
        accountId: DepositSrv.user.get('accountNumber')
      });
    }
  }

  angular // eslint-disable-line
    .module('TVG.Deposit')
    .controller('PayNearMeCtrl', PayNearMeController);
}());

(function () {
  'use strict';

  SightlineController.$inject = ['$q', '$scope', '$rootScope', '$filter', 'DepositSrv', 'NotificationService', 'SightlineSrv', 'ApiDepositsGTMFac', 'ConfigurationFac', 'ModalDialogService'];
  function SightlineController($q,
            $scope,
            $rootScope,
            $filter,
            DepositSrv,
            NotificationService,
            SightlineSrv,
            ApiDepositsGTMFac,
            ConfigurationFac,
            ModalDialogService) {
    /**
     * Holds account info, available options, selected options and
     * interface flags
     */
    $scope.data = {
      areTermsAccepted: false,
      isEnrollingCard: false
    };

    /**
     * PUBLIC methods
     */
    $scope.events = {
      toggleSightlineTerms: _toggleSightlineTerms,
      openModals: _openModals,
      enrolCard: _enrolCard
    };

    /**
     * Set/unset sightline terms flag
     * @param  {Boolean} val  Whether the terms are accepted
     * @return {Boolean}      Value set to the terms
     */
    function _toggleSightlineTerms(val) {
      $scope.data.areTermsAccepted = val;
      return $scope.data.areTermsAccepted;
    }

    /**
     * Send GTM event when user clicks enrollment button
     */
    function _sendEnrollClickGTM() {
      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        eventLabel: 'MyFunds-SightlineEnrollmentClick',
        gaEventCategory: 'Deposit',
        gaEventAction: 'Site Click',
        gaEventLabel: 'MyFunds | Sightline Enrollment Click',
        screenName: ApiDepositsGTMFac.tvg4ScreenName(),
        sectionName: ApiDepositsGTMFac.tvg4SectionName(),
        siteVersion: ConfigurationFac
          .getSiteVersion(DepositSrv.getApplicationContextItem('application')),
        accountId: DepositSrv.user.get('accountNumber')
      });
    }

    /**
     * Send GTM event when user enrollment is successful
     */
    function _enrollSuccessGTM() {
      ApiDepositsGTMFac.sendGTMEvent('SightlineEnrollment', {
        eventLabel: 'SightlineEnrollmentSuccess',
        gaEventCategory: 'Deposit',
        gaEventAction: 'Sightline Enrollment Success',
        gaEventLabel: 'MyFunds | Sightline Enrollment Success"',
        screenName: ApiDepositsGTMFac.tvg4ScreenName(),
        sectionName: ApiDepositsGTMFac.tvg4SectionName(),
        siteVersion: ConfigurationFac
          .getSiteVersion(DepositSrv.getApplicationContextItem('application')),
        accountId: DepositSrv.user.get('accountNumber')
      });
    }

    /**
     * Send GTM event when user enrollment fails
     */
    function _enrollErrorGTM(errorMsg) {
      ApiDepositsGTMFac.sendGTMEvent('SightlineEnrollment', {
        eventLabel: 'SightlineEnrollmentError',
        errorType: 'Sightline Enrollment Error',
        errorMessage: errorMsg,
        gaEventAction: 'Sightline Enrollment Failed',
        gaEventCategory: 'Deposit',
        gaEventLabel: 'MyFunds | Sightline Enrollment Error',
        screenName: ApiDepositsGTMFac.tvg4ScreenName(),
        sectionName: ApiDepositsGTMFac.tvg4SectionName(),
        siteVersion: ConfigurationFac
          .getSiteVersion(DepositSrv.getApplicationContextItem('application')),
        accountId: DepositSrv.user.get('accountNumber')
      });
    }
    /**
     * Enroll user's sightline card in TVG
     * @return {Promise}
     */
    function _enrolCard() {
      var noTerms = 'You must accept terms before enrolling card.';
      var pending = 'Enrolling card request is pending.';
      var context = _getDepositFirstChildSelector();

      if (!$scope.data.areTermsAccepted) {
        NotificationService
          .error('Error!', noTerms, context);
        return $q.reject({
          code: 'missing_required_terms',
          message: noTerms
        });
      }

      if ($scope.data.isEnrollingCard) {
        NotificationService
          .error('Error!', noTerms, context);
        return $q.reject({
          code: 'pending_requests',
          message: pending
        });
      }

      _sendEnrollClickGTM();
      $scope.data.isEnrollingCard = true;
      return SightlineSrv.enrollSightlineUser($scope.data.areTermsAccepted)
        .then(function () {
          _enrollSuccessGTM();
          $rootScope.$emit('sightlineUserEnrolled');
        })
        .catch(function (error) {
          var cmsError = $filter('CMSValue')('sightlineEnrollmentFailed');
          var errorMsg = (error || {}).message || cmsError;
          NotificationService
            .error('Error!', cmsError, context);
          _enrollErrorGTM(errorMsg);
        })
        .finally(function () {
          $scope.data.isEnrollingCard = false;
        });
    }

    /**
     * Open Sightline Modals
     *
     * @param  {String} titleCMSKey  CMS key for the modal header text
     * @param  {String} bodyCMSKey   CMS key for the modal body text
     * @return {Object}
     */
    function _openModals(titleCMSKey, bodyCMSKey) {
      return ModalDialogService.openLarge(
        $filter('CMSValue')(titleCMSKey),
        $filter('CMSValue')(bodyCMSKey)
      );
    }

    /**
     * Get the current sightline context 'deposit' or 'withdraw'
     *
     * $scope.sightlineContext is inherited from the parent controller
     * (DepositCtrl.js or WithdrawCtrl.js)
     *
     * @return {String}
     */
    function _getDepositFirstChildSelector() {
      var parentContextSelector = $scope.sightlineContext || 'deposit';
      var innerElementSelector = ' .tvg-deposit';
      if (parentContextSelector === 'deposit') {
        innerElementSelector += ' .deposit-form deposit-type-selector';
      } else if (parentContextSelector === 'withdraw') {
        innerElementSelector += ' withdraw-type-selector';
      }
      return parentContextSelector + innerElementSelector;
    }
  }

  angular
      .module('TVG.Deposit')
      .controller('SightlineController', SightlineController);
}());

(function () {
  'use strict';

  TransferController.$inject = ['$q', '$scope', '$rootScope', '$timeout', '$location', '$window', '$sce', '$filter', 'TransferSrv', 'NotificationService'];
  function TransferController(
    $q,
    $scope,
    $rootScope,
    $timeout,
    $location,
    $window,
    $sce,
    $filter,
    TransferSrv,
    NotificationService) {
    function _selectSource() {
      if ($scope.transferDataModel.destination
        && $scope.transferDataModel.source.id ===
        $scope.transferDataModel.destination.id) {
        $scope.transferDataModel.destination = undefined;
      }
    }

    function _selectDestination() {
      if ($scope.transferDataModel.source
        && $scope.transferDataModel.destination.id ===
        $scope.transferDataModel.source.id) {
        $scope.transferDataModel.source = undefined;
      }
    }

    function _makeTransfer(form) {
      if (form.$valid) {
        $scope.data.loading = true;

        TransferSrv.makeTransfer({
          source: $scope.transferDataModel.source.name,
          destination: $scope.transferDataModel.destination.name,
          amount: $scope.transferDataModel.amount
        }).then(function (data) {
          var status = data && data.status || 200;
          $scope.$emit('onDepositEventSuccess');
          $rootScope.$broadcast('accountBalance_update');

          if ($scope.transferDataModel.destination.name === 'Tote' &&
            status === 202) {
            NotificationService.warning('Transfer successful!',
            $filter('CMSLabels')(202, 'exwTransferToToteMessages'),
            _getDepositFormFirstChildSelector());
          } else {
            NotificationService.success('Transfer successful!',
              'Success! Your funds have been transferred',
            _getDepositFormFirstChildSelector());
          }

          $scope.transferDataModel.amount = undefined;
          form.$setUntouched();
          form.$setPristine();
          $scope.transferDataModel.source = undefined;
          $scope.transferDataModel.destination = undefined;
          $scope.data.loading = false;
        }, function (data) {
          $scope.$emit('onDepositEventFailure');
          _transferErrorHandler(data);
          $scope.data.loading = false;
        });
      }
    }

    function _transferErrorHandler(response) {
      if (response && response.code) {
        if ($scope.transferDataModel.destination.name === 'Tote') { // To TVG
          handleTransferToTote(response.code);
        } else {
          handleTransferToExchange(response.code);
        }
      }
    }

    function handleTransferToTote(code) {
      var genericMessage = 'We have not been able to complete your transfer at this time.'
      + ' Please call customer service.';
      switch (code) {
        case 139500:
          NotificationService.warning('Unable to complete transfer!',
            $filter('CMSLabels')(code, 'exwTransferToToteMessages') ||
            $filter('CMSLabels')('generic', 'exwTransferToToteMessages') ||
            genericMessage,
            _getDepositFormFirstChildSelector());
          break;
        default:
          NotificationService.error('Unable to complete transfer!',
            $filter('CMSLabels')(code, 'exwTransferToToteMessages') ||
            $filter('CMSLabels')('generic', 'exwTransferToToteMessages') ||
            genericMessage,
            _getDepositFormFirstChildSelector());
          break;
      }
    }

    function handleTransferToExchange(code) {
      NotificationService.error('Unable to complete transfer!',
            $filter('CMSLabels')(code, 'exwTransferToExchangeMessages') ||
            $filter('CMSLabels')('generic', 'exwTransferToExchangeMessages') ||
            'We have not been able to complete your transfer at this time.'
            + ' Please call customer service.',
            _getDepositFormFirstChildSelector());
    }

    $scope.data = {
      availableAmountOptions: [25, 100, 500],
      optionsAccounts: TransferSrv.getOptionsAccounts(),
      loading: true,
      makingTransfer: false,
      errorLoadingData: undefined,
      errorDepositRestrictions: false,
      message: ''
    };

    $scope.events = {
      makeTransfer: _makeTransfer,
      selectSource: _selectSource,
      selectDestination: _selectDestination
    };

    $scope.transferDataModel = {
      isAvailable: true,
      isPending: false,
      amount: undefined,
      source: undefined,
      destination: undefined,
      min: 0,
      max: 999999999
    };

    TransferSrv.getTransferInitialData().then(function () {
      var msg = '';
      $scope.data.errorDepositRestrictions = false;
      $scope.data.loading = false;

      if (TransferSrv.failedSession()) {
        msg = $filter('CMSValue')('transferFailedSession');
        $scope.data.errorDepositRestrictions = true;
        $scope.data.message = msg;
      } else if (TransferSrv.failedContext()) {
        $scope.data.errorDepositRestrictions = true;
        msg = $filter('CMSValue')('transferInitialError');
        $scope.data.message = msg;
      } else if (TransferSrv.failedExchange()) {
        msg = $filter('CMSValue')('transferFailedExchange');
        $scope.data.message = msg;
      }
    });

    /**
     * @return {string} the selector for the deposit form's first child.
     */
    function _getDepositFormFirstChildSelector() {
      return 'transfer .tvg-deposit .deposit-form transfer-amount-input';
    }
  }

  angular.module('TVG.Transfer').controller('TransferController', TransferController);
}());

(function () {
  'use strict';

  WithdrawCancelController.$inject = ['$scope', '$rootScope', '$filter', 'WithdrawFac', 'NotificationService', 'ConfigurationFac', '$location', 'ApiWithdrawGTMFac', 'SightlineSrv', 'Utilities'];
  function WithdrawCancelController($scope, $rootScope, $filter, WithdrawFac, NotificationService,
            ConfigurationFac, $location, ApiWithdrawGTMFac, SightlineSrv, Utilities) {
    $scope.data = {
      withdrawPendingList: [],
      isLoading: false,
      rootData: $rootScope
    };

    getWithdrawPendingList();

    function _getPendingWithdraw(id) {
      var i;

      if (id) {
        for (i = 0; i < $scope.data.withdrawPendingList.length; i++) {
          if (id === $scope.data.withdrawPendingList[i].withdrawalId) {
            return $scope.data.withdrawPendingList[i];
          }
        }
      }

      return {};
    }

    function _cancelGenericPendingWithdrawal(pendingWithdrawal) {
      return WithdrawFac.withdrawCancel(pendingWithdrawal.withdrawalId)
        .then(function (response) {
          // update balance
          if (response.data && response.data.balance) {
            $rootScope.$emit('accountBalance_changed', parseFloat(response.data.balance));
          }
          return [
            (response && ((response[0] && response[0].CancellationSucceeded) ||
            response.data && response.data.hasOwnProperty('balance'))),
            response
          ];
        });
    }

    //eslint-disable-next-line
    function _cancelSightlinePendingWithdraw(pendingWithdrawal) {
      return SightlineSrv.cancelWithdrawal(pendingWithdrawal.withdrawalId)
        .then(function () { return [true]; })
        .catch(function () { return [false]; });
    }

    $scope.cancelPendingWithdraw = function (withdrawId) {
      var pendingWithdraw = _getPendingWithdraw(withdrawId);
      var action = _cancelGenericPendingWithdrawal;

      $scope.data.isLoading = true;
      return action(pendingWithdraw)
        .then(function (data) {
          var myList;
          var myObj;
          var p;
          var _withdrawType;
          var succeeded = data[0];
          var response = data[1];

          if (succeeded) {
            getWithdrawPendingList();
            $scope.$emit('onWithdrawalCancelSuccess', {});
            NotificationService
              .success('Confirmation', 'Your withdrawal has been ' +
                'cancelled and the funds are back in your account',
              _getWithdrawCancelDepositContainerSelector());
          } else {
            NotificationService
              .error('Error', 'Your withdrawal has not been cancelled',
              _getWithdrawCancelDepositContainerSelector());

            $scope.$emit('onWithdrawalCancelError', {});
          }

          if ($scope.data.rootData) {
            myList = $scope.data.withdrawPendingList;
            myObj = function () { // eslint-disable-line
              for (var prop in myList) { // eslint-disable-line
                if (myList[prop].hasOwnProperty('withdrawalId') &&
                  myList[prop].WithdrawalId === withdrawId) {
                  return myList[prop];
                }
              }
            };

            _withdrawType = 'Check';

            if (myObj()) {
              if (myObj().PaymentType === 'CHK') {
                _withdrawType = 'Check';
              } else if (myObj().PaymentType === 'ACH') {
                _withdrawType = 'Bet Cash';
              } else {
                _withdrawType = 'Direct Deposit';
              }
            }

            if ($scope.data.rootData.userSession) {
              p = {
                eventName: 'withdrawCancelled',
                eventScreenName: 'My account|Withdrawal',
                screenName: 'Home',
                accountId: $scope.data.rootData.user.accountNumber,
                accountState: $scope.data.rootData.user.homeAddress ?
                  $scope.data.rootData.user.homeAddress.StateAbbr : '',
                customerStatus: '',
                eventAction: 'Withdrawal Cancellation',
                logged: $scope.data.rootData.userSession,
                withdrawAmount: myObj() ? myObj().Amount : 0,
                withdrawType: _withdrawType
              };
            } else if ($scope.data.rootData && response &&
              response.length && response[0].userData) {
              p = {
                eventName: 'withdrawCancelled',
                eventScreenName: undefined,
                screenName: 'Withdrawal',
                accountId: response[0].userData.customerId,
                accountState: response[0].userData.homeAddress &&
                angular.fromJson(response[0].userData.homeAddress)
                  .StateAbbr ?
                  angular.fromJson(response[0].userData.homeAddress)
                    .StateAbbr : '',
                customerStatus: '',
                eventAction: 'Withdrawal Cancellation',
                logged: 'Logged In',
                withdrawAmount: myObj() ? myObj().Amount : 0,
                withdrawType: _withdrawType,
                siteVersion: 'TVG3'
              };
            }

            if (p) {
              sendGTMCancellationEvent(p);
            }
          }
        })
        .catch(function () {
          NotificationService.error('Error',
            'Your withdrawal has not been cancelled',
            _getWithdrawCancelDepositContainerSelector());
          $scope.$emit('onWithdrawalCancelError', {});
        });
    };

    function getWithdrawPendingList() {
      $scope.data.isLoading = true;
      return WithdrawFac.withdrawPendingList()
        .then(function (response) {
          if (response) {
            $scope.data.withdrawPendingList = response;
            response.forEach(function (item) {
              item.DateInitiated = Utilities.toDateFormat('MM/DD/YYYY', item.transactionDate);
            });
          }
        })
        .catch(function () {
          $scope.data.errorFetchingPending = true;
        })
        .finally(function () {
          $scope.data.isLoading = false;
        });
    }

    function sendGTMCancellationEvent(params) {
      var p = {};
      p.event = params.eventName;
      p.accountId = params.accountId;
      p.residenceState = params.accountState;
      p.customerStatus = '';
      p.gaEventCategory = 'Withdraw';
      p.gaEventAction = params.eventAction;
      p.gaEventLabel = params.withdrawType;
      p.loginStatus = 'Logged In';
      p.registrationStatus = 'Registered';
      p.screenName = params.screenName;
      p.sectionName = params.eventScreenName;
      p.siteVersion = params.siteVersion ? params.siteVersion : 'mobile_web';
      p.withdrawAmount = ApiWithdrawGTMFac
        .gtmCurrencyFormat(params.withdrawAmount);
      p.withdrawType = params.withdrawType;

      ApiWithdrawGTMFac.sendGTMEvent(null, p);
    }

    /**
     * @return {string} the selector for the withdraw cancel deposit container.
     */
    function _getWithdrawCancelDepositContainerSelector() {
      return 'withdraw-cancel .tvg-deposit .before-notification';
    }
  }

  angular.module('TVG.Withdraw').controller('WithdrawCancelController', WithdrawCancelController);
}());

(function () {
  'use strict';

  WithdrawController.$inject = ['$rootScope', '$scope', '$filter', '$sce', '$window', '$q', 'WithdrawFac', 'ConfigurationFac', '$location', 'ApiWithdrawGTMFac', 'NotificationService', 'SightlineSrv', 'UserFactory', 'Utilities', 'FeedbackFac', 'paypalService', 'DepositSrv', 'DepositInitialDataFac', 'DEPOSIT_TYPES'];
  function WithdrawController(
    $rootScope,
    $scope,
    $filter,
    $sce,
    $window,
    $q,
    WithdrawFac,
    ConfigurationFac,
    $location,
    ApiWithdrawGTMFac,
    NotificationService,
    SightlineSrv,
    UserFactory,
    Utilities,
    FeedbackFac,
    paypalService,
    DepositSrv,
    DepositInitialDataFac,
    DEPOSIT_TYPES
  ) {
    var productVersion = ApiWithdrawGTMFac.getProduct(
      ConfigurationFac.getApplicationContextItem('product')
    );
    var device = ConfigurationFac.getApplicationContextItem('device');
    var firstWithdraw;
    var sightlineIframeUrl = ConfigurationFac.getSightline('iframeURL');
    var unbind = [];
    var paymentMethodsNoAddress = ['SLN', 'PAY'];
    var paymentsThreeColumns = ['SLN'];

    var standardWithdrawTypes = {
      ach: 'ACH',
      betcash: 'ACH',
      check: 'CHK',
      sln: 'SLP',
      slp: 'SLP',
      pay: 'PAY',
      debit_card: 'DEB',
      debit: 'DEB'
    };

    var initialTab = $location.search().initialTab;

    var isNative = false;
    if ($rootScope.product) {
      isNative = $rootScope.product.indexOf('native') !== -1;
    }

    /**
     * Holds account info, available options, selected options and
     * interface flags
     */
    $scope.data = {
      withdrawOptions: [],
      cardsOnFile: [],
      fetchedCardsOnFile: false,
      availableCheckOptions: [],
      availableBetCashAccounts: [],
      accountId: 0,
      balance: 0,
      availableBalance: 0,
      forms: WithdrawFac.getForms(),
      selectedWithdrawOption: {},
      selectedAddressSection: {},
      selectedBetCashAccount: {},
      selectedCardOnFile: {},
      isLoading: true, // Show loading indicator
      errorFetchingData: false,
      minWithdraw: 2,
      numberPattern: /^\d*([.]?\d+)$/,
      user: UserFactory.build(), // default empty,
      slnIframeURL: $sce.trustAsResourceUrl(sightlineIframeUrl),
      providerEmail: undefined,
      pageSetFromParams: false
    };

    $scope.sightlineContext = 'withdraw';

    $scope.njxIntegration = ConfigurationFac.getApplicationContextItem('product') === 'njx';
    $scope.isDesktop = device === 'desktop' && ($rootScope.product === 'ios2' || isNative
      || $rootScope.product === 'androidwrapper' || $rootScope.product === 'tvgandroid') ? false
      : device === 'desktop';

    $scope.showPendingWithdrawals = ($rootScope.layout === 'desktop' &&
      $rootScope.activeFeatures.showPendingWithdrawals) ||
      $scope.njxIntegration;

    /**
     * PUBLIC methods
     */
    $scope.events = {
      toggleHomeMailMethods: _toggleHomeMailMethods,
      toggleWithdrawOptions: _toggleWithdrawOptions,
      setCurrentBetCash: _setCurrentBetCash,
      setCurrentCardOnFile: _setCurrentCardOnFile,
      withdraw: _withdraw,
      // canWithdraw: _canWithdraw,
      changeAmount: _changeAmount,
      initDropdown: _initDropdown,
      started: _started
    };

    $scope.displays = {
      isSightlineApiEnrollmentVisible: _isSightlineApiEnrollmentVisible
    };

    /**
     * Withdraw data model
     */
    $scope.withdrawDataModel = {
      amount: '',
      locationId: -1,
      started: false
    };

    firstWithdraw = null;

    function getWithdrawType(type) {
      if (type) {
        return standardWithdrawTypes[type.toLowerCase()];
      }
      return '';
    }

    function _started() {
      var type;
      if (!$scope.withdrawDataModel.started) {
        type = getWithdrawType($scope.data.selectedWithdrawOption.id);
        _sendGTMEvent('withdrawal', {
          eventName: 'widthdrawal',
          eventAction: 'Withdrawal Started',
          logged: true,
          depositType: type,
          module: 'Withdrawal'
        });
        $scope.withdrawDataModel.started = true;
      }
    }

    function _changeAmount(dirty, valid) {
      if (firstWithdraw && dirty && valid) {
        _sendGTMEvent('withdrawStart', {
          eventName: 'withdrawStart',
          eventScreenName: 'My account|Withdrawal',
          gaEventLabel: '',
          eventAction: 'Withdraw Start',
          logged: true,
          withdrawAmount: $scope.withdrawDataModel.amount,
          withdrawType: $scope.data.selectedWithdrawOption &&
            $scope.data.selectedWithdrawOption.name ?
              $scope.data.selectedWithdrawOption.name :
              ''
        });

        firstWithdraw = false;
      }
    }

    /**
     * If is TVG3 show a paragraph and not paypal deposits
     * @return {Boolean}
     */
    function _isTVG3() {
      return ConfigurationFac.getApplicationContextItem('product') === 'tvg' &&
        ConfigurationFac.getApplicationContextItem('application') === 'deposit';
    }

    $scope.payPalTVG3 = function () {
      return _isTVG3() && $scope.data.selectedWithdrawOption.id === 'PAY';
    };

    $scope.payPalNJX = function () {
      return ConfigurationFac.getApplicationContextItem('product') === 'njx' &&
        $scope.data.selectedWithdrawOption.id === 'PAY';
    };

    $scope.showAddressForPayment = function () {
      return paymentMethodsNoAddress.indexOf($scope.data.selectedWithdrawOption.id) > -1;
    };

    $scope.showThreeColumns = function () {
      return paymentsThreeColumns.indexOf($scope.data.selectedWithdrawOption.id) > -1 ||
        ($scope.data.selectedWithdrawOption.id === 'PAY' && !$scope.data.providerEmail);
    };

    $scope.useDebitCardLimit = function (option) {
      return $scope.data.selectedWithdrawOption === option &&
        (option.max < $scope.data.availableBalance ||
          !$scope.data.availableBalance);
    };

    $scope.getMaxWithdrawValue = function () {
      var option;
      if ($rootScope.activeFeatures.limitWithdrawDebitCard) {
        option = _.find($scope.data.withdrawOptions, function (withdrawOption) {
          return withdrawOption.id === 'DEBIT_CARD';
        });
        if ($scope.useDebitCardLimit(option)) {
          return option.max;
        }
      }
      return $scope.data.availableBalance;
    };


    $scope.getInvalidWithdrawalMessage = function (input, min) {
      var message = 'Invalid amount.';
      var minAmount = $filter('CMSLabels')('amountLowerError', 'withdrawLabels');
      var option;
      if (input.$error.max) {
        message = $filter('CMSLabels')('amountGreaterError', 'withdrawLabels');
        if ($rootScope.activeFeatures.limitWithdrawDebitCard) {
          option = _.find($scope.data.withdrawOptions, function (withdrawOption) {
            return withdrawOption.id === 'DEBIT_CARD';
          });
          if ($scope.useDebitCardLimit(option)) {
            message = $filter('CMSLabels')('amountGreaterDebitCardLimit', 'withdrawLabels');
          }
        }
      }

      if (input.$error.min) {
        message = Utilities.supplant(minAmount, {
          minAmount: $filter('currency')(min)
        });
      }

      return message;
    };

    $scope.$on('accountBalance_update', function () {
      _updateBalance();
      if (isNative) {
        if ($window && $window.handleNativeMessages) {
          $window.handleNativeMessages('UPDATE_BALANCE');
        }
      }
    });

    //eslint-disable-next-line
    function _isAchRestricted(achAccounts) {
      return achAccounts.length === 0;
    }

    function _isCheckRestricted() {
      // TODO: implement logic to validate if check is restricted
      return false;
    }

    function _selectOption(opt) {
      var types = {
        SLN: handleSightline,
        DEBIT_CARD: handleDebitCard
      };
      var type = getWithdrawType(opt.id);

      $scope.data.selectedWithdrawOption = opt;

      _sendGTMEvent('withdrawal', {
        eventName: 'withdrawal',
        eventAction: 'Withdrawal Type Selected',
        eventCategory: 'Withdrawal',
        gaEventLabel: type,
        module: 'Withdrawal'
      });

      if (opt.id === 'BETCASH') {
        _setUserBankAccounts();
      }
      return types[opt.id] && types[opt.id]();
    }

    function _shouldShowOption(option) {
      var toggles = {
        BETCASH: !$rootScope.activeFeatures.pawsACH,
        DEBIT_CARD: !$rootScope.activeFeatures.pawsCC,
        CHECK: !$rootScope.activeFeatures.pawsCHK,
        PAY: !$rootScope.activeFeatures.pawsPAY
      };

      // eslint-disable-next-line angular/definedundefined
      return toggles[option] !== undefined && !$rootScope.isFdrApp &&
      $rootScope.activeFeatures.pawsWalletAvailable &&
      $rootScope.shouldShowWallet ? toggles[option] : true;
    }


    /**
     * Update models with withdraw initial data
     */
    function _getInitialData() {
      var cms = $filter('CMSValue');
      var currency = $filter('currency');

      return WithdrawFac.getWithdrawalProfile()
        .then(function (withdrawResponse) {
          var accountNumber = withdrawResponse.accountNumber ||
            WithdrawFac.getPlainAccountId();

          SightlineSrv.setInfo(accountNumber);

          return paypalService
            .getAccountInfo(accountNumber)
            .then(function (paypalResponse) {
              return [withdrawResponse, paypalResponse];
            }).catch(function () {
              return [withdrawResponse, {}];
            });
        })
        .then(function (response) {
          return handleSightline()
            .then(function () {
              return response;
            }).catch(function () {
              return response;
            });
        })
        .then(function (response) {
          var data = response[0];
          var paypalData = response[1];
          var cmsOptions;
          var cmsConfig = Utilities.attempt(function () {
            return angular.fromJson(cms('depositWidthrawAvailableOptions'));
          }, function () {
            return [];
          });

          if (
            $rootScope.activeFeatures.hideSightlineIfNotEnrolled &&
            !$scope.data.hasSightlineAccount
          ) {
            cmsConfig = cmsConfig.filter(function (value) { return value !== 'SLN'; });
          }

          cmsOptions = WithdrawFac.getWithdrawOptions(cmsConfig);

          $scope.data.unableToFetchProfile = false;

          if (data.failure) {
            $scope.data.unableToFetchProfile = true;
            $scope.data.availableBalance = data.response.availableBalance;
            $scope.data.balance = currency(data.response.toteBalance, '$');
          }

          // Paypal tab should only appear if user has made a paypal account
          cmsOptions = cmsOptions.filter(function (method) {
            return (method && method.id && method.id !== 'PAY' || paypalData && paypalData.payerId);
          });

          if (_isCheckRestricted()) {
            cmsOptions = cmsOptions.filter(function (method) {
              return method.id !== 'CHECK';
            });
          }

          //eslint-disable-next-line
          var locationTypes = [];

          if (data && data.homeAddress && data.mailingAddress) {
            locationTypes = [{
              id: 0,
              name: 'Residential Address',
              code: 'RESIDENTIAL',
              address:
          [data.homeAddress.streetNumber, data.homeAddress.address1, data.homeAddress.address2,
            data.homeAddress.city, data.homeAddress.state, data.homeAddress.zipCode]
            .join(' ').replace(/\s{2,}/g, ' ') // remove double whitespace, incase address2 is empty
            },
            {
              id: 1,
              name: 'Mailing Address',
              code: 'MAILING',
              address: [data.mailingAddress.streetNumber, data.mailingAddress.address1,
                data.mailingAddress.address2,
                data.mailingAddress.city, data.mailingAddress.state, data.mailingAddress.zipCode]
            .join(' ').replace(/\s{2,}/g, ' ') // remove double whitespace, incase address2 is empty
            }];
          }

          $scope.data.availableCheckOptions = _.filter(locationTypes, function (location) {
            return location.address !== '' && location.address.trim() !== '';
          });
          $scope.data.withdrawOptions = $scope.data.withdrawOptions.concat(cmsOptions)
          .filter(function (option) {
            return _shouldShowOption(option.id);
          });

          $scope.data.showingFallback = !$scope.data.withdrawOptions.length;
          if ($scope.data.withdrawOptions.length > 0) {
            $scope.data.withdrawOptions.forEach(function (item) {
              item.qalabel = item.name.replace(/ /g, '') + 'Tab';
            });
          }

          // Update account info
          if (data && !data.failure) {
            $scope.data.availableBalance = data.availableBalance;
            $scope.data.balance = currency(data.toteBalance, '$');
            $scope.data.user = UserFactory.build(data);
          }
          $scope.data.accountId = data.accountNumber ||
            WithdrawFac.getPlainAccountId();
          // Update available options and sets a default one
          if (initialTab) {
            _setInitalConfigFromParam();
            _initDropdown('CHECK');
          } else {
            $scope.data.selectedWithdrawOption = $scope.data.withdrawOptions[0];
            $scope.data.selectedAddressSection = {};
            $scope.withdrawDataModel.locationId = -1;
          }
          $scope.data.minWithdraw = parseFloat(cms('minWithdrawAmount')) || 2;
          $scope.data.providerEmail = _.get(paypalData, 'email');

          _sendGTMEvent('ga_pageload', {
            accountId: $scope.data.accountId,
            page: $window.location.pathname,
            privateBrowser: localStorage.getItem('privateMode') === 'true' ? 'Yes' : 'No',
            productVersion: productVersion,
            screenName: 'Withdrawal',
            sectionName: 'Withdrawal',
            appVersion: $rootScope.appVersion,
            eventName: 'ga_pageload',
            eventScreenName: 'My account|Withdrawal',
            customerStatus: '',
            eventAction: 'Withdrawal Page Load',
            logged: $scope.data.user.has('accountNumber'),
            module: 'Withdrawal'
          });
        })
        .then(_setUserBankAccounts)
        .then(_setUserCardsOnFile)
        .then(function () {
          var slnOption = $scope.data.withdrawOptions.filter(function (option) {
            return (option.id === 'SLN');
          });

          if (slnOption.length && $scope.fromOption === 'SLN') {
            _toggleWithdrawOptions(slnOption[0]);
          }
        })
        .catch(function () {
          _sendGTMEvent(null, {
            eventName: 'withdrawalError',
            eventScreenName: 'My account|Withdrawal',
            customerStatus: '',
            eventAction: 'Withdrawal Error',
            logged: $scope.data.user.has('accountNumber'),
            withdrawAmount: '',
            withdrawType: '',
            errorType: 'Withdrawal Error',
            errorMessage: 'Failed to load necessary withdrawal data from server.',
            module: 'Withdrawal'
          });

          $scope.data.errorFetchingData = true; // Show error
        })
        .finally(function () {
          if ($scope.data.selectedWithdrawOption.id !== 'DEBIT_CARD') {
            $scope.data.isLoading = false; // Hide loading indicator
          }
        });
    }

    function handleSightline() {
      if ($scope.data.unableToFetchProfile) {
        return {};
      }
      $scope.data.sightlineAccount = SightlineSrv.createSightlineAccount($scope.data.user);

      $scope.sightlineLoading = true;
      return SightlineSrv
        .isSightlineUser($scope.data.sightlineAccount)
        .then(function (user) {
          $scope.data.hasSightlineAccount = user.enrolled || user.exists;
          $scope.data.sightlineAccount.last4SSN = user.last4SSN || '0000';

          return (!user.enrolled);
        })
        .finally(function () {
          $scope.sightlineLoading = false;
        });
    }

    function handleDebitCard() {
      if (!$scope.data.fetchedCardsOnFile) {
        $scope.data.isLoading = true;
      }
    }

    /**
     * Toggles between Residential and Mail CHECK types
     * @param method
     * @private
     */
    function _toggleHomeMailMethods(method) {
      $scope.withdrawDataModel.locationId = method && method.id;
      $scope.data.selectedAddressSection = method;
    }

    function _resetNotification() {
      NotificationService.clearBanner();
    }

    /**
     * Toggles between CHECK and BetCash options
     * @param option - current option
     * @private
     */
    function _toggleWithdrawOptions(option) {
      var amount = $scope.withdrawDataModel.amount;
      var i;
      _resetNotification();

      $scope.data.selectedWithdrawOption = option;
      $scope.withdrawDataModel = {
        amount: amount
      };

      if ($scope.data.withdrawOptions &&
        $scope.data.withdrawOptions.length) {
        for (i = 0; i < $scope.data.withdrawOptions.length; i++) {
          if (option.id === $scope.data.withdrawOptions[i].id) {
            $scope.withdrawDataModel.locationId = $scope.data.selectedAddressSection.id;
          }
        }
      }

      _selectOption(option);
    }

    /**
     * Updates selected betCash account and update withdraw data model
     * @param betCashAccount - selected betCash option
     * @private
     */
    function _setCurrentBetCash(betCashAccount) {
      $scope.data.selectedBetCashAccount = betCashAccount;
      $scope.withdrawDataModel.betCashId = betCashAccount && betCashAccount.achId;

      // Useful for emitting messages
      $scope.withdrawDataModel.bankName = betCashAccount && betCashAccount.bankName;
    }

    /**
     * Select credit for withdraw
     * @param card
     * @private
     */
    function _setCurrentCardOnFile(card) {
      if (card && card.id) {
        $scope.data.selectedCardOnFile = card;
        $scope.withdrawDataModel.ccid = card.id;
      }
    }

    /**
     * Withdraw type chooser
     *
     * @param {Object}  form
     * @param {Boolean} form.$valid  Is form valid?
     * @private
     */
    function _withdraw(form) {
      var option = $scope.data.selectedWithdrawOption.id;
      var options = {
        BETCASH: _withdrawBetCashNewFlow,
        DEBIT_CARD: _withdrawDebitCard,
        CHECK: _withdrawCheck,
        SLN: _withdrawSightlineNewFlow,
        PAY: _withdrawPaypal
      };
      var depositType = getWithdrawType($scope.data.selectedWithdrawOption.id);
      var withdrawMethod = options[option];
      var label;
      var formAmount;
      var newAmount;
      if (form && form.amount && form.amount.$viewValue) {
        formAmount = form.amount.$viewValue;
      }
      if (form && form.newAmount && form.newAmount.$viewValue) {
        newAmount = form.newAmount.$viewValue;
      }

      _sendGTMEvent('withdrawal', {
        eventName: 'withdrawal',
        eventAction: 'Withdrawal Attempt',
        depositType: depositType,
        module: 'Withdrawal'
      });

      if ($scope.data.selectedWithdrawOption.id === 'DEBIT_CARD'
        && $scope.data.cardsOnFile.length === 0) {
        _sendGTMEvent(null, {
          eventName: 'withdrawal',
          customerStatus: '',
          eventAction: 'Withdrawal Error',
          logged: true,
          gaEventLabel: 'No Eligible visa debit on file',
          depositAmount: formAmount || newAmount,
          depositType: depositType,
          module: 'Withdrawal'
        });
      }
      if (!form.$valid) {
        label = _.get(document.querySelector('.js-error-label'), 'innerText', ''); //eslint-disable-line
        _sendGTMEvent(null, {
          eventName: 'withdrawal',
          customerStatus: '',
          eventAction: 'Withdrawal Error',
          logged: true,
          gaEventLabel: label,
          depositAmount: formAmount || newAmount,
          depositType: depositType,
          module: 'Withdrawal'
        });

        FeedbackFac.scrollIntoFirstError();
      } else {
        firstWithdraw = true;
        $scope.data.isLoading = true;

        return withdrawMethod()
          .then(function (withdrawalResult) {
            _updatePendingWithdrawals(withdrawalResult);
          })
          .then(function () {
            _clearAmount(form);
          })
          .then(function () {
            if (option === 'BETCASH') { _setUserBankAccounts(); }
          })
          .finally(function () {
            $scope.data.isLoading = false;
          });
      }

      return null;
    }

    function _clearAmount(form) {
      $scope.data.selectedBetCashAccount = undefined;
      $scope.withdrawDataModel.amount = null;
      if (form.$dirty) {
        form.$setUntouched();
        form.$setPristine();
      }
    }

    /**
     * Init the dropdown and set the first value in it
     * to the defaukt value so that an empty option is not created
     * @param {String}  Name of withdraw option
     * @public
     */

    function _initDropdown(option) {
      var i = 0;
      var checkOptionArray;
      var checkOption;
      var paramPaymentId;
      var cardFromParamsFound;
      var paramPaymentAddress;
      var paramAchId;
      var betCashAccountFromParam;

      switch (option) {
        case 'BETCASH':
          paramAchId = $location.search().paymentId;
          if ($scope.data.pageSetFromParams && paramAchId) {
            betCashAccountFromParam = $scope.data.availableBetCashAccounts.find(
              function (account) {
                return account.achId.toString() === paramAchId;
              }
            );
            if (betCashAccountFromParam) {
              _setCurrentBetCash(betCashAccountFromParam);
            }
          }

          if (!betCashAccountFromParam) {
            _setCurrentBetCash($scope.data.availableBetCashAccounts[0]);
          }
          break;
        case 'CHECK':
          paramPaymentAddress = _.get(
            $location.search(),
            'paymentId',
            ''
          ).toUpperCase();
          checkOptionArray = _.get($scope, 'data.availableCheckOptions', []);
          checkOption = checkOptionArray[0];

          for (i; i < checkOptionArray.length; i++) {
            if (checkOptionArray[i].code === 'MAILING') {
              checkOption = checkOptionArray[i];
              if (!$scope.data.pageSetFromParams) {
                break;
              }
            }
            if (
              $scope.data.pageSetFromParams &&
              paramPaymentAddress &&
              checkOptionArray[i].code === paramPaymentAddress
            ) {
              checkOption = checkOptionArray[i];
              break;
            }
          }
          _toggleHomeMailMethods(checkOption);
          break;
        case 'DEBIT_CARD':
          paramPaymentId = $location.search().paymentId;

          if ($scope.data.pageSetFromParams && paramPaymentId) {
            cardFromParamsFound = $scope.data.cardsOnFile.find(function (card) {
              return card.id.toString() === paramPaymentId;
            });
            if (cardFromParamsFound) {
              _setCurrentCardOnFile(cardFromParamsFound);
            }
          }

          if (!cardFromParamsFound) {
            _setCurrentCardOnFile($scope.data.cardsOnFile[0]);
          }
          break;
        default:
          break;
      }
    }

    /**
     * Withdraws using Check type
     * @private
     */
    function _withdrawCheck() {
      var msg = $filter('CMSLabels')('withdraw-check-success', 'dmaDepositLabels');
      var locationId = $scope.withdrawDataModel.locationId;
      var message = $filter('CMSLabels')('no-address', 'dmaDepositLabels');

      if (_.isNumber(locationId) && locationId !== -1) {
        return WithdrawFac.withdrawCheck(
          $scope.withdrawDataModel.amount,
          $scope.data.accountId,
          _.get($scope, 'data.selectedAddressSection.code', '')
        )
        .then(function (response) {
          var data = response.data;
          var serviceErrorMessage = _.get(response, 'data.message', '');
          if (response.status === 200) {
            if (response.data && response.data.balance) {
              $rootScope.$emit('accountBalance_changed', parseFloat(response.data.balance));
            }

            notifyWithdrawSuccess({
              type: 'check',
              message: Utilities.supplant(msg, {
                amount: $filter('currency')($scope.withdrawDataModel.amount)
              })
            });

            return {
              DateInitiated: moment(data.checkWithdrawalDetails.transactionDate).format('MM/DD/YYYY'),
              amount: parseFloat(data.checkWithdrawalDetails.amount),
              paymentType: 'CHK',
              transactionDate: data.checkWithdrawalDetails.transactionDate,
              transactionUUID: data.checkWithdrawalDetails.UUID,
              withdrawalId: data.checkWithdrawalDetails.UUID
            };
          }
          notifyWithdrawFailure({ type: 'check', serviceErrorMessage: serviceErrorMessage });
          return {};
        })
        .catch(function (response) {
          var serviceErrorMessage = _.get(response, 'data.message', '');
          return notifyWithdrawFailure({
            type: 'check',
            logged: response && (
              response.errorMessage &&
              response.errorMessage === 'ApiMissingUserSessionToken' ||
              response.errorMessage === 'ApiUserSessionTimedOut' ||
              response.errorMessage === 'ApiUserSessionNotFound'
            ),
            serviceErrorMessage: serviceErrorMessage
          });
        });
      }

      return NotificationService.error('Error!', message,
          _getWithdrawDepositContainerFirstChildSelector());
    }

    /**
     * Withdraws using Sightline New Flow
     * @private
     */
    function _withdrawSightlineNewFlow() {
      var option = $scope.data.selectedWithdrawOption.id;
      var msg = $filter('CMSLabels')('withdraw-sightline-success', 'dmaDepositLabels');
      option = option === 'SLN' ? 'SLP' : option;
      return SightlineSrv
          .transferToSightline($scope.withdrawDataModel.amount)
          .then(function (data) {
            if (data.data && data.data.balance) {
              $rootScope.$emit('accountBalance_changed', parseFloat(data.data.balance));
            }
            notifyWithdrawSuccess({
              type: option,
              message: Utilities.supplant(msg, {
                for: $filter('currency')($scope.withdrawDataModel.amount)
              })
            });
            return data.data ? data.data.slpWithdrawalDetails : {};
          })
        .catch(function (response) {
          var serviceErrorMessage = _.get(response, 'data.message', '');
          return notifyWithdrawFailure({
            type: option,
            serviceErrorMessage: serviceErrorMessage
          });
        });
    }

    /**
     * Withdraws using debit card flow
     */
    function _withdrawDebitCard() {
      var msg = $filter('CMSLabels')('withdraw-debit-success', 'dmaDepositLabels');
      if ($scope.withdrawDataModel.ccid) {
        return WithdrawFac.withdrawDebitCard(
          $scope.withdrawDataModel.amount, $scope.data.accountId, $scope.withdrawDataModel.ccid)
          .then(function (data) {
            if (data.data && data.data.balance) {
              $rootScope.$emit('accountBalance_changed', parseFloat(data.data.balance));
            }
            notifyWithdrawSuccess({
              type: 'debit',
              message: Utilities.supplant(msg, {
                for: $filter('currency')($scope.withdrawDataModel.amount),
                to: $scope.withdrawDataModel.ccid
              })
            });
            return data.data ? data.data : {};
          }).catch(function (response) {
            var serviceErrorMessage = _.get(response, 'data.message', '');
            return notifyWithdrawFailure({
              type: 'debit',
              serviceErrorMessage: serviceErrorMessage
            }, response);
          });
      }

      return NotificationService.error('Error!',
        'No debit cards available to withdrawal',
        _getWithdrawDepositContainerFirstChildSelector());
    }

    /**
     * Withdraws using BetCash new flow
     * @private
     */
    function _withdrawBetCashNewFlow() {
      var msg = $filter('CMSLabels')('withdraw-betcash-success', 'dmaDepositLabels');
      if ($scope.withdrawDataModel.betCashId) {
        return WithdrawFac.withdrawBetcashNewDepositFlow(
          $scope.withdrawDataModel.amount, $scope.data.accountId,
            $scope.withdrawDataModel.betCashId)
        .then(function (data) {
          if (data.data && data.data.balance) {
            $rootScope.$emit('accountBalance_changed', parseFloat(data.data.balance));
          }
          notifyWithdrawSuccess({
            type: 'ach',
            message: Utilities.supplant(msg, {
              for: $filter('currency')($scope.withdrawDataModel.amount),
              to: $scope.withdrawDataModel.bankName
            })
          });
          return data.data ? data.data.achWithdrawalResult : {};
        }).catch(function (response) {
          var serviceErrorMessage = _.get(response, 'data.message', '');
          return notifyWithdrawFailure({
            type: 'ach',
            logged: response && (response.errorMessage &&
            response.errorMessage === 'ApiMissingUserSessionToken' ||
            response.errorMessage === 'ApiUserSessionTimedOut' ||
            response.errorMessage === 'ApiUserSessionNotFound'),
            serviceErrorMessage: serviceErrorMessage
          });
        });
      }

      return NotificationService.error('Error!',
        'No BetCash Account selected',
          _getWithdrawDepositContainerFirstChildSelector());
    }

    function _withdrawPaypal() {
      var msg = $filter('CMSLabels')('withdraw-paypal-success', 'dmaDepositLabels');

      return WithdrawFac.withdrawPaypal(
        $scope.withdrawDataModel.amount,
        $scope.data.accountId
      )
        .then(function (response) {
          notifyWithdrawSuccess({
            type: 'PAY',
            message: Utilities.supplant(msg, {
              for: $filter('currency')($scope.withdrawDataModel.amount)
            })
          });

          return response;
        })
        .then(function (withdraw) {
          $rootScope.$emit('accountBalance_changed', parseFloat(withdraw.balance));

          return {
            DateInitiated: moment(withdraw.payWithdrawalDetails.transactionDate).format('MM/DD/YYYY'),
            amount: parseFloat(withdraw.payWithdrawalDetails.amount),
            paymentType: 'PAY',
            transactionDate: withdraw.payWithdrawalDetails.transactionDate,
            transactionUUID: withdraw.payWithdrawalDetails.UUID,
            withdrawalId: withdraw.payWithdrawalDetails.UUID
          };
        })
        .catch(function (response) {
          var serviceErrorMessage = _.get(response, 'data.message', '');
          return notifyWithdrawFailure({
            type: 'PAY',
            serviceErrorMessage: serviceErrorMessage
          });
        });
    }

    function notifyWithdrawSuccess(options) {
      var type = getWithdrawType(options.type);
      $scope.$emit('onDepositEventSuccess');
      $rootScope.$broadcast('accountBalance_update');
      NotificationService.success('Success!', options.message,
        _getWithdrawDepositContainerFirstChildSelector());

      _sendGTMEvent(null, {
        eventName: 'withdrawal',
        eventScreenName: 'My account|Withdrawal',
        customerStatus: '',
        eventAction: 'Withdrawal Success',
        logged: true,
        depositAmount: $scope.withdrawDataModel.amount,
        depositType: type,
        module: 'Withdrawal'
      });
    }

    function notifyWithdrawFailure(options, response) {
      var message;
      var errorObj;
      var errorMessage;
      var responseCode = _.get(response, 'data.code', null);
      var serviceErrorMessage = _.get(options, 'serviceErrorMessage', '');
      var type = getWithdrawType(options.type);

      if (responseCode) {
        message = _.attempt(function () {
          return $filter('CMSLabels')(responseCode, 'depositErrorCodes');
        });
      }

      errorObj = {
        type: options.type,
        title: 'This method of withdrawal doesn\'t seem to be going through.',
        text: message && !_.isError(message) ? message : [
          'Please',
          '<a target="_blank" href=\'/redirectengine?type=messageus\'>contact our customer services</a>',
          'and we\'ll work as fast as we can to help you.'
        ].join(' ')
      };
      errorMessage = '<strong>{title}</strong><br/>{text}';
      $scope.$emit('onDepositEventFailure');

      NotificationService.error(
        'Error!',
        Utilities.supplant(errorMessage, errorObj),
        _getWithdrawDepositContainerFirstChildSelector()
      );

      _sendGTMEvent(null, {
        eventName: 'withdrawal',
        eventAction: 'Withdrawal Fail',
        depositAmount: $scope.withdrawDataModel.amount,
        logged: options.logged || true,
        depositType: type,
        gaEventLabel: serviceErrorMessage,
        module: 'Withdrawal'
      });
    }

    function _buildGTMEvent(params) {
      var user = $scope.data.user;
      var withdrawAmount = params.withdrawAmount;
      var p = {};
      var cookie;
      var accountId;
      var residenceState;
      var gaEventLabel = _.get(params, 'gaEventLabel', params.withdrawType);

      if (_hasParentWindow()) {
        cookie = Utilities.prop('parent.TVG.Cookie.getValueByKey', window) || Utilities.noop;
      } else {
        cookie = Utilities.noop;
      }
      accountId = user.get('accountNumber') || cookie('user_id');
      residenceState = user.get('homeAddress.StateAbbr') || cookie('state');

      if (accountId) {
        p.accountId = accountId;
      }

      if (residenceState) {
        p.residenceState = residenceState;
      }

      p.event = params.eventName;
      p.page = params.page || $window.location.pathname;
      p.customerStatus = '';
      p.gaEventCategory = 'Withdrawal';
      p.gaEventAction = params.eventAction;
      p.gaEventLabel = gaEventLabel;
      p.loginStatus = !!accountId ? 'Logged In' : 'Logged Out';
      p.registrationStatus = 'Registered';
      p.screenName = '';
      p.module = params.module;
      p.depositType = params.depositType;
      p.depositAmount = params.depositAmount;

      if (ApiWithdrawGTMFac.isTVG4()) {
        p.screenName = 'My Account';
      } else {
        if ($location.path().split('/').length > 1) {
          p.screenName = $location.path().split('/')[1];
        } else {
          p.screenName = '';
        }
      }

      p.sectionName = ApiWithdrawGTMFac.isTVG4() ?
          'My Account | My Funds | Withdraw' :
          params.eventScreenName;
      p.siteVersion =
        ApiWithdrawGTMFac.getSiteVersion(ConfigurationFac.getApplicationContextItem('product'));
      p.withdrawAmount = ApiWithdrawGTMFac.gtmCurrencyFormat(withdrawAmount);
      p.withdrawType = params.withdrawType;

      if (params.errorMessage) {
        p.errorMessage = params.errorMessage;
        p.errorType = params.errorType;
        p.gaEventAction = params.errorType;
        p.gaEventLabel = params.errorMessage;
      }

      if (p.siteVersion === 'TVG3' || p.siteVersion === 'FDR-01') {
        p.screenName = 'Withdrawal';
        p.sectionName = undefined;
      }

      return p;
    }

    function _sendGTMEvent(event, params) {
      var obj = _buildGTMEvent(params);
      ApiWithdrawGTMFac.sendGTMEvent(event, obj);
    }

    function _updateBalance() {
      var currency = $filter('currency');
      return WithdrawFac.getAccountBalance()
        .then(function (data) {
          $scope.data.availableBalance = data.availableBalance;
          $scope.data.balance = currency(data.toteBalance, '$');
        });
    }

    function _updatePendingWithdrawals(withdrawalResult) {
      // This is only used on the desktop version
      if ($scope.showPendingWithdrawals) {
        $rootScope.hasPendingWithdrawals = true; // eslint-disable-line
        $rootScope.lastWithdrawalResult = withdrawalResult;
        $rootScope.$broadcast('WithdrawSuccessful::UpdatePendingRequests');
      }
    }

    /**
     * Is sightline enrollment with API visible?
     * (previous data.showSightlineApiEnrollment flag)
     * @return {Boolean}
     */
    function _isSightlineApiEnrollmentVisible() {
      var isSightline = $scope.data.selectedWithdrawOption.id === 'SLN';
      var hasSightlineAccount = $scope.data.hasSightlineAccount;
      var notLoading = !$scope.sightlineLoading;

      return isSightline && !hasSightlineAccount && notLoading;
    }

    /**
     * @return {string} the selector for the withdraw deposit container's first child.
     */
    function _getWithdrawDepositContainerFirstChildSelector() {
      return 'withdraw .tvg-deposit withdraw-type-selector';
    }

    function _hasParentWindow() {
      return Utilities.attempt(
        function () {
          return $window.document.referrer
              && $window.document.domain === $window.parent.document.domain
              && $window.self !== $window.top
              && $window.parent.location.href !== $window.location.href;
        },
        function () {
          return false;
        }
      );
    }

    function _setInitalConfigFromParam() {
      var filteredFromInitialTab;
      var filteredFromAvailableOptions;

      switch (initialTab) {
        case 'CCP':
        case 'DEB':
          filteredFromInitialTab = 'DEBIT_CARD';
          break;
        case 'ACH':
          filteredFromInitialTab = 'BETCASH';
          break;
        case 'CHK':
          filteredFromInitialTab = 'CHECK';
          break;
        case 'PPAL':
        case 'PAY':
          filteredFromInitialTab = 'PAY';
          break;
        case 'SLN':
        case 'SLP':
          filteredFromInitialTab = 'SLN';
          break;
        default:
          filteredFromInitialTab = null;
          break;
      }

      if (filteredFromInitialTab) {
        filteredFromAvailableOptions = $scope.data.withdrawOptions;
        filteredFromAvailableOptions = filteredFromAvailableOptions.filter(function (item) {
          if (item.id) {
            return item.id === filteredFromInitialTab;
          }
          return false;
        });

        if (filteredFromAvailableOptions && filteredFromAvailableOptions.length > 0) {
          $scope.data.selectedWithdrawOption = filteredFromAvailableOptions[0];
          $scope.data.pageSetFromParams = true;
        } else {
          $scope.data.selectedWithdrawOption = $scope.data.withdrawOptions[0];
        }
      } else {
        $scope.data.selectedWithdrawOption = $scope.data.withdrawOptions[0];
      }
    }

    /**
     * Get user cards on file
     */
    function _setUserCardsOnFile() {
      var accountId = $scope.data.accountId;
      var optionsOnFile = [];

      if (
        !_.find($scope.data.withdrawOptions, function (value) {
          return value.id === 'DEBIT_CARD';
        })
      ) {
        return;
      }

      WithdrawFac.getCardsOnFile(accountId)
        .then(function (data) {
          if (data.CardList && data.CardList.length > 0) {
            angular.forEach(data.CardList, function (card) {
              optionsOnFile.push({
                groupName: 'Cards On File',
                id: card.cardId,
                cardNumber: card.cardNumber,
                cardNumberExt: '****' + card.cardNumber,
                cardTypeId: DepositInitialDataFac.getCardType(card.cardType).id,
                limitTypeId: DepositInitialDataFac.getDepositLimitType(card.cardType).id,
                expirationDate: card.expDate,
                isExpired: moment(card.expDate, 'MM/YY')
                  .add(1, 'month') < moment(),
                signed: card.signed,
                name: card.network + ' (****' + card.cardNumber + ') ' + card.expDate,
                ftype: 'CC',
                type: DepositInitialDataFac.getCardType(card.cardType).abbr,
                typeName: card.cardType,
                cardType: card.cardType,
                network: card.network,
                min: DepositInitialDataFac.getLimitType(card.DepositLimitTypeId, 'min'),
                max: DepositInitialDataFac.getLimitType(card.DepositLimitTypeId, 'max'),
                depositTypeId: DEPOSIT_TYPES.CARD_ON_FILE,
                lastUsedDate: card.lastUsedDate || '1900-01-01T00:00:00.000-07:00'
              });
            });
          }

          if ($scope.data.cardsOnFile.length !== 0 && optionsOnFile.length) {
            _setUserCardsOnFile(optionsOnFile[0]);
          }

          $scope.data.unableToFetchCardsOnFile = false;
          $scope.data.cardsOnFile = optionsOnFile;
          _initDropdown('DEBIT_CARD');
          $scope.data.isLoading = false;
          $scope.data.fetchedCardsOnFile = true;
        })
        .catch(function () {
          $scope.data.unableToFetchCardsOnFile = true;
          $scope.data.isLoading = false;
          $scope.data.fetchedCardsOnFile = true;
        });
    }

    /**
     * Set user ach accounts on file
     * @private
     */
    function _setUserBankAccounts() {
      var accountId = $scope.data.accountId;

      DepositSrv.getUserBankAccounts(accountId)
      .then(function (data) {
        var optionsOnFile = [];
        if (data.bankAccounts && data.bankAccounts.length > 0) {
          angular.forEach(data.bankAccounts, function (ach) {
            optionsOnFile.push({
              achId: ach.id,
              bankName: ach.name,
              name: '(*****' + ach.accountNumber
              .substr(ach.accountNumber.length - 4) + ') ' + ach.name
            });
          });
        }

        $scope.data.unableToFetchBankAccounts = false;
        $scope.data.availableBetCashAccounts = optionsOnFile;

        if (data.bankAccounts && data.bankAccounts.length > 0) {
          _initDropdown('BETCASH');
        } else {
         //eslint-disable-next-line
         var newWithdrawOptions = $scope.data.withdrawOptions.filter(function (item) {
           return item.id !== 'BETCASH';
         });

          $scope.data.withdrawOptions = newWithdrawOptions;

          if (initialTab) {
            _setInitalConfigFromParam();
          } else {
            $scope.data.selectedWithdrawOption = $scope.data.withdrawOptions[0];
          }
        }
      })
      .catch(function () {
        $scope.data.unableToFetchBankAccounts = true;
      });
    }

    /* eslint-disable */
    unbind.push($rootScope.$on('sightlineUserEnrolled', function () {
      $scope.data.hasSightlineAccount = true;
      return NotificationService
        .success('Success!',
        'Congratulations! Your pre paid account has been approved!',
        'withdraw');
    }));

    $scope.$on('$destroy', function () {
      _.forEach(unbind, function (bind) {
        bind();
      });
    });

    (function init() {
      _getInitialData();
      firstWithdraw = true;
    }());
  }

  angular
    .module('TVG.Withdraw')
    .controller('WithdrawCtrl', WithdrawController);
}());

(function () {
  'use strict';

  BannerController.$inject = ['$sce'];
  bannerDirective.$inject = ['$rootScope', '$compile'];
  function BannerController($sce) {
    var DEFAULT_TYPE = 'success';
    this.type = angular.isString(this.type) && this.type || DEFAULT_TYPE;
    this.title = angular.isString(this.title) && $sce.trustAsHtml(this.title) || '';
  }

  function bannerDirective($rootScope, $compile) {
    var scopeObj = {
      callback: '&?',
      message: '=',
      title: '=?',
      type: '=?'
    };

    function _linkFn(scope, element) {
      var vm = scope.vm;
      var message = '<div>' + vm.message + '</div>';

      vm.close = function (invokeCallback) {
        element.remove();
        if (invokeCallback && angular.isFunction(vm.callback)) {
          return vm.callback();
        }

        return angular.noop();
      };

      vm.isConfirmBanner = function () {
        return vm.type === 'confirm';
      };

      scope.broadcastEvent = function (eventName) {
        $rootScope.$emit(eventName);
      };

      element.find('alert-content').append($compile(message)(scope));
    }

    return {
      bindToController: true,
      controller: BannerController,
      controllerAs: 'vm',
      link: _linkFn,
      restrict: 'E',
      scope: scopeObj,
      templateUrl: 'src/templates/banner.html'
    };
  }

  angular
    .module('TVG.Deposit')
    .directive('banner', bannerDirective);
}());

(function () {
  'use strict';

  clickOutside.$inject = ['$window', '$parse'];
  function clickOutside($window, $parse) {
    function link(scope, el, attr) {
      var fn = $parse(attr.clickOutside);

      var handler = function (e) {
        if (el[0] === e.target || el[0].contains(e.target) || !attr.clickOutside) {
          return;
        }

        scope.$apply(fn);
      };

      $window.addEventListener('click', handler, true);

      scope.$on('$destroy', function () {
        $window.removeEventListener('click', handler);
      });
    }

    return {
      link: link,
      restrict: 'A'
    };
  }

  angular.module('TVG.Deposit')
    .directive('clickOutside', clickOutside);
}());

(function () {
  'use strict';
  angular.module('TVG.Deposit')
    .directive('deposit', function () {
      return {
        restrict: 'E',
        scope: {
          withPlaceholders: '=',
          withAccountDetails: '=',
          notifyErrors: '=',
          fromOption: '=?',
          callback: '='
        },
        templateUrl: 'src/templates/deposit/deposit.html',
        link: function ($scope, $element, $attrs) {
          $scope.fromOption = $scope.fromOption || $attrs.fromOption; // eslint-disable-line
          $scope.redirectFrom = $attrs.redirectFrom; // this is an edge case: when the user comes from registration page
        }
      };
    })
    .directive('tvgCollapse', function () {
      return {
        restrict: 'E',
        transclude: true,
        scope: {
          title: '@',
          scrollDown: '@'
        },
        controller: ['$scope', '$window', '$timeout', '$rootScope', function ($scope, $window, $timeout, $rootScope) {
          var applyScroll = true;
          $scope.scrollDown = function () {
            if (applyScroll && $rootScope.isFdrApp) {
              $timeout(function () {
                $window.scrollTo(0, $window.innerHeight + 300);
              }, 50);
            }
            applyScroll = !applyScroll;
          };
        }],
        templateUrl: 'src/templates/tvg-collapse.html'
      };
    })
    .directive('customerOptions', function () {
      return {
        restrict: 'E',
        scope: {
          standalone: '@'
        },
        controller: ['$scope', '$filter', function ($scope, $filter) {
          var optionConfig = [];

          try {
            optionConfig = angular
              .fromJson($filter('CMSValue')('depositConfigOtherMenu', null));
          } catch (e) {
            // TODO: handle exception e
          }

          $scope.data = { optionsConfig: optionConfig }; // eslint-disable-line
        }],
        templateUrl: 'src/templates/customer-options.html'
      };
    })
    .directive('customerInfo', function () {
      return {
        restrict: 'E',
        scope: {
          htmlContentKey: '@'
        },
        templateUrl: 'src/templates/customer-info.html',
        controller: ['$scope', '$location', '$filter', '$sce', function ($scope, $location, $filter, $sce) {
          var path = $location.path();
          var cmsContent = '';

          $scope.data = {}; // eslint-disable-line

          if (!$scope.htmlContentKey) {
            cmsContent = $filter('CMSValue')(path.substring(
              path.lastIndexOf('/') + 1));
          } else {
            cmsContent = $filter('CMSValue')($scope.htmlContentKey);
          }

          $scope.data = { // eslint-disable-line
            htmlContent: $sce.trustAsHtml(cmsContent)
          };
        }]
      };
    })
    .directive('footerLinks', function () {
      return {
        restrict: 'E',
        scope: {},
        templateUrl: 'src/templates/footer-links.html'
      };
    })
    .directive('successDeposit', function () {
      return {
        restrict: 'E',
        scope: {
          depositData: '='
        },
        templateUrl: 'src/templates/deposit/deposit-success.html'
      };
    })
    .directive('errorDeposit', function () {
      return {
        restrict: 'E',
        scope: {},
        templateUrl: 'src/templates/deposit/deposit-error.html'
      };
    })
    .directive('depositAmountInput', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/deposit-amount-input.html'
      };
    })
    .directive('depositTypeSelector', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/deposit-type-selector.html'
      };
    })

    .directive('quickDepositSelector', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/quick-deposit-selector.html'
      };
    })

    .directive('quickDepositDefault', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/quick-deposit-default.html'
      };
    })

    .directive('depositTotalCost', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/deposit-total-cost.html'
      };
    })
    .directive('achDescriptionText', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/ach-description-text.html'
      };
    })
    .directive('cardDescriptionText', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/card-description-text.html'
      };
    })
    .directive('applepayDescriptionText', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/fields/applepay-description-text.html'
      };
    })
    .directive('sightlineEnrollment', function () {
      return {
        require: 'ngModel',
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/deposit/types/sightline/enrollment.html'
      };
    })
    .directive('dwInfoMessage', function () {
      return {
        restrict: 'E',
        scope: {
          title: '@',
          message: '@'
        },
        templateUrl: 'src/templates/dw-info-message.html'
      };
    })
    .directive('dwInfoDialog', function () {
      return {
        restrict: 'E',
        transclude: true,
        scope: {
          actionUrl: '=',
          action: '=',
          actionText: '@',
          livePerson: '@'
        },
        templateUrl: 'src/templates/dw-info-dialog.html'
      };
    })
    .directive('dwInfoDialogFdr', function () {
      return {
        restrict: 'E',
        transclude: true,
        scope: {
          actionUrl: '=',
          action: '=',
          actionText: '@',
          headingText: '@',
          buttonText: '@',
          buttonAction: '=',
          livePerson: '@'
        },
        templateUrl: 'src/templates/dw-info-dialog-fdr.html'
      };
    })
    .directive('welcomeDialogFdr', ['$rootScope', '$location', function ($rootScope, $location) {
      return {
        restrict: 'E',
        templateUrl: 'src/templates/welcome-dialog-fdr.html',
        link: function ($scope) {
          $scope.dismiss = function () {
            $scope.events.closeSuccessfulRegistrationModal();
            $rootScope.newUser = false;
            $location.search('newUser', null);
          };
        }
      };
    }])
    .directive('toggleComponent', function () {
      return {
        restrict: 'E',
        scope: {
          savein: '=',
          title: '@',
          subtitle: '@'
        },
        templateUrl: 'src/templates/toggle-component.html'
      };
    })
    .directive('additionalInfo', function () {
      return {
        restrict: 'E',
        scope: true,
        transclude: true,
        controller: ['$scope', 'UserActionEventsService', function ($scope, UserActionEventsService) {
          var defaultAmountList;
          var amountType;
          $scope.data = { infoState: false };
          $scope.events = {
            toggleInfo: function () {
              $scope.data.infoState = !$scope.data.infoState;
              if (!$scope.$ctrl) {
                defaultAmountList = [50, 100, 300];
                amountType = defaultAmountList.
                    indexOf(_.get($scope, 'depositDataModel.amount')) > -1 ? 'Yes' : 'No';
                if ($scope.data.selectedPayOption && $scope.data.selectedPayOption.ftype === 'CC') {
                  UserActionEventsService.emit('CVVInfoClick', amountType);
                } else {
                  UserActionEventsService.emit('TooltipClick');
                }
              }
            },

            closeInfo: function () {
              $scope.data.infoState = false;
            }
          };
        }],
        templateUrl: 'src/templates/additional-info.html'
      };
    })
    .directive('tvgDmaModal', function () {
      return {
        restrict: 'E',
        scope: {
          close: '&',
          title: '@',
          body: '@'
        },
        templateUrl: 'src/templates/deposit/utils/modal-content-directive.html'
      };
    })

    .directive('restrictChars', [function () {
      return {
        restrict: 'A',
        link: function (scope, elem) {
          angular.element(elem).on('keypress', function (e) { // eslint-disable-line
            var CHAR_AFTER_DP = 2;  // number of decimal places
            var validList = '0123456789.';  // allowed characters in field
            var key;
            var keyChar;
            var dp;
            var obj = angular.element(document.querySelector('input[name="amount"]')); // eslint-disable-line
            key = window.event ? window.event.keyCode : e ? e.which : null; // eslint-disable-line

            // control keys
            // null, backspace, tab, carriage return, escape
            if (key === 0 || key === 8 || key === 9 || key === 13 ||
              key === 27) {
              return true;
            }

            // get character
            keyChar = String.fromCharCode(key);

            // check valid characters
            if (validList.indexOf(keyChar) !== -1) {
              // check for existing decimal point
              dp = 0;

              if ((dp = obj.val().indexOf('.')) > -1) { // eslint-disable-line
                if (keyChar === '.') {
                  e.preventDefault();  // only one allowed
                } else {
                  // check for room for more numbers after decimal point
                  if ((obj.val().length - dp > CHAR_AFTER_DP) ||
                    obj.val().length >= 9) {
                    e.preventDefault();
                  }
                }
              } else if (obj.val().length >= 9 ||
                (obj.val().length >= 8 && keyChar === '.') ||
                (obj.val().length === 0 && keyChar === '.')) {
                // over the field input limit
                e.preventDefault();
              } else {
                return true;
              }
            } else if (validList.indexOf(keyChar) === -1) {
              // not a valid character
              e.preventDefault();
            } else {
              return true;
            }
          });
        }
      };
    }])
    .directive('tvgLimitTo', ['$document', '$window', function ($document, $window) {
      return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
          var limit = parseInt(attrs.tvgLimitTo, 10);

          elem.on('keydown', function (e) {
            var text = '';

            if (angular.isFunction($window.getSelection)) {
              text = $window.getSelection().toString();
            } else if (angular.isDefined($document[0].selection) &&
              $document[0].selection.type === 'Text') {
              text = $document[0].selection.createRange().text;
            }

            if (text !== this.value
                && this.value.length === limit
                && e.keyCode !== 8
                && e.keyCode !== 9
                && e.keyCode !== 46
                && e.keyCode !== 37
                && e.keyCode !== 39
            ) {
              return false;
            }

            return true;
          });
        }
      };
    }])
    .directive('sectionTitle', function () {
      return {
        restrict: 'E',
        scope: {
          title: '@',
          index: '@',
          qalabel: '@'
        },
        templateUrl: 'src/templates/section-title.html'
      };
    });
}());

(function () {
  'use strict';

  pendingWithdrawElement.$inject = ['$rootScope', '$timeout', 'ConfigurationFac'];
  function pendingWithdrawElement($rootScope, $timeout, ConfigurationFac) {
    return {
      restrict: 'E',
      scope: {
        item: '=',
        loading: '=',
        cancelPendingWithdraw: '&'
      },
      templateUrl: 'src/templates/withdraw/desktop/pendingWithdrawals/' +
      'pending-withdraw-element.html',
      link: function (scope, element) {
        var timer;
        var $li;

        scope.showConfirmation = false;
        scope.showMessage = false;
        scope.showCancelButton = true;

        scope.njxIntegration = ConfigurationFac.getApplicationContextItem('product') === 'njx';

        timer = null;
        $li = element.find('li');

        scope.undoCancel = function () {
          scope.showConfirmation = false;
          $li.removeClass('lighter-warning');
          $rootScope.$emit('PendingWithdrawUndoCancelClick', scope.item.WithdrawalId);
        };

        scope.onCancel = function () {
          scope.showConfirmation = true;
          $li.removeClass('lighter-error lighter-success');
          $li.addClass('lighter-warning');
          $rootScope.$emit('PendingWithdrawCancelClick', scope.item.withdrawalId);
        };

        scope.getBetTypeName = function (key) {
          switch (key) {
            case 'ACH':
              return 'eCheck';
            case 'CHK':
              return 'Check Request';
            case 'SLP':
              return 'TVG Pre Paid Card';
            case 'PAY':
              return 'PayPal';
            case 'VIWD':
              return 'Debit Card';
            case 'MZM':
              return 'Online Banking';
            default:
              return '';
          }
        };

        function _hideOnTimeout() {
          timer = $timeout(function () {
            scope.onRemoveMessage();
          }, 10000);
        }

        scope.$on('PendingWithdrawals::CancelSuccess', function (event, params) {
          if (scope.item.withdrawalId === params.withdrawalId) {
            scope.isSuccess = true;
            scope.successMessage = params.message;
            _onMessageDisplay();
            $li.addClass('lighter-success');
            _hideOnTimeout();
          }
        });

        scope.$on('PendingWithdrawals::CancelError', function (event, params) {
          if (scope.item.withdrawalId === params.withdrawalId) {
            scope.isError = true;
            scope.errorMessage = params.message;
            _onMessageDisplay();
            _hideOnTimeout();
            $li.addClass('lighter-error');
          }
        });

        scope.$on('PendingWithdrawals::CancelCriticalError', function (event, params) {
          if (scope.item.withdrawalId === params) {
            scope.isCriticalError = true;
            _onMessageDisplay();
            _hideOnTimeout();
            $li.addClass('lighter-error');
          }
        });

        scope.$on('PendingWithdrawals::CancelWarning', function (event, params) {
          if (scope.item.withdrawalId === params.withdrawalId) {
            scope.isWarning = true;
            scope.warningMessage = params.message;
            _onMessageDisplay();
            _hideOnTimeout();
            $li.addClass('lighter-warning');
          }
        });

        scope.onRemoveMessage = function () {
          $timeout.cancel(timer);
          scope.$emit('WithdrawSuccessful::UpdatePendingRequests');
          scope.showMessage = false;
          scope.isError = false;
          scope.showCancelButton = !scope.isSuccess;
          scope.isSuccess = false;
          scope.isCriticalError = false;
          scope.isWarning = false;
          scope.showConfirmation = false;
          $li.removeClass('lighter-error lighter-success lighter-warning');
        };

        function _onMessageDisplay() {
          scope.showConfirmation = false;
          scope.showCancelButton = false;
          scope.showMessage = true;
        }
      }
    };
  }

  angular.module('TVG.Withdraw')
      .directive('pendingWithdrawElement', pendingWithdrawElement);
}());

(function () {
  'use strict';

  angular.module('TVG.ManagePaymentMethods')
    .directive('managePaymentMethods', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/managePaymentMethods/' +
        'manage-payment-methods.html'
      };
    })
    .directive('newPaymentMethod', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/managePaymentMethods/fields/' +
        'new-payment-method.html'
      };
    })
    .directive('paymentMethodOnFileList', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/managePaymentMethods/fields/' +
        'payment-method-on-file-list.html'
      };
    })
    .directive('depositLimits', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/managePaymentMethods/fields/' +
        'deposit-limits.html'
      };
    })
    .directive('paymentMethodsTypeSelector', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/managePaymentMethods/fields/' +
        'payment-methods-type-selector.html'
      };
    })
    .directive('paymentMethodOnFileOption', function () {
      return {
        restrict: 'E',
        scope: {
          card: '=',
          onEditCardAction: '&',
          onGoToDeposit: '&',
          onRemoveCardAction: '&',
          $index: '='
        },
        templateUrl: 'src/templates/managePaymentMethods/fields/' +
        'payment-method-on-file-option.html'
      };
    })
    .directive('ngEnter', function () {
      return function (scope, element, attrs) {
        element.bind('keydown keypress', function (event) {
          if (event.which === 13) {
            scope.$apply(function () {
              scope.$eval(attrs.ngEnter, { event: event });
            });

            event.preventDefault();
          }
        });
      };
    })
    .component('paymentMethodCard', {
      templateUrl: 'src/templates/managePaymentMethods/fields/payment-method-card.html',
      controller: 'ManagePaymentMethodsController',
      bindings: {
        card: '=',
        removeCard: '&',
        sliceCard: '&'
      }
    })
    .component('paymentTitles', {
      templateUrl: 'src/templates/managePaymentMethods/fields/titles.html',
      controller: 'ManagePaymentMethodsController',
      bindings: {
        type: '=',
        length: '=',
        redirectAdd: '&'
      }
    });
}());

(function () {
  'use strict';

  function moneyFormater() {
    var oldValue = '';

    function link(scope, element, attrs, ngModel) {
      element.bind('keyup', function (event) {
        var patt;
        var str = event.currentTarget.value;
        if (event.currentTarget.validity.badInput) {
          event.currentTarget.value = oldValue; // eslint-disable-line
          ngModel.$viewValue = oldValue; // eslint-disable-line
          ngModel.$render();
        } else {
          patt = new RegExp('(^$|^(\\d{1,' + attrs.numLength +
            '}(\\.)?$|^\\d{1,' + attrs.numLength +
            '}\\.\\d{1,2}$|^\\.(\\d{1,2})?$))');
          if (patt.test(str)) {
            oldValue = str;
          } else {
            event.currentTarget.value = oldValue; // eslint-disable-line
            ngModel.$viewValue = oldValue; // eslint-disable-line
            ngModel.$render();
          }
        }
      });
    }

    return {
      link: link,
      restrict: 'A',
      require: '?ngModel'
    };
  }

  angular.module('TVG.Deposit')
    .directive('moneyFormater', moneyFormater);
}());

(function () {
  'use strict';

  function quickDeposit() {
    return {
      restrict: 'E',
      scope: {
        quick: '@',
        withPlaceholders: '=',
        withAccountDetails: '=',
        notifyErrors: '='
      },
      templateUrl: 'src/templates/deposit/quick-deposit.html'
    };
  }

  angular.module('TVG.Deposit')
    .directive('quickDeposit', quickDeposit);
}());

(function () {
  'use strict';

  /* eslint-disable */

  /**
    * series
    * Given an array of functions, it will call every function,
    * once at a time, sequentially.
    * Every function will have a trigger function as its last argument,
    * that should be called when the function is done.
    * If arguments are given to this trigger function, those will be passed
    * to the next function.
    *
    * @example
    *     series([
    *         function doSomething(next) {
    *             //when it's done
    *             next(argument1, arguments2)
    *         },
    *         function doSomethingElse(arg1, arg2, next) {
    *             // do something with the arguments,
    *             // and when it's done:
    *             next();
    *         },
    *         function doAnotherThing(next) {
    *             // because we didn't give arguments to this function
    *             // only the 'next' is available
    *             // when done.
    *             next();
    *         }
    *     ]);
    *
    *
    * @param   {Array} fns Array of functions
    */
  var cachedComponent;

  var series = function (fns) {
      (function next() {
          var args = Array.prototype.slice.call(arguments);
          fns.length && fns.shift().apply(this, args.concat(next));
      }());
  };

  var parseJSON = function(json) {
    var data = {};
    var error = null;

    try { data = JSON.parse(json) }
    catch (e) {
      error = e;
    }

    return error ? error : data;
  }

  function getURL(path) {
    return path;
  }

  function request(url, callback) {
    var oReq = new XMLHttpRequest();

    oReq.addEventListener('error', callback);
    oReq.addEventListener('load', function () {
      var data = parseJSON(this.responseText);
      return (data instanceof Error)
        ? callback(data)
        : callback(null, data);
    });
    oReq.open('GET', url);
    oReq.setRequestHeader('Accept', 'application/json')
    oReq.setRequestHeader('Content-Type', 'application/json')

    oReq.send();
  }

  var createLink = function (url) {
    var link = document.createElement('link');
    link.setAttribute('rel', 'stylesheet');
    link.setAttribute('href', getURL(url));
    document.head.appendChild(link)
    return link;
  };

  var createScript = function (url, cb) {
    var script = document.createElement('script');
    script.setAttribute('src', getURL(url));
    script.onload = function() { cb() };
    script.onerror = function (e) { cb(e) };
    document.body.appendChild(script);
    return script;
  };

  var createHTML = function (str) {
    var fragment = document.createDocumentFragment();
    if (str) { fragment.innerHTML = str; }
    cachedComponent = fragment;
    return fragment;
  };

  var append = function (manifest, cb) {
    manifest.css.map(createLink)

    // Prepare an array of functions
    var tasks = manifest.js.map(function (url) {
      return function(next) {
        if (next instanceof Error) { return cb(next); }
        return createScript(url, next)
      };
    })

    tasks = tasks.concat(function (next) {
      if (next instanceof Error) { return cb(next); }

      cb(null);
      next();
    });

    series(tasks);
  };

  function loadComponent(url, callback) {
    if(cachedComponent) {
      return callback(null, cachedComponent);
    } else {
      request(getURL(url), function (err, data) {
        if (err) { return callback(err); }
        append(data, function () {
          return callback(null, createHTML(data.html));
        });
      });
    }
  }

    /* eslint-enable */
  angular
        .module('TVG.Deposit')
        .directive('reactSightline', ['$rootScope', '$timeout', '$window',
          function ($rootScope, $timeout, $window) {
            return {
              restrict: 'E',
              scope: false,
              link: function ($scope, $element) {
                $element.attr('id', 'funds'); // we'll keep this as some css classes on funds are dependent on this
                $element.addClass('loading');
              // eslint-disable-next-line no-console,angular/log
                loadComponent('/fnd/component', function (err, node) {
                // Stop! Hammer time!
                // We're not sure how to remove the loading states
                  $timeout(function () {
                    $element.removeClass('loading');
                    $scope.data.loading = false;
                    $scope.data.sightlineLoading = false;
                    $scope.data.makingDeposit = false;
                    $scope.sightlineLoading = false;
                  });

                  if (err) {
                    $element.addClass('error');
                    throw err;
                  }

                  $element.html(node);
                  sightline.mount(
                  $element.get(0),
                    {
                      isAuthenticated: !!$scope.$parent.accountDetails,
                      accountDetails: $scope.$parent.accountDetails,
                      showRedirectMessage: $rootScope.showRedirectMessage,
                      depositInfo: $rootScope.cardDataToReactSightline,
                      onDepositComplete: function (payload) {
                        $rootScope.$broadcast('emitEgFund', payload);
                      },
                      onFundComplete: function () {
                        $rootScope.$broadcast('hasMadeInitialDeposit_update');
                        if (
                        $rootScope.product &&
                        $rootScope.product.indexOf('native') !== -1
                      ) {
                          if ($window && $window.handleNativeMessages) {
                            $window.handleNativeMessages('UPDATE_BALANCE');
                          }
                        }
                      },
                      onPaymentComplete: function () {
                        $rootScope.$broadcast('accountBalance_update');
                      },
                      onInvalidCardType: function () {
                        $rootScope.$broadcast('cardType_invalid');
                      }
                    }
                );

                  $scope.$on('$destroy', function () {
                    sightline.destroy($element.get(0));
                    $rootScope.showRedirectMessage = false;
                    $rootScope.cardDataToReactSightline = {};
                    $scope.depositInitialData = {};
                  });
                });
              }
            };
          }]);

  return angular;
}());

(function () {
  'use strict';

  angular.module('TVG.Transfer')
    .directive('transfer', function () {
      return {
        restrict: 'E',
        templateUrl: 'src/templates/transfer/transfer.html'
      };
    })
    .directive('transferAmountInput', function () {
      return {
        restrict: 'E',
        templateUrl: 'src/templates/transfer/fields/transfer-amount-input.html'
      };
    })
    .directive('transferSourceDestination', function () {
      return {
        restrict: 'E',
        templateUrl: 'src/templates/transfer/fields/' +
        'transfer-source-destination.html'
      };
    });
}());

(function () {
  'use strict';

  angular.module('TVG.Withdraw')

    .directive('withdraw', function () {
      return {
        restrict: 'E',
        scope: {
          fromOption: '@?'
        },
        templateUrl: 'src/templates/withdraw/withdraw.html',
        link: function ($scope, $element, $attrs) {
          $scope.fromOption = $attrs.fromOption; // eslint-disable-line
        },
        controller: 'WithdrawCtrl',
        controllerAs: 'withdrawCtrl'
      };
    }).directive('withdrawTypeSelector', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/withdraw/fields/withdraw-type-selector.html'
      };
    })
    .directive('withdrawSuccess', function () {
      return {
        restrict: 'E',
        scope: {
          withdraw: '='
        },
        templateUrl: 'src/templates/withdraw/withdraw-success.html'
      };
    })
    .directive('withdrawError', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/withdraw/withdraw-error.html'
      };
    })
    .directive('withdrawCancel', function () {
      return {
        restrict: 'E',
        scope: true,
        templateUrl: 'src/templates/withdraw/withdraw-cancel.html'
      };
    })
    .directive('withdrawPendingRequests', function () {
      return {
        restrict: 'EA',
        scope: true,
        templateUrl: 'src/templates/withdraw/desktop/pendingWithdrawals/withdraw-pending-requests.html',
        controller: 'WithdrawCancelDesktopController',
        controllerAs: 'WithdrawCancelDesktopController'
      };
    });
}());

(function () {
  'use strict';

  var capitalize = function (Utilities) {
    return Utilities.upperFirst;
  };
  capitalize.$inject = ['Utilities'];

  angular.module('TVG.DMA.Common').filter('capitalize', capitalize);
}());

(function () {
  'use strict';

  DMAFeatureTogglesFilter.$inject = ['DMAFeatureTogglesHashContainerSvc'];
  function DMAFeatureTogglesFilter(DMAFeatureTogglesHashContainerSvc) {
    var _featureTooglesHash = DMAFeatureTogglesHashContainerSvc.getBasedOnKey('dma');

    return function (key) {
      return _featureTooglesHash(key);
    };
  }

  angular.module('TVG.DMAToggles')
    .filter('DMAFeatureTogglesFilter', DMAFeatureTogglesFilter);
}());

(function () {
  'use strict';

  var noFractionCurrency = function ($filter, $locale) {
    var currencyFilter = $filter('currency');
    var formats = $locale.NUMBER_FORMATS;
    return function (amount, currencySymbol) {
      var value = currencyFilter(amount, currencySymbol);
      var sep = value.indexOf(formats.DECIMAL_SEP);
      if (amount >= 0) {
        if (amount % 1 === 0) {
          return value.substring(0, sep);
        }
        return value;
      }
      return value.substring(0, sep) + ')';
    };
  };
  noFractionCurrency.$inject = ['$filter', '$locale'];

  angular.module('TVG.DMA.Common')
         .filter('noFractionCurrency', noFractionCurrency);
}());

(function () {
  'use strict';
  var trust = function ($sce) {
    return $sce.trustAsHtml;
  };
  trust.$inject = ['$sce'];

  angular.module('TVG.DMA.Common').filter('trust', trust);
}());

(function () {
  'use strict';

  ApiDepositsGTMFac.$inject = ['$rootScope', '$location', '$document', '$window', 'ConfigurationFac', 'DMAScreenNames', 'DMASectionNames', 'Utilities'];
  function ApiDepositsGTMFac($rootScope,
            $location,
            $document,
            $window,
            ConfigurationFac,
            DMAScreenNames,
            DMASectionNames,
            Utilities) {
    function _gtmCurrencyFormat(val) {
      var tempBetAmount = val;
      try {
        tempBetAmount = tempBetAmount.toFixed(2);
      } catch (e) {
        // Purposely ignore the exception
      }
      return tempBetAmount;
    }

    /**
     *
     * @param {type} input
     * @returns {unresolved}
     */
    function _formatGALAbelUpperCase(input) {
      var result;

      if (input) {
        result = input.replace(/([A-Z]+)/g, ',$1').replace(/^,/, '');

        return result.replace(/,/g, ' ').replace(/\b\w/g, function (m) {
          return m.toUpperCase();
        });
      }
      return '';
    }


    /**
     *
     * @param {type} evName event name
     * @returns {object} defaulParams
     */
    function _baseParams(evName) {
      var eventParams = {};
      eventParams.accountId = undefined;
      eventParams.betAmount = undefined;
      eventParams.betName = undefined;
      eventParams.betType = undefined;
      eventParams.cableProvider = undefined;
      eventParams.cardType = undefined;
      eventParams.customerStatus = undefined;
      eventParams.dedicatedTVGChannel = undefined;
      eventParams.depositAmount = undefined;
      eventParams.depositMethod = undefined;
      eventParams.depositType = undefined;
      eventParams.errorMessage = undefined;
      eventParams.errorType = undefined;
      eventParams.gaEventAction = undefined;
      eventParams.gaEventCategory = undefined;
      eventParams.gaEventLabel = undefined;
      eventParams.gaEventValue = undefined;
      eventParams.loginStatus = undefined;
      eventParams.netDepositFee = undefined;
      eventParams.paymentMethod = undefined;
      eventParams.promoCode = undefined;
      eventParams.productVersion = undefined;
      eventParams.raceName = undefined;
      eventParams.raceNumber = undefined;
      eventParams.raceStatus = undefined;
      eventParams.registrationStatus = undefined;
      eventParams.residenceState = undefined;
      eventParams.referrer = undefined;
      eventParams.runnerSelectionList = undefined;
      eventParams.screenName = undefined;
      eventParams.siteVersion = undefined;
      eventParams.sectionName = undefined;
      eventParams.videoName = undefined;
      eventParams.videoType = undefined;
      eventParams.withdrawAmount = undefined;
      eventParams.withdrawType = undefined;
      eventParams.trackName = undefined;
      eventParams.eventLabel = undefined;
      eventParams.url = undefined;
      eventParams.wagerAmount = undefined;
      eventParams.wagerName = undefined;
      eventParams.wagerType = undefined;
      eventParams.withdrawalAmount = undefined;
      eventParams.withdrawalType = undefined;
      eventParams.event = evName;
      eventParams.sport = undefined;
      eventParams.gaEventCategory = 'Deposit';
      eventParams.loginStatus = 'Logged In';
      eventParams.registrationStatus = 'Registered';
      eventParams.screenName = 'Deposit';
      eventParams.sectionName = 'Deposit';
      eventParams.siteVersion = _isTVG4() ? 'desktop' : 'mobile_web';
      eventParams.productVersion = _getProduct(
        ConfigurationFac.getApplicationContextItem('product')
      );
      return eventParams;
    }

    function _sendGTMEvent(_eventName, aditionalParams) {
      var finalParams = _baseParams(_eventName);

      if (angular.isObject(aditionalParams)) {
        finalParams = angular.extend(finalParams, aditionalParams);
      }

      if ($window.dataLayer) {
        $window.dataLayer.push(finalParams);
      }
      return finalParams;
    }

    function _isTVG4() {
      return $rootScope.layout === 'desktop';
    }

    function _eventScreenName() {
      if (_isTVG4() && $location.hash().length > 1) {
        return _formatGALAbelUpperCase($location.path().substring(1)) + '|' +
          _getScreenName($location.hash());
      }
      return _formatGALAbelUpperCase($location.path().split('/').length > 1 ?
        $location.path().split('/')[1] : '');
    }

    function _getSiteVersion(product) {
      var siteVersionKeys = {
        touch3: 'mobile_web',
        ios2: 'ios_native',
        fdrmobile: 'mobile_web',
        fdrios: 'ios_native',
        fdrandroid: 'android_native',
        androidwrapper: 'android_native',
        tvgandroid: 'android_native',
        iosnative: 'ios_native'
      };
      return siteVersionKeys[product] ? siteVersionKeys[product] : product.toUpperCase();
    }

    function _getProduct(product) {
      var productKeys = {
        touch3: 'MEP',
        ios2: 'iOS',
        fdrmobile: 'MEP',
        fdrios: 'MEP',
        fdrandroid: 'android_apk',
        androidwrapper: 'android_gps',
        tvgandroid: 'android_apk',
        iosnative: 'ios_native'
      };
      return productKeys[product] ? productKeys[product] : product.toUpperCase();
    }


    // Get Screenname for all GTM events
    function _tvg4ScreenName() {
      var url = $location.path().split('/');
      var urlToken = url[1];
      var sectionName = DMAScreenNames[urlToken];

      if (angular.isUndefined(sectionName)) {
        return '';
      }

      return sectionName;
    }


    function _getScreenName(name) {
      var screenName;

      switch (name) {
        case 'wallet':
          screenName = 'My Wallet';
          break;
        case 'deposit':
          screenName = 'Deposit';
          break;
        case 'withdraw':
          screenName = 'Withdraw';
          break;
        case 'reports':
          screenName = 'My Bets';
          break;
        case 'account':
          screenName = 'My Account';
          break;
        case 'handicapping-store':
          screenName = 'Handicapping Store';
          break;
        case 'free-pp':
          screenName = 'Free Past Performances';
          break;
        case 'talentpicks':
          screenName = 'TVG Picks';
          break;
        case 'my-tracks':
          screenName = 'My Tracks';
          break;
        case 'my-stable':
          screenName = 'My Stable';
          break;
        default:
          screenName = name;
      }

      return screenName;
    }

    function _tvg4SectionNameByURLSharp(name, params) {
      var parts = _URLParse(name);
      var section = parts.pathname.replace('/', '');
      var hash = parts.hash.replace('#', '');
      var splitHash = hash.split('+');
      var translation = [section, 'translation'].join('.');
      var firstSection = Utilities.isEmpty(splitHash[0]) ? '' :
        [section, splitHash[0]].join('.');
      var sectionName = Utilities.prop(translation, DMASectionNames);
      var fullSectionName;
      var secondSection;

      if (splitHash.length > 1) {
        secondSection = [section, splitHash[1]].join('.');
        fullSectionName = [
          sectionName,
          (Utilities.prop(firstSection, DMASectionNames) || ''),
          (Utilities.prop(secondSection, DMASectionNames) || '')
        ].join(' | ');
      } else {
        fullSectionName = Utilities.isEmpty(firstSection) ?
          sectionName :
          [sectionName, (Utilities.prop(firstSection, DMASectionNames) || '')]
            .join(' | ');
      }

      return Utilities.isEmpty(params) ?
        fullSectionName : fullSectionName.concat(' | ')
        .concat(params.sectionName);
    }

    function _URLParse(url) {
      var parser = $window.document.createElement('a');
      parser.href = url;

      return {
        pathname: parser.pathname,
        hash: parser.hash
      };
    }

    function _tvg4SectionNameByURLToken(key, name, params) {
      var sectionName;

      if (angular.isString(name) && !Utilities.isEmpty(name)) {
        sectionName = DMASectionNames[key].translation + ' | ' +
          DMASectionNames[key][name];
      } else {
        sectionName = DMASectionNames[key].translation;
      }

      if (!Utilities.isEmpty(params) && !Utilities.isEmpty(params.sectionName)) {
        sectionName += ' | ' + params.sectionName;
      }

      return sectionName;
    }

    function _getURLForRetroCompatibleGTM() {
      var url = $location.url();

      if (url.indexOf('my-funds/deposit') > -1) {
        return '/my-profile#funds+deposit';
      } else if (url.indexOf('my-funds/bank') > -1) {
        return '/my-profile#funds+bank';
      } else if (url.indexOf('my-funds/withdraw') > -1) {
        return '/my-profile#funds+withdraw';
      }

      return url;
    }

    function _tvg4SectionName(params) {
      var url = _getURLForRetroCompatibleGTM().split('/');
      var urlToken = url[1];
      var defaultParam;

      if (urlToken && (urlToken.indexOf('#') > -1 ||
        urlToken.indexOf('%20') > -1)) {
        return _tvg4SectionNameByURLSharp(urlToken, params);
      }

      switch (urlToken) {
        case 'info':
          return _tvg4SectionNameByURLToken('siteinfo', url[2], params);
        case 'races':
          defaultParam = {
            sectionName: 'By Time'
          };
          return _tvg4SectionNameByURLToken('horseracing', urlToken,
            angular.isUndefined(params) || Utilities.isEmpty(params) ?
              defaultParam : params);
        case 'results':
          defaultParam = {
            sectionName: 'By Time'
          };
          return _tvg4SectionNameByURLToken('horseracing', urlToken,
            angular.isUndefined(params) || Utilities.isEmpty(params) ?
              defaultParam : params);
        case 'home':
          return _tvg4SectionNameByURLToken('home', null, params);
        case 'my-profile':
          return _tvg4SectionNameByURLToken('my-profile', 'profile', params);
        case 'my-favorite-tracks':
          return _tvg4SectionNameByURLToken('my-profile', 'my-favorite-tracks', params);
        case 'my-stable':
          return _tvg4SectionNameByURLToken('my-profile', 'my-stable', params);
        case 'my-tracks':
          return _tvg4SectionNameByURLToken('my-profile', 'my-tracks', params);
        case 'my-funds':
          return _tvg4SectionNameByURLToken('my-profile', 'funds', params);
        case 'my-bets':
          return _tvg4SectionNameByURLToken('my-profile', 'my-bets', params);
        case 'my-account-summary':
          return _tvg4SectionNameByURLToken('my-profile', 'my-account-summary', params);
        case 'registration':
          return _tvg4SectionNameByURLToken('registration', null, params);
        default:
          return '';
      }
    }

    return {
      sendGTMEvent: _sendGTMEvent,
      gtmCurrencyFormat: _gtmCurrencyFormat,
      formatGALAbelUpperCase: _formatGALAbelUpperCase,
      isTVG4: _isTVG4,
      eventScreenName: _eventScreenName,
      getScreenName: _getScreenName,
      tvg4ScreenName: _tvg4ScreenName,
      tvg4SectionName: _tvg4SectionName,
      getSiteVersion: _getSiteVersion,
      getProduct: _getProduct
    };
  }

  angular.module('TVG.Deposit').factory('ApiDepositsGTMFac', ApiDepositsGTMFac);
}());

(function () {
  'use strict';
  ApiWithdrawGTMFac.$inject = ['$rootScope', '$window', 'ConfigurationFac'];
  function ApiWithdrawGTMFac($rootScope, $window, ConfigurationFac) {
    function _gtmCurrencyFormat(val) {
      var tempBetAmount = val;
      try {
        tempBetAmount = tempBetAmount.toFixed(2);
      } catch (e) {
        // Purposely ignore the exception
      }
      return tempBetAmount;
    }

    /**
     *
     * @param {type} input
     * @returns {unresolved}
     */
    function _formatGALAbelUpperCase(input) {
      var result;

      if (input) {
        result = input.replace(/([A-Z]+)/g, ',$1').replace(/^,/, '');

        return result.replace(/,/g, ' ').replace(/\b\w/g, function (m) {
          return m.toUpperCase();
        });
      }

      return '';
    }


    /**
     *
     * @param {type} evName event name
     * @returns {object} defaulParams
     */
    function _baseParams(evName) {
      var eventParams = {};
      eventParams.accountId = undefined;
      eventParams.betAmount = undefined;
      eventParams.betName = undefined;
      eventParams.betType = undefined;
      eventParams.cableProvider = undefined;
      eventParams.cardType = undefined;
      eventParams.customerStatus = undefined;
      eventParams.dedicatedTVGChannel = undefined;
      eventParams.depositAmount = undefined;
      eventParams.depositMethod = undefined;
      eventParams.depositType = undefined;
      eventParams.errorMessage = undefined;
      eventParams.errorType = undefined;
      eventParams.gaEventAction = undefined;
      eventParams.gaEventCategory = undefined;
      eventParams.gaEventLabel = undefined;
      eventParams.loginStatus = undefined;
      eventParams.netDepositFee = undefined;
      eventParams.paymentMethod = undefined;
      eventParams.promoCode = undefined;
      eventParams.productVersion = undefined;
      eventParams.raceName = undefined;
      eventParams.raceNumber = undefined;
      eventParams.raceStatus = undefined;
      eventParams.registrationStatus = undefined;
      eventParams.residenceState = undefined;
      eventParams.referrer = undefined;
      eventParams.runnerSelectionList = undefined;
      eventParams.screenName = undefined;
      eventParams.siteVersion = undefined;
      eventParams.sectionName = undefined;
      eventParams.videoName = undefined;
      eventParams.videoType = undefined;
      eventParams.withdrawAmount = undefined;
      eventParams.withdrawType = undefined;
      eventParams.trackName = undefined;
      eventParams.url = undefined;
      eventParams.wagerAmount = undefined;
      eventParams.wagerName = undefined;
      eventParams.wagerType = undefined;
      eventParams.withdrawalAmount = undefined;
      eventParams.withdrawalType = undefined;
      eventParams.page = '';
      eventParams.accountId = '';
      eventParams.residenceState = '';
      eventParams.event = evName;
      eventParams.gaEventCategory = 'Withdraw';
      eventParams.loginStatus = 'Logged In';
      eventParams.registrationStatus = 'Registered';
      eventParams.screenName = 'Withdraw';
      eventParams.sectionName = 'Withdraw';
      eventParams.siteVersion = isTVG4() ? 'desktop' : 'mobile_web';
      eventParams.productVersion =
        _getProduct(ConfigurationFac.getApplicationContextItem('product'));
      return eventParams;
    }

    function _sendGTMEvent(_eventName, aditionalParams) {
      var finalParams = _baseParams(_eventName);

      if (angular.isObject(aditionalParams)) {
        finalParams = angular.extend(finalParams, aditionalParams);
      }

      if ($window.dataLayer) {
        $window.dataLayer.push(finalParams);
      }
    }

    function _getSiteVersion(product) {
      var siteVersionKeys = {
        touch3: 'mobile_web',
        ios2: 'ios_native',
        fdrmobile: 'mobile_web',
        fdrios: 'ios_native',
        fdrandroid: 'android_native',
        androidwrapper: 'android_native',
        tvgandroid: 'android_native',
        iosnative: 'ios_native'
      };
      return siteVersionKeys[product] ? siteVersionKeys[product] : product.toUpperCase();
    }

    function _getProduct(product) {
      var productKeys = {
        touch3: 'MEP',
        ios2: 'iOS',
        fdrmobile: 'MEP',
        fdrios: 'MEP',
        fdrandroid: 'android_apk',
        androidwrapper: 'android_gps',
        tvgandroid: 'android_apk',
        iosnative: 'ios_native'
      };
      return productKeys[product] ? productKeys[product] : product.toUpperCase();
    }

    function isTVG4() {
      return $rootScope.layout === 'desktop';
    }

    return {
      sendGTMEvent: _sendGTMEvent,
      gtmCurrencyFormat: _gtmCurrencyFormat,
      formatGALAbelUpperCase: _formatGALAbelUpperCase,
      isTVG4: isTVG4,
      getSiteVersion: _getSiteVersion,
      getProduct: _getProduct
    };
  }

  angular.module('TVG.Withdraw').factory('ApiWithdrawGTMFac', ApiWithdrawGTMFac);
}());

(function () {
  'use strict';

  applePayFac.$inject = ['$compile', '$rootScope', 'NotificationService', 'ApiDepositsGTMFac', 'Utilities', 'ConfigurationFac', 'APPLE_PAY_VERSION', '$q', '$http', '$filter', '$document', '$window'];
  function applePayFac(
    $compile,
    $rootScope,
    NotificationService,
    ApiDepositsGTMFac,
    Utilities,
    ConfigurationFac,
    APPLE_PAY_VERSION,
    $q,
    $http,
    $filter,
    $document,
    $window
  ) {
    var brainTreeEndpoint = Utilities.endpoint('brt');
    var applepay = {};

    /* This variables are meant for Apple Pay quick deposits swift implementation,
     so we can have a reference of this values instead of duplicating functions */
    var iOSdepositAmount = '';
    var iOSaccountNumber = '';
    var iOScontext = '';
    var iOSsuccessCallback = null;

    /**
     * Get labels from CMS
     * @param  {string} name
     * @return {[string]}      [label]
     */
    var getFromCMS = function (name) {
      return $filter('CMSLabels')(name, 'applepayLabels');
    };

    /**
     * Create an API error instance
     * Try to fetch an error message from the CMS (using the error code)
     * If none is found, use the error.message as a fallback
     *
     * @param  {Array} errors [description]
     * @return {Error}     [description]
     */
    var createApiError = function (data) {
      var apiError = new Error();
      var error = data[0] || {};
      var applePayError = getFromCMS(error.code);

      apiError.message = applePayError || error.message;
      apiError.code = error.code;
      apiError.data = error.data || {};
      return apiError;
    };

    var checkError = function (response) {
      return $q(function (resolve, reject) {
        return reject(createApiError([{
          message: _.get(response, 'data.message'),
          code: response.status,
          data: response.data
        }]));
      });
    };

    /**
     * Add the headers needed to perform API calls
     *
     * @return {object}: Header Object
     */
    var addHeaders = function (options) {
      var headers = {
        'x-tvgcontext': angular.toJson(ConfigurationFac.getApplicationContext())
      };

      if (Utilities.prop('cache', options)) {
        headers = _.extend({}, {
          'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
          'Cache-Control': 'no-cache',
          Pragma: 'no-cache'
        }, headers);
      }
      return headers;
    };

    /**
     * request
     * @param  {Object} data
     * @param  {string} data.url
     * @param  {string} data.method
     * @param  {Object} data.data
     *
     * @return {Promise}
     */
    var request = function (params) {
      var defaults = {
        headers: addHeaders(),
        method: 'POST'
      };

      return $http(_.extend({}, defaults, params))
        .catch(function (err) {
          return checkError(err);
        })
        .then(function (response) {
          response.data = _.assign({}, response.data, { statusCode: response.status });
          return response;
        })
        .then(Utilities.prop('data'));
    };

    var getToken = function (accountNumber) {
      var path = 'users/' + accountNumber + '/client-token';

      return request({
        url: brainTreeEndpoint(path),
        method: 'GET'
      })
        .then(Utilities.prop('token'));
    };

    var applePayDepositAttempt = function (depositAmount, isInQuickDeposits) {
      ApiDepositsGTMFac.sendGTMEvent('deposit', {
        gaEventCategory: 'Deposit',
        gaEventAction: 'Apple Pay Attempt',
        gaEventLabel: undefined,
        depositType: 'Apple Pay',
        module: isInQuickDeposits ? 'Quick Deposit' : 'My Funds',
        depositAmount: depositAmount
      });
    };

    var applePayDepositFailAPI = function (depositAmount, isInQuickDeposits, error) {
      ApiDepositsGTMFac.sendGTMEvent('deposit', {
        event: 'deposit',
        gaEventCategory: 'Deposit',
        gaEventAction: 'Apple Pay Error',
        gaEventLabel: error,
        depositType: 'Apple Pay',
        module: isInQuickDeposits ? 'Quick Deposit' : 'My Funds',
        depositAmount: depositAmount
      });
    };

    var applePayDepositPanelOpen = function (depositAmount, isInQuickDeposits) {
      ApiDepositsGTMFac.sendGTMEvent('deposit', {
        gaEventCategory: 'Deposit',
        gaEventAction: 'Open',
        gaEventLabel: 'Apple Pay',
        depositType: 'Apple Pay',
        module: isInQuickDeposits ? 'Quick Deposit' : 'My Funds',
        depositAmount: depositAmount
      });
    };

    /**
     * Send nonce from braintree payment
     * @param  {String} accountNumber
     * @param  {String} nonce
     * @param  {String} amount
     * @param  {String} deviceData
     * @return {String} BrainTree token
     */
    var sendNonce = function (accountNumber, nonce, amount, deviceData) {
      var path = 'users/' + accountNumber + '/deposits';

      return request({
        url: brainTreeEndpoint(path),
        method: 'POST',
        data: {
          nonce: nonce,
          amount: amount,
          deviceData: deviceData
        }
      })
        .then(Utilities.prop('balance'));
    };

    /**
     * Method to handle the sightline workaround modal
     * @param {object} applePayErrorModalConfigParam
     * @return null
     */
    var setErrorModal = function (applePayErrorModalConfigParam) {
      $window.ReactInjector.renderApplePayRedirect(
        document.getElementById('injected-modal'), //eslint-disable-line
        {
          sharedState: { isOpen: true },
          title: 'Deposit Declined',
          buttonText: applePayErrorModalConfigParam.buttonText,
          buttonTextSecond: applePayErrorModalConfigParam.buttonTextSecond,
          buttonTextCustomerSupport: applePayErrorModalConfigParam.buttonTextCustomerSupport,
          buttonCallback: applePayErrorModalConfigParam.buttonCallback,
          buttonCallbackSecond: applePayErrorModalConfigParam.buttonCallbackSecond,
          buttonCallbackCustomerSupport: applePayErrorModalConfigParam.buttonCallbackCustomerSupport, // eslint-disable-line
          textMain: applePayErrorModalConfigParam.textMain,
          textCustomerSupport: applePayErrorModalConfigParam.textCustomerSupport

        }
      );
    };

    /**
     * Method to submit the nonce generated from the Braintree to our BE
     * @param {string} nonce
     * @param {string} accountNumber
     * @param {string} depositAmount
     * @param {string} deviceData
     * @param {any} session
     * @param {string} context
     * @param {function} successCallback
     * @param {object} applePayErrorModalConfigParam
     * @param {boolean} isInQuickDeposits
     * @return null
     */
    var sendNonceToBE = function (
      nonce,
      session,
      accountNumber,
      depositAmount,
      deviceData,
      context,
      successCallback,
      applePayErrorModalConfigParam,
      isInQuickDeposits
    ) {
      sendNonce(
        accountNumber,
        nonce,
        depositAmount,
        deviceData
      )
        .then(function (data) {
          // call `completePayment` to dismiss the Apple Pay sheet.
          session.completePayment($window.ApplePaySession.STATUS_SUCCESS);

          // has to be called before the NotificationService or it will hide it
          if (angular.isFunction(successCallback)) {
            successCallback(data);
          }

          NotificationService.success(
            null,
            getFromCMS('transactionSuccessful'),
            context
          );

          ApiDepositsGTMFac.sendGTMEvent('deposit', {
            event: 'deposit',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Success',
            gaEventLabel: undefined,
            depositType: 'Apple Pay',
            module: isInQuickDeposits ? 'Quick Deposit' : 'My Funds',
            depositAmount: data
          });
        })
        .catch(function (error) {
          var data = error.data || {};

          switch (data.code) {
            case 159407:
            case 159500:
            case 159501:
            case 159502:
              // Braintree error
              if (!isInQuickDeposits) {
                setErrorModal(applePayErrorModalConfigParam);
              }
            default: // eslint-disable-line
              NotificationService.error(
                null,
                getFromCMS(data.code) || getFromCMS('generalError'),
                context
              );
          }

          ApiDepositsGTMFac.sendGTMEvent('deposit', {
            event: 'deposit',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Error',
            gaEventLabel: data.exception,
            depositType: 'Apple Pay',
            module: isInQuickDeposits ? 'Quick Deposit' : 'My Funds',
            depositAmount: depositAmount
          });

          session.abort();
        });
    };

    /**
     * Method to submit the nonce generated from the Braintree to our BE from our iOS implementation
     * @param {string} nonce
     * @param {string} deviceData
     * @return null
     */
    var iOSQuickDepositSendNonceToBE = function (
      nonce,
      deviceData
    ) {
      sendNonce(
        iOSaccountNumber,
        nonce,
        iOSdepositAmount,
        deviceData
      )
        .then(function (data) {
          // TODO: handle post message origins with configuration
          if ($window.parent) {
            $window.parent.postMessage({
              isSuccessful: true
            }, '*');
          }

          if (angular.isFunction(iOSsuccessCallback)) {
            iOSsuccessCallback(data);
          }

          NotificationService.success(
            null,
            getFromCMS('transactionSuccessful'),
            iOScontext
          );


          ApiDepositsGTMFac.sendGTMEvent('deposit', {
            event: 'deposit',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Success',
            gaEventLabel: undefined,
            depositType: 'Apple Pay',
            module: 'Quick Deposit',
            depositAmount: data
          });
        })
        .catch(function (error) {
          var data = error.data || {};
          // TODO: handle post message origins with configuration
          if ($window.parent) {
            $window.parent.postMessage({
              isSuccessful: false
            }, '*');
          }

          NotificationService.error(
            null,
            getFromCMS(data.code) || getFromCMS('generalError'),
            iOScontext
          );

          ApiDepositsGTMFac.sendGTMEvent('deposit', {
            event: 'deposit',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Error',
            gaEventLabel: data.exception,
            depositType: 'Apple Pay',
            module: 'Quick Deposit',
            depositAmount: iOSdepositAmount
          });
        });
    };

    /**
     * Method to send when we submit the nonce to BE, this is just for security reasons https://developers.braintreepayments.com/guides/advanced-fraud-management-tools/device-data-collection/javascript/v3
     * @param {any} client
     * @return Promise
     */
    applepay.createDataCollector = function (client) {
      var deferred = $q.defer();

      $window.braintree.dataCollector.create({
        client: client,
        applepay: true
      })
        .then(function (dataCollectorInstance) {
          deferred.resolve(dataCollectorInstance.deviceData);
        })
        .catch(function (error) {
          deferred.resolve(error);
        });

      return deferred.promise;
    };

    function handlePostMessageQuickDeposits(event) {
      var data = event.data;
      var payload = data.payload;

      if (payload.message === 'braintreeClientFailed') {
        applepay.handleNativeApplePayFailure(iOScontext);
      }

      if (payload.message === 'paymentRequestInvalid') {
        applepay.handleNativePaymentRequestInvalid(iOScontext);
      }

      if (payload.message === 'applePayPanelOpen') {
        applePayDepositPanelOpen(iOSdepositAmount, true);
      }

      if (payload.message === 'applePayAttempt') {
        applePayDepositAttempt(iOSdepositAmount, true);
      }

      if (payload.message === 'applePayAPIFail') {
        applePayDepositFailAPI(iOSdepositAmount, true, 'payment failed');
      }

      // Swift is submitting a payment so lets send to the BE
      if (payload.nonce && payload.deviceData) {
        iOSQuickDepositSendNonceToBE(
          payload.nonce,
          payload.deviceData
        );
      }
    }

    /**
     * Method to disable Apple Pay button if braintree client fails inside iOS and trigger error message for quick deposits
     * @param {string} context
     * @return {null}
     */
    applepay.handleNativeApplePayFailure = function (context) {
      // Variable to control apple pay native iOS instance
      applepay.iosApplePayInstanceFailure = true;

      NotificationService.error(
        null,
        getFromCMS('quickDepositsBraintreeClientFailMessage'),
        context
      );
    };

    /**
     * Method to throw error message of something went wrong when payment request is mounted incorrectly
     * @param {string} context
     * @return {null}
     */
    applepay.handleNativePaymentRequestInvalid = function (context) {
      NotificationService.error(
        null,
        getFromCMS('defaultError'),
        context
      );
    };

    /**
     * Creates a client instance of BrainTree
     * @param {string} accountNumber
     * @param {boolean} isInQuickDeposits
     * @param {function} handleBraintreeClientError
     * @param {string} context
     * @return Promise
     */
    applepay.createClientInstance = function (
      accountNumber,
      isInQuickDeposits,
      handleBraintreeClientError,
      context
    ) {
      var deferred = $q.defer();
      var braintreeClientInstance = null;

      getToken(accountNumber)
        .then(function (token) {
          if ($rootScope.product === 'ios2' && isInQuickDeposits) {
            iOScontext = context;

            $window.addEventListener('message', handlePostMessageQuickDeposits, false);

            // TODO: handle post message origins with configuration
            if ($window.parent) {
              $window.parent.postMessage({
                initBrainTreeIOS: token
              }, '*');
            }
          } else {
            $window.braintree.client.create({
              authorization: token
            })
              .then(function (clientInstance) {
                braintreeClientInstance = clientInstance;

                return $window.braintree.applePay.create({
                  client: clientInstance
                });
              })
              .then(function (applePayInstance) {
                return deferred.resolve({
                  applePayInstance: applePayInstance,
                  braintreeClientInstance: braintreeClientInstance
                });
              })
              .catch(function (err) {
                deferred.resolve(err);

                if (angular.isFunction(handleBraintreeClientError)) {
                  handleBraintreeClientError();
                } else {
                  NotificationService.error(
                    null,
                    getFromCMS('defaultError'),
                    context
                  );
                }
              });
          }
        })
        .catch(function (err) {
          if (angular.isFunction(handleBraintreeClientError)) {
            handleBraintreeClientError();
          } else {
            NotificationService.error(
              null,
              getFromCMS('quickDepositsBraintreeClientFailMessage'),
              context
            );
          }

          deferred.resolve(err);
        });

      return deferred.promise;
    };

    /**
     * Method that handles the onClick of apple pay button
     * @param {any} applePayInstance
     * @param {string} depositAmount
     * @param {string} fee
     * @param {string} feeDiscount
     * @param {string} accountNumber
     * @param {string} deviceData
     * @param {string} context
     * @param {function} successCallback
     * @param {object} applePayErrorModalConfigParam
     * @param {boolean} isInQuickDeposits
     * @return null
     */
    applepay.onApplePayDeposit = function (
      applePayInstance,
      depositAmount,
      fee,
      feeDiscount,
      accountNumber,
      deviceData,
      context,
      successCallback,
      applePayErrorModalConfigParam,
      isInQuickDeposits
    ) {
      var paymentRequest;
      var session;

      ApiDepositsGTMFac.sendGTMEvent('siteClick', {
        event: 'deposit',
        gaEventCategory: 'Deposit',
        gaEventAction: 'Deposit Attempt',
        gaEventLabel: 'Deposit Attempt',
        depositType: 'Apple Pay',
        module: isInQuickDeposits ? 'Quick Deposit' : 'My Funds',
        depositAmount: depositAmount
      });

      // We handle iOS quick deposits natively
      if ($rootScope.product === 'ios2' && isInQuickDeposits) {
        // TODO: handle post message origins with configuration
        if ($window.parent) {
          $window.parent.postMessage({
            amount: depositAmount,
            label: 'TVG'
          }, '*');

          // Lets save our vars to the scope so we can access when trying to submit the nonce

          iOSaccountNumber = accountNumber;
          iOSdepositAmount = depositAmount;
          iOScontext = context;
          iOSsuccessCallback = successCallback;
        }
      } else {
        paymentRequest = applePayInstance.createPaymentRequest({
          total: {
            label: 'TVG',
            amount: depositAmount + fee - feeDiscount
          }
        });
        session = new $window.ApplePaySession(APPLE_PAY_VERSION, paymentRequest);

        NotificationService.clearBanner();

        // Validate merchant
        session.onvalidatemerchant = function (event) {
          applePayDepositPanelOpen(depositAmount, isInQuickDeposits);

          applePayInstance.performValidation({
            validationURL: event.validationURL,
            displayName: 'TVG'
          })
            .then(function (merchantSession) {
              session.completeMerchantValidation(merchantSession);
            })
            .catch(function () {
              NotificationService.error(
                null,
                getFromCMS('defaultError'),
                context
              );
              session.abort();
            });
        };

        session.onpaymentauthorized = function (event) {
          applePayDepositAttempt(depositAmount, isInQuickDeposits);

          applePayInstance.tokenize({
            token: event.payment.token
          })
            .then(function (payload) {
              // Send nonce to BE
              sendNonceToBE(
                payload.nonce,
                session,
                accountNumber,
                depositAmount,
                deviceData,
                context,
                successCallback,
                applePayErrorModalConfigParam,
                isInQuickDeposits
              );
            })
            .catch(function (error) {
              applePayDepositFailAPI(depositAmount, isInQuickDeposits, error);

              NotificationService.error(
                null,
                getFromCMS('generalError'),
                context
              );
              session.completePayment($window.ApplePaySession.STATUS_FAILURE);
            });
        };

        session.begin();
      }

      ApiDepositsGTMFac.sendGTMEvent('deposit', {
        gaEventCategory: 'Deposit',
        gaEventAction: 'Open',
        gaEventLabel: undefined,
        depositType: 'Apple Pay',
        module: isInQuickDeposits ? 'Quick Deposit' : 'My Funds',
        depositAmount: depositAmount
      });
    };

    return applepay;
  }

  angular
    .module('TVG.Deposit')
    .factory('ApplePayFac', applePayFac);
}());

'use strict';

angular.module('TVG.Deposit')
  .constant('SightlineDepositConfig', {
    ftype: 'SLN',
    name: 'TVG Pre Paid Card',
    id: 99999999999, // @TODO check if this is ok (needed in quick-deposit)
    limitTypeId: 12,
    min: 10,
    max: 25000,
    depositTypeId: 12
  })
  .constant('PaypalDepositConfig', {
    ftype: 'PAY',
    name: 'PayPal',
    id: 0,
    min: 5,
    max: 100000,
    limitTypeId: 13,
    depositTypeId: 13
  })
  .constant('ApplePayDepositConfig', {
    ftype: 'APPL',
    name: 'ApplePay',
    id: 0,
    min: 3,
    max: 25000,
    limitTypeId: 11,
    depositTypeId: 11
  })
  .constant('DMAScreenNames', {
    'my-profile': 'My Account',
    'my-tracks': 'My Account',
    'my-favorite-tracks': 'My Account',
    'my-funds': 'My Account',
    'my-bets': 'My Account',
    'my-account-summary': 'My Account',
    'my-stable': 'My Account',
    races: 'Races',
    race: 'Program',
    handicapping: 'Handicapping',
    info: 'Site Info',
    home: 'Home',
    results: 'Races',
    betslip: 'Bet Ticket',
    promotions: 'Promotions',
    'password-recovery': 'Credentials Recovery',
    'forgot-credentials': 'Credentials Recovery',
    'reset-credentials': 'Credentials Recovery',
    registration: 'Registration'
  })
  .constant('DMASectionNames', {
    'my-profile': {
      translation: 'My Account',
      'my-tracks': 'My Tracks',
      'my-favorite-tracks': 'My Favorite Tracks',
      funds: 'My Funds',
      'my-bets': 'My Bets',
      'my-account-summary': 'My Account Summary',
      profile: 'My Profile',
      deposit: 'Deposit',
      bank: 'Payment Management',
      withdraw: 'Withdraw',
      'my-stable': 'My Stable'
    },
    handicapping: {
      translation: 'Handicapping',
      'handicapping-store': 'Handicapping Store',
      'free-pp': 'Free Past Performances',
      talentpicks: 'Talent Picks',
      racereplays: 'Race Replays'
    },
    promotions: {
      translation: 'Promotions',
      'wager-rewards': 'Wager Rewards'
    },
    horseracing: {
      translation: 'Races',
      races: 'Full Schedule',
      results: 'Results'
    },
    home: {
      translation: 'Home | Home Page'
    },
    programpage: {
      translation: 'Program Page'
    },
    siteinfo: {
      translation: 'Site Info',
      privacypolicy: 'Privacy Policy',
      wagerresponsibly: 'Wager Responsibly',
      termsandconditions: 'Terms and Conditions'
    },
    betslip: {
      translation: 'Bet Ticket',
      default: 'Bet Ticket Page'
    },
    'password-recovery': {
      translation: 'Info'
    },
    'reset-credentials': {
      translation: 'Credentials Setup'
    },
    'forgot-credentials': {
      translation: 'Credentials Recovery | Start'
    },
    registration: {
      translation: 'Registration'
    }
  })
  .constant('depositMinAmountOverrides', [
    { depositType: 'ACH', minLimit: 5.00 },
    { depositType: 'CC', minLimit: 5.00 },
    { depositType: 'CCS', minLimit: 5.00 },
    { depositType: 'DEB', minLimit: 5.00 },
    { depositType: 'DEBS', minLimit: 5.00 },
    { depositType: 'CHK', minLimit: 5.00 },
    { depositType: 'IBC', minLimit: 5.00 },
    { depositType: 'PAY', minLimit: 5.00 },
    { depositType: 'SLP', minLimit: 10.00 }
    // { depositType: 'MPAK', minLimit: 0.00 },
    // { depositType: 'OTR', minLimit: 0.00 },
    // { depositType: 'PNM', minLimit: 0.00 },
    // { depositType: 'VIWD', minLimit: 0.00 }
  ])
  .constant('DEPOSIT_TYPES', {
    ACH_ON_FILE: 1,
    ACH_NEW: 2, // or 'INSTANT_BETCASH'?
    CARD_ON_FILE: 3,
    CARD_NEW: 4,
    GREENDOT_MONEY_PAK: 5,
    CREDIT_CARD_NEW: 6,
    OTHER: 9,
    APPLE_PAY: 11,
    SIGHTLINE: 12, // should match SightlineDepositConfig.depositTypeId
    SIGHTLINE_V2: 13, // should match SightlineDepositConfig.depositTypeId
    PAYPAL: 13
  })
  .constant('APPLE_PAY_VERSION', 3)
  .constant('DepositPath', {
    tvg4: '/my-funds/deposit',
    touch2: '/deposit',
    touch3: '/deposit',
    ios: '/deposit/deposit',
    ios2: '/deposit',
    njx: '/deposit/deposit',
    fdrmobile: '/deposit',
    fdrios: '/deposit',
    fdrandroid: '/deposit',
    androidwrapper: '/deposit',
    tvgandroid: '/deposit'
  });

(function () {
  'use strict';

  DepositSrv.$inject = ['$http', '$q', '$filter', '$window', '$rootScope', 'Utilities', 'ConfigurationFac', 'DepositInitialDataFac', 'ApiDepositsGTMFac', 'SightlineSrv', 'UserFactory', 'DEPOSIT_TYPES', 'RequestContextHeaders', 'APPLE_PAY_VERSION', '$uibModal', '$location'];
  function DepositSrv(
    $http,
    $q,
    $filter,
    $window,
    $rootScope,
    Utilities,
    ConfigurationFac,
    DepositInitialDataFac,
    ApiDepositsGTMFac,
    SightlineSrv,
    UserFactory,
    DEPOSIT_TYPES,
    RequestContextHeaders,
    APPLE_PAY_VERSION,
    $uibModal,
    $location
  ) {
    var goToSln = false;
    var _depositInitialData = null;
    var tmpAmount = 0;
    var _transactionFee = 0;
    var _FeeDiscount = 0;
    var deposits = {
      user: UserFactory.build({}),
      accountId: null,
      gtmDepositErrorEvent: function () {
        return _gtmDepositErrorEvent();
      },
      getApplicationContextItem: function (item) {
        return ConfigurationFac.getApplicationContextItem(item);
      },
      getDepositDataConfig: function () {
        return _depositInitialData;
      },

      getInitialData: function () {
        deposits.accountId = '';
        return deposits.getAccountNumber().then(function (accountId) {
          deposits.accountId = accountId;
          return deposits.getProfile(accountId).then(function (data) {
            data.accountNumber = deposits.accountId;
            deposits.user = UserFactory.build(data);
            $rootScope.userSession = true;
            $rootScope.user = deposits.user;

            SightlineSrv
              .getSightlineFlowVersion(accountId).then(function (version) {
                $rootScope.sightlineFlowVersion = version;
                $rootScope.sightlineLoaded = true;
                return deposits.user;
              }).catch(function () {
                $rootScope.sightlineVersion = undefined;
              });
          });
        })
        .then(function () {
          return deposits.getStates();
        })
        .then(function (states) {
          return deposits.getDepositOptions(states);
        });
      },

      getProfile: function (accountId) {
        var url = '/uam/v1/users/' + accountId + '/profile';
        url = ConfigurationFac.getBaseServiceUrl() + url;
        return $http({
          method: 'GET',
          url: url,
          headers: _addHeaders()
        }).then(function (res) {
          return res.data;
        });
      },

      getUserPaymentDefault: function () {
        var url = '/uam/v1/users/' + deposits.user.get('accountNumber') + '/preferences/defaultPaymentMethod';
        url = ConfigurationFac.getBaseServiceUrl() + url;
        return $http({
          method: 'GET',
          url: url,
          headers: _addHeaders()
        }).then(function (res) {
          return Utilities.prop('preferences[0].value', res.data);
        }).catch(function () {
          return null;
        });
      },

      setUserPaymentDefault: function (paymentMethod) {
        var url = '/uam/v1/users/' + deposits.user.get('accountNumber') + '/preferences';
        url = ConfigurationFac.getBaseServiceUrl() + url;
        return $http({
          method: 'PUT',
          url: url,
          headers: _addHeaders(),
          data: {
            preferences: [
              {
                description: 'defaultPaymentMethod',
                metadata: angular.toJson(paymentMethod) || ''
              }
            ]
          }
        }).then(function () {
          return true;
        }).catch(function () {
          return false;
        });
      },

      getStates: function () {
        var url = '/uam/v1/states';
        url = ConfigurationFac.getBaseServiceUrl() + url;
        return $http({
          method: 'GET',
          url: url,
          headers: _addHeaders()
        }).then(function (res) {
          return res.data && res.data.states || [];
        });
      },

      buildAccountDetails: function () {
        var accDetails = {};
        if (deposits.user) {
          accDetails.accountHState = deposits.user.homeAddress.state;
          accDetails.accountNumber = deposits.user.accountNumber;
          accDetails.accountUsername = deposits.user.username;
        }
        return accDetails;
      },

      getDepositOptions: function (states) {
        var deferred = $q.defer();
        var accountId = deposits.user.get('accountNumber');
        var url = walletEndpoint('users') + '/' + accountId + '/deposit-options/';
        var urlMerchantId = brainTreeEndpoint('merchant');
        var headers = _addHeaders({ cache: true });
        var successCallback = function (depositOptionsData, canMakePaymentsWithActiveCard) {
          var cmsConfig = Utilities.attempt(
            function () {
              return angular.fromJson(
                $filter('CMSValue')('depositConfigAvailableOptions'));
            },
            function () {
              return ['IBC', 'CC', 'ACH', 'SLN'];
            }
          );

          var initialData = Object.assign(
            {
              accountDetails: deposits.buildAccountDetails(),
              states: DepositInitialDataFac.parseStates(states || [])
            },
            DepositInitialDataFac.buildPaymentOptions(
              depositOptionsData,
              cmsConfig,
              canMakePaymentsWithActiveCard
            )
          );

          _depositInitialData = initialData;

          deferred.resolve(initialData);
        };

        /* eslint-disable */
        $http.get(url, { headers: headers }).success(function (depositOptionsData) {
          if (
            $window.ApplePaySession &&
            $window.ApplePaySession.supportsVersion(APPLE_PAY_VERSION)
          ) {
            $http.get(urlMerchantId, { headers: headers }).success(function (data) {
              return $window.ApplePaySession.canMakePaymentsWithActiveCard(
                'merchant.' + data.merchantId
              )
                .then(function (canMakePaymentsWithActiveCard) {
                  console.log('Can make payments with active card', canMakePaymentsWithActiveCard); //eslint-disable-line
                  successCallback(depositOptionsData, canMakePaymentsWithActiveCard);
                });
            }).error(function () {
              successCallback(depositOptionsData);
            });
          } else {
            successCallback(depositOptionsData);
          }
        }).error(function (data) {
          deferred.reject(data);
        });

        return deferred.promise;
      },


      /**
       * Get deposit initial data:
       * - available payment options
       * - available payment options from CMS
       * - card types hash
       * - payment types hash
       * (...)
       *
       * @return {Promise}
       */
      getDepositInitialData: function () {
        var deferred = $q.defer();
        var url = _baseUrl() + 'depositInitialData?showAccountDetails=true';
        var headers = _addHeaders({ cache: true });

        // @TODO: may be factored to remove promise and use $http only?
        /* eslint-disable */
        $http.get(url, { headers: headers }).success(function (data) {
        /* eslint-enable */
          var cmsConfig;
          var restrictedDepositTypes;
          var message;

          if (data.status === 'success') {
            deposits.user = UserFactory.build(data.response.accountDetails);
            _depositInitialData = data.response;

            cmsConfig = Utilities.attempt(
              function () {
                return angular.fromJson(
                  $filter('CMSValue')('depositConfigAvailableOptions'));
              },
              function () {
                return ['IBC', 'CC', 'ACH'];
              }
            );

            restrictedDepositTypes = DepositInitialDataFac
              .getDepositRestrictedTypes(data.response, cmsConfig);

            cmsConfig = cmsConfig.filter(function (value) {
              return restrictedDepositTypes.indexOf(value) === -1;
            });

            if (cmsConfig.length === 0) {
              return deferred.reject('depositRestrictions');
            }

            if (cmsConfig.indexOf('ACH') === -1) {
              /* eslint-disable */
              data.response.achOnFile = [];
              /* eslint-enable */
            }

            deferred.resolve(DepositInitialDataFac.buildInitialData(
              data.response,
              _getTypeEnumMapValues(),
              cmsConfig)
            );

            deposits.updateCustomerStatus();
          } else {
            message = Utilities.prop('response.errorMessage', data) ||
              'UnknownError';

            _gtmDepositErrorEvent(
              ApiDepositsGTMFac.formatGALAbelUpperCase(message), data);

            deferred.reject(data);
          }
        }).error(function (data) {
          var message = Utilities.prop('response.errorMessage', data) ||
            'UnknownError';

          _gtmDepositErrorEvent(
            ApiDepositsGTMFac.formatGALAbelUpperCase(message), data);

          deferred.reject(data);
        });

        return deferred.promise;
      },
        /**
       * Get deposit status after transferToTVG with the new deposit flow
       */
      getDepositStatus: function (url) {
        var accountId = deposits.user.get('accountNumber');
        var uuid = url.split('deposits/').length > 0 ? (url.split('deposits/')[1].split('/status')[0]) : null;
        var locationUrl = url;
        if (!locationUrl.contains('http') && uuid) {
          locationUrl = walletEndpoint('users') + '/' + accountId + '/deposits/' + uuid + '/status';
        }
        return request({
          url: locationUrl,
          method: 'GET'
        });
      },
        /**
       * Get user account number incase it's not previously loaded
       */
      getAccountNumber: function () {
        return request({
          url: usaEndpoint('session') + '/context',
          method: 'GET'
        }).then(function (data) {
          if (data.accountNumber) {
            deposits.accountId = data.accountNumber;
            $rootScope.userSession = true;
            if (!$rootScope.user) {
              $rootScope.user = {accountNumber:  data.accountNumber};
            } else {
              $rootScope.user.accountNumber = data.accountNumber
            }
          }
          return data.accountNumber;
        }).catch(function (err) {
          return err;
        });
      },
      getDepositFee: function (depositType, amount) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var config = { headers: headers };
        var accountId = deposits.user.get('accountNumber');
        var url;
        var newFeeEndpoint = false;

        switch (depositType) {
          case 1: // IBC
            url = achEndpoint('users') + '/' + accountId + '/deposits/fee';
            config.params = { depositAmount: amount };
            newFeeEndpoint = true;
            break;
          case 4: // ACH
            url = achEndpoint('users') + '/' + accountId + '/deposits/fee';
            config.params = { depositAmount: amount };
            newFeeEndpoint = true;
            break;
          case 12: // SLN
            url = sightlineEndpoint('user') + '/' + accountId + '/deposit/fee';
            config.params = { depositAmount: amount };
            newFeeEndpoint = true;
            break;
          case 2: // CC
              url = ccpEndpoint('users') + '/' + accountId + '/deposits/fee';
              config.params = { depositAmount: amount };
              newFeeEndpoint = true;
              break;
          case 3: // DEB
              url = ccpEndpoint('users') + '/' + accountId + '/deposits/fee';
              config.params = { depositAmount: amount };
              newFeeEndpoint = true;
              break;
          case 11: // APPL
            url = brainTreeEndpoint('users') + '/' + accountId + '/deposits/fees';
            config.params = {
              paymentType: 'APPL',
              amount: amount
            };
            newFeeEndpoint = true;
            break;
          default:
            return deferred.promise;
        }

        $http.get(url, config)
          .success(function (data) {
            if (newFeeEndpoint) {
              _transactionFee = data.feeAmount || 0;
              _FeeDiscount = data.feeRefundAmount || 0;
              data.useNewFeeFlow = true;
              data.RequestedAmount = amount;
              deferred.resolve(_depositTransactionFeeBuilder(
                data, depositType));
            } else {
              if (data.status === 'success') {
                _transactionFee = Utilities.prop('response.Fee', data) || 0;
                _FeeDiscount = Utilities.prop('response.FeeDiscount', data) || 0;
                deferred.resolve(_depositTransactionFeeBuilder(
                  data.response, depositType));
              } else {
                deferred.reject(data);
              }
            }
          }).error(function (data) {
            deferred.reject(data);
          });

        return deferred.promise;
      },

      makeCreditDebitDepositNewFlow: function (
                                        amount,
                                        bankName,
                                        cardNumber,
                                        cardTypeId,
                                        nameOnCard,
                                        cardVerificationNumber,
                                        month,
                                        year,
                                        cardTypeDesc,
                                        sightlineFlowVersion) {
        var accountId = deposits.user.get('accountNumber');
        var url = ccpEndpoint('users') + '/' + accountId + '/deposit';
        var prefixPattern = /^(6|60|601|6011|65|64|64[4-9]|622[126-925])$/;
        var exactPattern = /^(6011|65|6221|6229|64[4-9]|622[126-925])\d*$/;

        var cardType = cardTypeDesc;
        var isDiscoverCard = false;
        tmpAmount = amount;

        if (exactPattern.test(cardNumber) || prefixPattern.test(cardNumber)) {
          isDiscoverCard = true;
        }

        if (isDiscoverCard && sightlineFlowVersion === '1') {
          $rootScope.$emit('redirectSightline-discCard');
        } else {
          return request({
            url: url,
            method: 'POST',
            data: {
              cardNumber: cardNumber,
              cardType: cardType,
              cardVerificationNumber: cardVerificationNumber,
              nameOnCard: nameOnCard,
              bankName: bankName,
              amount: amount,
              expirationMonth: month,
              expirationYear: year.toString(),
              headers: _addHeaders()
            }
          }, true);
        }
        return $q.defer().promise;
      },

      makeCreditDebitDeposit: function (addCardOnFile,
                                        amount,
                                        bankName,
                                        cardNumber,
                                        cardTypeId,
                                        nameOnCard,
                                        cardVerificationNumber,
                                        expirationDate,
                                        makeTransfer) {
        var deferred = $q.defer();
        var depositToMake;
        var prefixPattern = /^(6|60|601|6011|65|64|64[4-9]|622[126-925])$/;
        var exactPattern = /^(6011|65|6221|6229|64[4-9]|622[126-925])\d*$/;

        var cardType = null;

        tmpAmount = amount;

        depositToMake = _newCreditDebitCard(
          bankName,
          cardNumber,
          cardTypeId,
          nameOnCard,
          cardVerificationNumber,
          expirationDate,
          '',
          ''
        );
        depositToMake.depositAndTransfer = makeTransfer || false;

        if (exactPattern.test(cardNumber) || prefixPattern.test(cardNumber)) {
          cardType = 'DISCOVER';
        }

        if (cardType && cardType === 'DISCOVER') {
          deferred.reject({
            oldCardDepositFlow: true,
            exceptionCode: 'OLD_CCP_DISCOVER_CARD'
          });

          return deferred.promise;
        } else {
          $http({
            method: 'POST',
            url: _baseUrl() + 'CreditOrDebitCard?addCardOnFile=' +
            (addCardOnFile === true ? 'true' : 'false') + '&amount=' + amount,
            data: depositToMake,
            headers: _addHeaders()
          }).success(function (data) {
            data.response.depositType = 'CreditOrDebitCard';

            if (data.status === 'success') {
              deferred.resolve(_depositSuccessBuilder(data.response));
            } else {
              _gtmDepositErrorEvent('Credit', data);
              deferred.reject(data.response);
            }
          }).error(function (response) {
            deferred.reject(response);
          });
        }
        return deferred.promise;
      },

      // Bet cash (other account)
      getBankName: function (routingNumber) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var url = achEndpoint('bank') + '/' + routingNumber;

        $http.get(url,
          { headers: headers })
          .success(function (data) {
            var resp;

            resp = {
              routingNumber: routingNumber,
              bankName: data.name
            };
            deferred.resolve(resp);
          }).error(function (data) {
            deferred.reject(data);
          });

        return deferred.promise;
      },
      makeInstantBetCashDeposit: function (
          pinOrPassword,
          bankName,
          checkingAccountNumber,
          bankRoutingNumber,
          driversLicenseNumber,
          driversLicenseStateAbbr,
          depositAmount,
          addCardOnFile,
          makeTransfer
        ) {
        var deferred = $q.defer();
        tmpAmount = depositAmount;

        $http({
          method: 'POST',
          url: _baseUrl() + 'InstantBetCash',
          data: {
            pinOrPassword: pinOrPassword,
            bankName: bankName,
            checkingAccountNumber: checkingAccountNumber,
            bankRoutingNumber: bankRoutingNumber,
            driversLicenseNumber: driversLicenseNumber,
            driversLicenseStateAbbr: driversLicenseStateAbbr,
            depositAmount: depositAmount,
            addCardOnFile: addCardOnFile,
            depositAndTransfer: makeTransfer || false
          },
          headers: _addHeaders()
        }).success(function (data) {
          var depositSuccess;

          /* eslint-disable */
          data.response.depositType = 'InstantBetCash';
          /* eslint-enable */

          if (data.status === 'success') {
            depositSuccess = {
              DepositResult: data.response
            };

            deferred.resolve(_depositSuccessBuilder(depositSuccess));
          } else {
            _gtmDepositErrorEvent('InstantBetCash', data);
            deferred.reject(data.response);
          }
        }).error(function (data) {
          deferred.reject(data);
        });

        return deferred.promise;
      },
      makeInstantBetCashDepositNewFlow: function (
          routingNumber,
          bankAccountNumber,
          licenseNumber,
          licenseState,
          depositAmount
        ) {
        var accountId = deposits.user.get('accountNumber');
        var url = achEndpoint('users') + '/' + accountId + '/deposits';
        var postData = {
          bankRoutingNumber: routingNumber,
          bankAccountNumber: bankAccountNumber,
          dlNumber: licenseNumber,
          dlState: licenseState,
          amount: depositAmount
        };
        tmpAmount = depositAmount;

        return request({
          url: url,
          method: 'POST',
          data: postData
        }, true);
      },
      makeCardOnFileDepositNewFlow: function (cvn, amount, cardId) {
        var accountId = deposits.user.get('accountNumber');
        var url = ccpEndpoint('users') + '/' + accountId + '/bankCard/' + cardId + '/deposit';
        tmpAmount = amount;
        return request({
          url: url,
          method: 'POST',
          data: {
            cardVerificationNumber: cvn,
            amount: amount,
            headers: _addHeaders()
          }
        }, true);
      },
      makeCardOnFileDeposit: function (cvn, amount, cardId) {
        var deferred = $q.defer();
        tmpAmount = amount;

        $http({
          method: 'POST',
          url: _baseUrl() + 'CardOnFile',
          data: {
            cvn: cvn,
            cardId: cardId,
            amount: amount
          },
          headers: _addHeaders()
        }).success(function (data) {
          data.response.depositType = 'CardOnFile';

          if (data.status === 'success') {
            deferred.resolve(_depositSuccessBuilder(data.response));
          } else {
            _gtmDepositErrorEvent('Credit', data);
            deferred.reject(data.response);
          }
        }).error(function (data) {
          deferred.reject(data);
        });

        return deferred.promise;
      },

      makeACHOnFileDepositNewFlow: function (
        amount,
        achOnFileID) {
        var postData = {
          amount: amount,
          headers: _addHeaders()
        };
        var accountId = deposits.user.get('accountNumber');
        var url = achEndpoint('users') + '/' + accountId + '/bankAccount/' + achOnFileID + '/deposits';
        tmpAmount = amount;

        return request({
          url: url,
          method: 'POST',
          data: postData
        }, true);
      },

      makeACHOnFileDeposit: function (
          driversLicenseNumber,
          amount,
          achOnFileID,
          driversLicenseStateAbbr
        ) {
        var deferred = $q.defer();
        var postData = {
          driversLicenseNumber: driversLicenseNumber,
          achOnFileID: achOnFileID,
          driversLicenseStateAbbr: driversLicenseStateAbbr,
          amount: amount
        };
        tmpAmount = amount;

        $http({
          method: 'POST',
          url: _baseUrl() + 'AchOnFile',
          data: postData,
          headers: _addHeaders()
        }).success(function (data) {
          var depositSuccess;
          data.response.depositType = 'AchOnFile'; // eslint-disable-line

          if (data.status === 'success') {
            depositSuccess = {
              DepositResult: data.response
            };
            deferred.resolve(_depositSuccessBuilder(depositSuccess));
          } else {
            _gtmDepositErrorEvent('BetCash', data);
            deferred.reject(data.response);
          }
        }).error(function (data) {
          deferred.reject(data);
        });

        return deferred.promise;
      },
      makeSightlineDeposit: function (sightlineUser, amount) {
        return SightlineSrv.transferToTVG(sightlineUser, amount);
      },

      /**
       * Get the templates' filenames that must be rendered for each
       * type of quick deposit.
       *
       * Names must match the files present in templates/deposit/fields/.
       * (see more in quick-deposit.html)
       *
       * @return {Object} Description labels for quick deposit view
       */
      getQuickDepositForms: function () {
        return {
          CC: [
            'card-description-text',
            'card-verification-number'
          ],
          SLN: [
            'card-verification-number'
          ],
          ACH: [
            'ach-description-text'
          ],
          APPL: [
            'applepay-description-text'
          ]
        };
      },

      /**
       * Get the templates' filenames that must be rendered for each
       * type of deposit.
       *
       * Names must match the files present in templates/deposit/fields/.
       * (see more in deposit.html)
       *
       * @return {Object} Description labels for deposit view
       */
      getDepositForms: function () {
        return {
          NEW: {
            CC: [
              'card-type-selector',
              'card-number-input',
              'card-exp-date-and-cvn'
            ],
            IBC: [
              'bank-routing-number',
              'bank-account-number',
              'bank-name',
              'driver-license-number',
              'driver-license-state'
            ]
          },
          STORED: {
            CC: [
              'card-onfile-selector',
              'card-verification-number'
            ]
          }
        };
      },

      getExpirationDateValues: _getExpirationDateValues,

      /**
       * Make deposit according to the deposit type ID
       * @param  {Object} depositData  Deposit information
       * @return {Promise}
       */
      makeDeposit: function (depositData) {
        var selected;
        var month;
        var promise;

        switch (depositData.depositTypeId) {
          case DEPOSIT_TYPES.ACH_ON_FILE:
            selected = depositData.selectedOnFile || {};
            promise = deposits.makeACHOnFileDepositNewFlow(
                          depositData.amount,
                          selected.achId
                        );
            break;

          case DEPOSIT_TYPES.ACH_NEW:
            selected = depositData.selectedOnFile || {};
            promise = deposits.makeInstantBetCashDepositNewFlow(
                          depositData.routingNumber,
                          depositData.accountNumber,
                          depositData.licenseNumber,
                          depositData.stateSelectedOption.abbreviation,
                          depositData.amount
                        );
            break;
          case DEPOSIT_TYPES.CARD_ON_FILE:
            promise = deposits.makeCardOnFileDepositNewFlow(
              depositData.cardSecurityNumber,
              depositData.amount,
              depositData.selectedOnFile.id
            );
            break;
          case DEPOSIT_TYPES.CARD_NEW:
            month = depositData.expirationMonth.toString();

            if (month.length === 1) {
              month = '0' + month;
            }

            promise = deposits.makeCreditDebitDepositNewFlow(
              depositData.amount,
              '',
              depositData.cardNumber.toString(),
              depositData.selectedCardType.cardTypeId,
              '',
              depositData.cardSecurityNumber,
              month,
              depositData.expirationYear,
              depositData.selectedCardType.type,
              $rootScope.sightlineFlowVersion
          );
            break;

          case DEPOSIT_TYPES.GREENDOT_MONEY_PAK:
            promise = deposits.makeGreenDotMoneyPakDeposit(
              depositData.amount, depositData.pakNumber
            );
            break;

          case DEPOSIT_TYPES.SIGHTLINE:
            promise = deposits.makeSightlineDeposit(
              depositData.sightlineUser,
              depositData.amount
            );
            break;

          case DEPOSIT_TYPES.SIGHTLINE_V2:
            promise = SightlineSrv.fundAndTransferToTVG(depositData);
            break;

          default:
            promise = $q.reject('Invalid deposit type selected');
            break;
        }

        return promise;
      },

      getAvailableAmountOptions: function (initialData) {
        var depositConfigAmountOptions = Utilities.attempt(
          function () {
            return angular.fromJson(
              $filter('CMSValue')('depositConfigAmountOptions'));
          },
          function () {
            return {
              firstTimeAmountList: [20, 50, 100],
              defaultAmountList: [20, 50, 100]
            };
          }
        );

        return initialData.madeFirstDeposit ?
          depositConfigAmountOptions.defaultAmountList :
          depositConfigAmountOptions.firstTimeAmountList;
      },
      setGoToSln: function (value) {
        goToSln = value;
      },
      getGoToSln: function () {
        var message = goToSln;
        goToSln = false;
        return message;
      },

      /**
       * Get the customer status from the the payment options
       * @return {String} Customer status
       */
      getCustomerStatus: function () {
        var hasInitialDeposit = this.getHasMadeInitialDeposit();
        return hasInitialDeposit ?
          'Returning' : 'First Time';
      },

      /**
       * Update CustomerStatus saved in rootScope
       */
      updateCustomerStatus: function () {
        $rootScope.hasInitialDeposit = deposits.getCustomerStatus();
      },

      /**
       * Get the "madeInitialDeposit" flag value
       * @return {Boolean}  Has the user made the initial deposit?
       */
      getHasMadeInitialDeposit: function () {
        if (!_depositInitialData || !_depositInitialData.availableOptions) {
          return false;
        }
        return !!_depositInitialData.availableOptions.HasMadeInitialDeposit;
      },

      /**
       * THIS FLAG WILL BE UPDATED WHEN A /depositInitialData is received
       *
       * Set the "madeInitialDeposit" flag value
       *
       * @param {Boolean} val  Value to set
       */
      _setHasMadeInitialDeposit: function (val) {
        // stop
        if (!_depositInitialData) { return this; }

        _depositInitialData.availableOptions = _depositInitialData.availableOptions || {};
        _depositInitialData.availableOptions.HasMadeInitialDeposit = !!val;

        return _depositInitialData.availableOptions.HasMadeInitialDeposit;
      },

      getDepositLandingTab: function (depositOptions, loadEnv) {
        var depositLandingTab = '';
        var initialTab = $location.search().initialTab;

        if(initialTab) {
          return {depositLandingTab: initialTab};
        }

        try {
          var message =  loadEnv === 'registration' ?
            $filter('CMSValue')('RMADefaultDepositLandingTab') :
            $filter('CMSValue')('DMADefaultDepositLandingTab');
          var capiDefaults = JSON.parse(message);

          var canUserMakeApplePayPayments = $window.ApplePaySession && ApplePaySession.supportsVersion(3) && $window.ApplePaySession.canMakePayments();

          // check if first default is Apple Pay and if it is check if safari is available
          if (capiDefaults.firstDefault === 'APPL' && canUserMakeApplePayPayments) {
            depositLandingTab = capiDefaults.firstDefault;
          } else if (capiDefaults.firstDefault === 'APPL' && !canUserMakeApplePayPayments) {
            depositLandingTab = capiDefaults.secondDefault;
          } else if (capiDefaults.firstDefault !== 'APPL') {
            depositLandingTab = capiDefaults.firstDefault;
          }
        } catch (e) {
          // Common default case when json is wrong in CAPI message
          depositLandingTab = 'CC';
        }

        var accountId = deposits.accountId;
        var deferred = $q.defer();
        var url = walletEndpoint('users') + '/' + accountId + '/deposits';
        var headers = { 'Content-Type': 'application/json' };
        var lastPaymentMethod;
        var hasMadeInitialDeposit = false;

        if ($rootScope.managePaymentMethodsRedirect) {
          depositLandingTab = $rootScope.managePaymentMethodsTab;
          return {depositLandingTab: depositLandingTab};
        }

        if (loadEnv === 'registration') {
          return {depositLandingTab: depositLandingTab};
        }

        /* eslint-disable */
        $http.get(url + '?pageSize=1', { headers: headers }).success(function (data) {
          /* eslint-enable */
          if (data.deposits.length > 0 && data.deposits[0].type !== '') {
            hasMadeInitialDeposit = true;
            lastPaymentMethod = data.deposits[0].type === 'SLP' ? 'SLN' : data.deposits[0].type;
            // check if last payment method used is on available deposit options
            if (search(lastPaymentMethod, 'ftype', depositOptions)) {
              depositLandingTab = lastPaymentMethod;
            } else if (lastPaymentMethod === 'ACH' && search('IBC', 'ftype', depositOptions)) {
              depositLandingTab = 'IBC';
            } else if (lastPaymentMethod === 'IBC' && search('ACH', 'ftype', depositOptions)) {
              depositLandingTab = 'ACH';
            }
          }

          deferred.resolve({depositLandingTab: depositLandingTab, hasMadeInitialDeposit: hasMadeInitialDeposit});
        }).error(function () {
          deferred.resolve({depositLandingTab: depositLandingTab, hasMadeInitialDeposit: false});
        });

        return deferred.promise;
      },

      getDepositLimits: function (accountId, paymentType, cardType) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var url;

        if (paymentType === 'IBC' || paymentType === 'ACH') {
          url = walletEndpoint("users") + "/" + accountId + "/limits/ACH";
          $http
            .get(url, { headers: headers })
            .success(function (data) {
              var formattedResponse = formatPaymentLimit(data);
              deferred.resolve(formattedResponse);
            })
            .error(function (data) {
              deferred.reject(data);
            });

        } else if (paymentType === 'APPL') {
          url = walletEndpoint("users") + "/" + accountId + "/limits/APPL";
          $http
            .get(url, { headers: headers })
            .success(function (data) {
              deferred.resolve(data);
            })
            .error(function (data) {
              deferred.reject(data);
            });

        } else if (paymentType === 'CC' || paymentType === 'DEB') {
          var cardTypes = ["CC", "CCS", "DEB", "DEBS"];
          var cardLimits = [];
          url = walletEndpoint("users") + "/" + accountId + "/limits";

          $http
              .get(url, {headers: headers})
              .success(function (data) {
                data.accountDepositLimits.forEach(function(item) {
                  if (item.paymentType !== "ACH") {
                    cardLimits.push({
                      cardType: item.paymentType,
                      limitsResponse: formatPaymentLimit(item)
                    });
                  }
                });
                if (cardType) {
                  var singlePaymentTypeResult = cardLimits.filter(
                    function(item) {
                      return item.cardType === cardType;
                    }
                  );
                  return deferred.resolve({
                    minSingleDepositLimit: singlePaymentTypeResult[0].limitsResponse.minSingleDepositLimit,
                    remainingDepositLimit: singlePaymentTypeResult[0].limitsResponse.remainingDepositLimit
                  });
                }
                return deferred.resolve({cardLimits: cardLimits});
              }).error(function (data) {
                deferred.reject(data);
              });
        } else {
          deferred.reject({ useInitialDataDefault: true });
          return deferred.promise;
        }

        return deferred.promise;
      },

      getCardPaymentOptions: function (accountId, paymentType, cardType) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var url;
        var paymentMethod = cardType ? cardType : paymentType;
        if (paymentMethod === "IBC") {
          paymentMethod = "ACH";
        }

        url = walletEndpoint("users") + "/" + accountId + "/payment-options";

        $http.get(url,
          { headers: headers })
          .success(function (data) {
            var min;
            var max;

            data.forEach(function (item) {
              if (item.paymentType === paymentMethod) {
                min = item.minLimit;
                max = item.maxLimit;
              }
            });

            return deferred.resolve({
              minSingleDepositLimit: min,
              remainingDepositLimit: max
            });

          }).error(function (data) {
            deferred.reject(data);
          });

        return deferred.promise;
      },

      getPaymentTypeDepositLimit: function (accountId, paymentType, cardType) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var url;

        switch (paymentType) {
          case 'IBC':
            url = achEndpoint('users') + '/' + accountId + '/deposits/limits';
            break;
          case 'ACH':
            url = achEndpoint('users') + '/' + accountId + '/deposits/limits';
            break;
          case 'CC':
              url = ccpEndpoint('users') + '/' + accountId + '/deposits/limits';
              break;
          case 'DEB':
              url = ccpEndpoint('users') + '/' + accountId + '/deposits/limits';
              break;
          case 'APPL':
            url = walletEndpoint('users') + '/' + accountId + '/limits/APPL';
              break;
          default:
            deferred.reject({ useInitialDataDefault: true });
            return deferred.promise;
        }

        $http.get(url,
          { headers: headers })
          .success(function (data) {
            var limitMatch = null;
            if (
              data.cardLimits &&
              cardType &&
              (paymentType === "CC" || paymentType === "DEB")
            ) {
              limitMatch = data.cardLimits.filter(function(item) {
                return item.cardType === cardType;
              });
              if (limitMatch && limitMatch[0]) {
                //eslint-disable-next-line
                var min = limitMatch[0].limitsResponse.minSingleDepositLimit;
                //eslint-disable-next-line
                var max = limitMatch[0].limitsResponse.remainingDepositLimit;


                return deferred.resolve({
                  minSingleDepositLimit: min,
                  remainingDepositLimit: max
                });
              }
            }
            deferred.resolve(data);
          }).error(function (data) {
            deferred.reject(data);
          });

        return deferred.promise;
      },

      getUserBankAccounts: function (accountId) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var url = achEndpoint('users') + '/' + accountId + '/bankAccounts';

        $http.get(url,
          { headers: headers })
          .success(function (data) {
            deferred.resolve(data);
          }).error(function (data) {
            deferred.reject(data);
          });

        return deferred.promise;
      },

      getCardsOnFile: function (accountId) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var url = ccpEndpoint('users') + '/' + accountId + '/bankCards';

        $http.get(url,
          { headers: headers })
          .success(function (data) {
            deferred.resolve(data);
          }).error(function (data) {
            deferred.reject(data);
          });

        return deferred.promise;
      },

      getPrepaidCardsOnFile: function (accountId) {
        var deferred = $q.defer();
        var headers = _addHeaders({ cache: true });
        var url = sightlineEndpoint('user') + '/' + accountId + '/account-info';

        $http.get(url,
          { headers: headers })
          .success(function (data) {
            deferred.resolve(data);
          }).error(function (data) {
          deferred.reject(data);
        });

        return deferred.promise;
      },

      getSuccessDepositModal: function(isACH) {
          var modalScope = $rootScope.$new();
          modalScope.isACH = isACH;
          modalScope.betNow = function (closeFn) {
            closeFn({ fromBetNow: true });
          };

          $uibModal
            .open({
              templateUrl:
                'src/templates/deposit/deposit-success-modal.html',
              scope: modalScope,
              windowTemplateUrl: 'src/templates/modal-window.html',
              backdropClass: 'tvgmodal-backdrop',
              windowClass: 'tvg-ui-modal-dialog tvgmodal-dma-redesign'
            })
            .result.then(function (res) {
              if (res && res.fromBetNow) {
                if ($window && $window.handleNativeMessages) {
                  $window.handleNativeMessages('CLOSE_DMA');
                } else if ($rootScope.isQuickDeposit) {
                    $rootScope.$broadcast('onCloseSuccessWindow');
                    if ($window.parent) {
                      $window.parent.postMessage(
                        {
                          type: 'close_deposit'
                        },
                        '*'
                      );
                    }
                } else if ($location.search().callback) {
                  Utilities.attempt(
                    function () {
                      var callbackDecoded = decodeURIComponent($location.search().callback);
                      var callbackSearchParams = new URLSearchParams(callbackDecoded)
                      var pgmDepositRedirect = $rootScope && $rootScope.activeFeatures && $rootScope.activeFeatures.pgmDepositRedirect;
                      if(pgmDepositRedirect && callbackSearchParams.getAll("wt").length > 0 && callbackSearchParams.getAll("bet").length > 0) {
                        // user came from program page, sending him back with bets
                        $window.location.href = '//' + callbackDecoded;
                      }
                      else{
                        $window.location.href = '//' + decodeURIComponent($location.search().callback.split("/")[0]);
                      }
                    }
                  );
                } else {
                  $window.location = "/"
                }
              }
            })
            .catch(function(error){
              console.log("modal error:", error);
            });
          }
    };

    var walletEndpoint = Utilities.endpoint('uwt');
    var achEndpoint = Utilities.endpoint('ach');
    var ccpEndpoint = Utilities.endpoint('ccp');
    var brainTreeEndpoint = Utilities.endpoint('brt');
    var sightlineEndpoint = Utilities.endpoint('slp');
    var usaEndpoint = Utilities.endpoint('usa');

    /**
     * Function to format a payment type object
     * @param  {Object}   item containing the information for a single payment type
     * @return {Object}   formated item
     */
    function formatPaymentLimit(item) {
      var formatedItem = {
        minSingleDepositLimit: item.minLimit,
        remainingDepositLimit: item.limitsEffective.limits.dailyLimit,
        userLimits: {
          dailyLimit: {
            depositLimit: item.limitsEffective.limits.dailyLimit,
            futureDepositLimit: item.limitsFuture.limits.dailyLimit,
            futureDate: item.limitsFuture.futureDailyDate
          },
          weeklyLimit: {
            depositLimit: item.limitsEffective.limits.weeklyLimit,
            futureDepositLimit: item.limitsFuture.limits.weeklyLimit,
            futureDate: item.limitsFuture.futureWeeklyDate
          },
          monthlyLimit: {
            depositLimit: item.limitsEffective.limits.monthlyLimit,
            futureDepositLimit: item.limitsFuture.limits.monthlyLimit,
            futureDate: item.limitsFuture.futureMonthlyDate
          }
        },
        tvgLimits: {
          dailyLimit: {
            depositLimit: item.limitsTvg.limits.dailyLimit
          },
          weeklyLimit: {
            depositLimit: item.limitsTvg.limits.weeklyLimit
          },
          monthlyLimit: {
            depositLimit: item.limitsTvg.limits.monthlyLimit
          },
          holdDays: item.limitsTvg.holdDays
        }
      };
      return formatedItem;
    }

    /**
     * checkTransaction
     * Check if the transaction failed, although the request did not return
     * any error status code.
     *
     * @param  {$httpResponse} response the response object from the $http call
     * @return {Promise}
     * @FIXME angular doesn't respect the Promise A+ standard
     */
    function checkTransaction(response) {
      return $q(function (resolve, reject) {
        if (Utilities.prop('data.errors', response)) {
          return reject(createApiError(response));
        }

        return resolve(response);
      });
    }

    /**
     * request
     * @param  {Object} data
     * @param  {string} data.url
     * @param  {string} data.method
     * @param  {string} data.headers
     * @param  {Object} data.data
     *
     * @return {Promise}
     */
    function request(data, fullResponse) {
      if (data) {
        data.headers = prepareHeaders(data.headers);
      }

      return $http(data)
        .then(checkTransaction)
        .then(function (response) { return fullResponse ? response : response.data; })
        .catch(function (err) {
          return $q.reject(createApiErrorFromHttpError(err));
        });
    }

    /**
     * Add default headers if needed
     * @param  {Object} headers  Headers to send
     * @return {Object}          Headers with defaults
     */
    function prepareHeaders(headers) {
      var defaultHeaders = {};
      var xTvgContext = RequestContextHeaders[$window.clientApp + '_' + $window.locationContext];

      defaultHeaders['Content-Type'] = 'application/json';
      defaultHeaders['x-tvg-context'] = xTvgContext;

      return _.defaults(headers || {}, defaultHeaders);
    }

      /**
     * Create an API error instance
     * @param  {Object} response  HTTP Response with nested errors
     * @return {Object}           Extracted errors
     */
    function createApiError(response) {
      var apiError = new ApiError();
      var responseError = response.data.errors[0];

      apiError.uri = response.config.url;
      apiError.message = responseError.message;
      apiError.code = responseError.code;

      return apiError;
    }

     /**
     * Create an API error instance from new HTTP code errors
     * @param  {Object} response  HTTP Response with nested errors
     * @return {Object}           Extracted errors
     */
    function createApiErrorFromHttpError(response) {
      var apiError = new ApiError();
      var responseError = response.data || {};

      apiError.uri = (response.config || {}).url;
      apiError.message = responseError.message;
      apiError.code = responseError.exception || responseError.code;
      apiError.exceptionCode = responseError.code;
      apiError.status = responseError.status;

      return apiError;
    }

        /**
     * @class ApiError
     * @extends Error
     */
    function ApiError() {
      this.uri = '';
      this.name = '';
      this.message = '';
      this.code = '';
      this.status = '';
      Error.apply(this, [].slice.call(arguments, 0));
    }

    ApiError.prototype = Object.create(Error.prototype);
    ApiError.prototype.constructor = ApiError;

    function search(nameKey, prop, myArray) {
      var i;
      for (i = 0; i < myArray.length; i++) {
        if (myArray[i][prop] === nameKey) {
          return myArray[i];
        }
      }
      return false;
    }

    function _getLoginStatus(errorMessage) {
      return [
        'ApiMissingUserSessionToken',
        'ApiUserSessionTimedOut',
        'ApiUserSessionNotFound'
      ].indexOf(errorMessage) !== -1 ? 'Logged Out' : 'Logged In';
    }

    function _gtmDepositErrorEvent(_depositType, _data) {
      var _errorMessage = Utilities.prop('response.errorMessage', _data) || null;
      var _isQuickDeposit = $rootScope.isQuickDeposit;
      var eventName = 'depositStandardError';
      var eventGAEventAction = 'Deposit Error';
      var eventGAEventLabel = _errorMessage;
      var _netDepositFee = ApiDepositsGTMFac.gtmCurrencyFormat(_transactionFee);
      var iframePos = 0;
      var iframePosQuick = 0;
      /* eslint-disable */
      var modalHeaders = document.getElementsByClassName('modal-header');
      /* eslint-enable */
      var p = {};
      if (ConfigurationFac.getApplicationContextItem('product') !== 'njx') {
        Utilities.attempt(
          function () {
            /* eslint-disable */
            if($window.document.domain === $window.parent.document.domain) {
              iframePos = $window.parent.document.getElementsByTagName('iframe').length;
              iframePosQuick = $window.parent.document.getElementsByTagName('iframe')[iframePos - 1]
                  .src.indexOf('quick') > -1;
            }
            /* eslint-enable */
          }
        );
      }

      if (_depositType && (deposits.user.has('homeAddress.StateAbbr') ||
        deposits.user.has('accountNumber'))) {
        if (!_isQuickDeposit && modalHeaders.length && modalHeaders[0] &&
          modalHeaders.innerHTML) {
          _isQuickDeposit = modalHeaders[0].innerHTML.indexOf('Quick') !== -1;
        }

        if (_isQuickDeposit || (iframePos > 0 && iframePosQuick)) {
          eventName = 'depositQuickError';
        }

        if (tmpAmount === 0 || (_transactionFee > 0 &&
          _FeeDiscount === _transactionFee)) {
          _netDepositFee = '0.00';
        }

        p.event = eventName;
        p.accountId = deposits.user.get('accountNumber');
        p.residenceState = deposits.user.get('homeAddress.StateAbbr');
        p.gaEventCategory = 'Deposit';
        p.gaEventAction = eventGAEventAction;
        p.gaEventLabel = eventGAEventLabel;
        p.customerStatus = deposits.getCustomerStatus();
        p.depositAmount = ApiDepositsGTMFac.gtmCurrencyFormat(tmpAmount);
        p.netDepositFee = _netDepositFee;
        p.depositType = _depositType;
        p.errorType = eventGAEventAction;
        p.errorMessage = _errorMessage;
        p.loginStatus = _getLoginStatus(_errorMessage);
        p.promoCode = '';
        p.registrationStatus = 'Registered';
        p.screenName = ApiDepositsGTMFac.tvg4ScreenName();
        p.sectionName = ApiDepositsGTMFac.tvg4SectionName();
        p.siteVersion = ConfigurationFac.getSiteVersion(
          ConfigurationFac.getApplicationContextItem('application'));

        if (p.siteVersion === 'TVG3') {
          p.screenName = 'Deposit';
          p.sectionName = undefined;
        }

        ApiDepositsGTMFac.sendGTMEvent(null, p);
      }
    }

    function _getExpirationDateValues() {
      var currentYear = parseInt($filter('date')(new Date(), 'yy', 'UTC'), 10);
      return {
        min: currentYear.toString(),
        max: (currentYear + 50).toString()
      };
    }

    function _baseUrl() {
      var protocol;

      if ($rootScope.useAbsoluteRequests ||
        ConfigurationFac.absoluteRequests()) {
        protocol = ConfigurationFac
          .getBaseUrlForApplicationContext('protocol') ?
          ConfigurationFac.getBaseUrlForApplicationContext('protocol') : '//';
        return protocol + ConfigurationFac
            .getBaseUrlForApplicationContext('deposit') + '/deposit/api/v1.0/';
      }

      return '/deposit/api/v1.0/';
    }

    function _getTypeEnumMapValues() {
      return {
        ALL: {
          key: 'ALL',
          value: { type: 'ALL', name: 'all', value: 0 } },
        IBC: {
          key: 'IBC',
          value: { type: 'IBC', name: 'ibc', value: 1 } },
        CC: {
          key: 'CREDIT',
          value: { type: 'CC', name: 'credit', value: 2 } },
        DEB: {
          key: 'DEBIT',
          value: { type: 'DEB', name: 'debit', value: 3 } },
        ACH: {
          key: 'ACH',
          value: { type: 'ACH', name: 'ach', value: 4 } },
        CCS: {
          key: 'CREDIT_SIGNED',
          value: { type: 'CCS', name: 'credit_signed', value: 5 }
        },
        DEBS: {
          key: 'DEBIT_SIGNED',
          value: { type: 'DEBS', name: 'debit_signed', value: 6 }
        },
        MPAKS: {
          key: 'GIFT_CARD_SIGNED',
          value: { type: 'MPAKS', name: 'gift_card_signed', value: 7 }
        },
        MPAK: {
          key: 'MONEY_PACK',
          value: { type: 'MPAK', name: 'money_pak', value: 8 }
        },
        SLN: {
          key: 'SLN', value: {
            type: 'SLN', name: 'sightline', value: 12
          }
        }
      };
    }

    function _newCreditDebitCard(bankName,
        cardNumber,
        cardTypeId,
        nameOnCard,
        cardVerificationNumber,
        expirationDate,
        cardID,
        depositLimitTypeId
      ) {
      return {
        cardID: cardID,
        bankName: bankName,
        cardNumber: cardNumber,
        cardTypeId: cardTypeId,
        depositLimitTypeId: depositLimitTypeId,
        nameOnCard: nameOnCard,
        cardVerificationNumber: cardVerificationNumber,
        expirationDate: expirationDate
      };
    }

    function _depositSuccessBuilder(responseData) {
      return {
        serialNumber: responseData.SerialNumber,
        collectedFee: responseData.DepositResult.Fee,
        discountFee: responseData.DepositResult.FeeDiscount,
        netAmount: responseData.DepositResult.NetAmount,
        requestedAmount: responseData.DepositResult.RequestedAmount,
        transactionalTotal: responseData.DepositResult.TransactionTotal,
        depositType: responseData.depositType || responseData.DepositResult.depositType
      };
    }

    /**
     * _addHeaders
     *
     * @param {object} options
     * @param {boolean} options.cache   Add headers to avoid IE caching of GET
     * requests
     * @returns {object}
     */
    function _addHeaders(options) {
      var headers = {
        'x-tvgcontext': angular.toJson(ConfigurationFac.getApplicationContext()),
        'x-tvg-context': RequestContextHeaders[$window.clientApp + '_' + $window.locationContext]
      };

      if (Utilities.prop('cache', options)) {
        headers = angular.extend({}, {
          'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
          'Cache-Control': 'no-cache',
          Pragma: 'no-cache'
        }, headers);
      }
      return headers;
    }

    function _depositTransactionFeeBuilder(transactionFee, depositType) {
      return {
        fee: transactionFee.useNewFeeFlow ?
          parseFloat(transactionFee.feeAmount) : transactionFee.Fee,
        feeDiscount: transactionFee.useNewFeeFlow ?
          parseFloat(transactionFee.feeRefundAmount) : transactionFee.FeeDiscount,
        netAmount: transactionFee.useNewFeeFlow ?
          parseFloat(transactionFee.RequestedAmount) : transactionFee.NetAmount,
        requestedAmount: transactionFee.RequestedAmount,
        transactionTotal: transactionFee.useNewFeeFlow ?
          parseFloat(transactionFee.RequestedAmount) + parseFloat(transactionFee.feeAmount) -
          parseFloat(transactionFee.feeRefundAmount) : transactionFee.TransactionTotal,
        depositTypeId: depositType,
        useNewFeeFlow: !!transactionFee.useNewFeeFlow ? transactionFee.useNewFeeFlow : false
      };
    }

    return deposits;
  }

  angular.module('TVG.Deposit')
    .factory('DepositSrv', DepositSrv)
    .constant('RequestContextHeaders', {
      tvg4_nj: 'tvg4-4njbets',
      tvg4_pa: 'tvg4-pabets',
      tvg4_all: 'tvg4-tvg',
      tvg4_ia: 'tvg4-iowa',
      tvg5_nj: 'tvg5-4njbets',
      tvg5_pa: 'tvg5-pabets',
      tvg5_all: 'tvg5-tvg',
      tvg5_ia: 'tvg5-iowa',
      touch2_nj: 'touch2-4njbets',
      touch2_pa: 'touch2-pabets',
      touch2_all: 'touch2-tvg',
      touch2_ia: 'touch2-iowa',
      touch3_nj: 'touch3-4njbets',
      touch3_pa: 'touch3-pabets',
      touch3_all: 'touch3-tvg',
      touch3_tvg: 'touch3-tvg',
      touch3_ia: 'touch3-iowa',
      ios2_nj: 'ios2-4njbets',
      ios2_pa: 'ios2-pabets',
      ios2_all: 'ios2-tvg',
      ios2_tvg: 'ios2-tvg',
      ios2_ia: 'ios2-iowa',
      ios_nj: 'ios-4njbets',
      ios_pa: 'ios-pabets',
      ios_all: 'ios-tvg',
      ios_tvg: 'ios-tvg',
      ios_ia: 'ios-iowa',
      njx_nj: 'exchange-exchange',
      fdrmobile_all: 'fdrmobile-fdr',
      fdrmobile_fdr: 'fdrmobile-fdr',
      fdrios_all: 'fdrios-fdr',
      fdrios_fdr: 'fdrios-fdr',
      fdrandroid_all: 'fdrandroid-fdr',
      fdrandroid_fdr: 'fdrandroid-fdr',
      iosnative_all: 'iosnative-tvg',
      iosnative_tvg: 'iosnative-tvg',
      iosnative_nj: 'iosnative-4njbets',
      iosnative_pa: 'iosnative-pabets',
      iosnative_ia: 'iosnative-iowa',
      androidnative_all: 'androidnative-tvg',
      androidnative_tvg: 'androidnative-tvg',
      androidnative_nj: 'androidnative-4njbets',
      androidnative_pa: 'androidnative-pabets',
      androidnative_ia: 'androidnative-iowa',
      androidwrapper_tvg: "androidwrapper-tvg",
      androidwrapper_all: "androidwrapper-tvg",
      androidwrapper_nj:"androidwrapper-4njbets",
      androidwrapper_fdr:"androidwrapper-fdr",
      tvgandroid_tvg: "tvgandroid-tvg",
      tvgandroid_all: "tvgandroid-tvg",
      tvgandroid_nj: "tvgandroid-4njbets",
      tvgandroid_fdr:"tvgandroid-fdr"
    });
}());

(function () {
  'use strict';

  DepositInitialDataFac.$inject = ['SightlineDepositConfig', 'PaypalDepositConfig', 'ApplePayDepositConfig', '$filter', '$window', '$timeout', '$rootScope', 'DEPOSIT_TYPES'];
  function DepositInitialDataFac(
      SightlineDepositConfig,
      PaypalDepositConfig,
      ApplePayDepositConfig,
      $filter,
      $window,
      $timeout,
      $rootScope,
      DEPOSIT_TYPES
    ) {
    var LIMIT_TYPES = {};

    var DEPOSIT_OPTIONS = {
      CC: 'Credit',
      CCS: 'CreditSigned',
      DEB: 'Debit',
      DEBS: 'DebitSigned'
    };

    var CARD_TYPES = {
      CC: {
        id: 1,
        name: 'Credit',
        abbr: 'CC'
      },
      DEB: {
        id: 2,
        name: 'Debit',
        abbr: 'DEB'
      }
    };

    var LIMIT_TYPES_MOCK = [
      {
        id: 1,
        name: 'Betcash',
        abbr: 'IBC'
      },
      {
        id: 1,
        name: 'Betcash',
        abbr: 'ACH'
      },
      {
        id: 2,
        name: 'Credit',
        abbr: 'CC'
      },
      {
        id: 3,
        name: 'Debit',
        abbr: 'DEB'
      },
      {
        id: 5,
        name: 'CreditSigned',
        abbr: 'CCS'
      },
      {
        id: 8,
        name: 'MoneyPak',
        abbr: 'MPAK'
      },
      {
        id: 10,
        name: 'PayNearMe',
        abbr: 'PNM'
      },
      {
        id: 11,
        name: 'ApplePay',
        abbr: 'APPL'
      }
    ];

    function _getCardType(name) {
      var match = Object.values(CARD_TYPES).filter(function (item) {
        return item.name === name;
      });
      return match.length > 0 ? match[0] : {};
    }

    function _getDepositLimitType(name) {
      var match = LIMIT_TYPES_MOCK.filter(function (item) {
        return item.name === name;
      });
      return match.length > 0 ? match[0] : {};
    }

    function _getDepositLimitTypeByAbbr(abbr) {
      var match = LIMIT_TYPES_MOCK.filter(function (item) {
        return item.abbr === abbr;
      });
      return match.length > 0 ? match[0] : {};
    }

    function _parseStates(statesList) {
      return statesList.map(function (state) {
        return {
          abbreviation: state.Abbreviation || state.abbreviation,
          name: state.Name || state.name
        };
      });
    }

    function _parseCardTypes(response) {
      var cardAbbr;
      var card;

      return response.reduce(function (acc, cardType) {
        cardAbbr = cardType.Abbreviation.toLowerCase().trim() === 'db' ?
          'DEB' : 'CC';
        card = {
          id: cardType.Id,
          name: cardType.Name,
          abbr: cardAbbr
        };

        acc[cardAbbr] = card; // eslint-disable-line
        acc[cardType.Id] = card; // eslint-disable-line
        return acc;
      }, {});
    }

    function _parseLimitMinMax(optionMinMaxList, typeToEnumMap) {
      var cardType;
      var limitType;

      return optionMinMaxList.reduce(function (acc, optionMinMax) {
        cardType = typeToEnumMap[optionMinMax.Type.trim()];
        limitType = {};

        if (cardType && cardType.value) {
          limitType = {
            name: cardType.value.name,
            type: cardType.value.type,
            feeType: cardType.value.name,
            min: optionMinMax.Min || 0,
            max: optionMinMax.Max || 0,
            id: cardType.value.value
          };

          acc[optionMinMax.Type.trim()] = limitType; // eslint-disable-line
          acc[cardType.value.value] = limitType; // eslint-disable-line
        }

        return acc;
      }, {});
    }


    /**
     * Get deposit max or min limits by paymentType
     *
     * @param  {String} type     Limit type ID
     * @param  {String} prop     Max or min key
     * @return {Number/Boolean}  Max/min limit for the selected limit type
     */
    function _getLimitType(type, prop) {
      var fallback;

      // stop
      if ((!angular.isObject(LIMIT_TYPES) ||
          !angular.isObject(LIMIT_TYPES[type]))) {
        return false;
      }

      if (prop === 'min') {
        fallback = 0.1;
      } else if (prop === 'max') {
        fallback = 999999;
      }

      return LIMIT_TYPES[type][prop] || fallback;
    }

    function _parseAccountDetails(accountDetails) {
      // stop
      if (!accountDetails) { return null; }

      return {
        accountNumber: accountDetails.AccountNumber,
        accountHState: accountDetails.HomeAddress.StateAbbr,
        accountUsername: accountDetails.Username
      };
    }

    function _buildCreditDebitCardsOption(
        cardTypes,
        //eslint-disable-next-line
        cardOnFile
      ) {
      var option = {
        name: $rootScope.isFdrApp ? 'Credit / Debit Card' : 'Credit/Debit Card',
        ftype: 'CC',
        depositTypeId: DEPOSIT_TYPES.CARD_NEW,
        subTypes: []
      };

      option.onFile = [];

      if (cardTypes.CC) {
        option.subTypes.push({
          name: 'Credit',
          ftype: 'CC',
          type: 'CC',
          limitTypeId: _getLimitType('CC', 'id') ||
            _getDepositLimitTypeByAbbr('CC').id,
          min: _getLimitType('CC', 'min'),
          max: _getLimitType('CC', 'max'),
          cardTypeId: cardTypes.CC.id,
          depositTypeId: DEPOSIT_TYPES.CARD_NEW
        });
      }

      if (cardTypes.DEB) {
        option.subTypes.push({
          name: 'Debit',
          ftype: 'CC',
          type: 'DEB',
          limitTypeId: _getLimitType('DEB', 'id')
            || _getDepositLimitTypeByAbbr('DEB').id,
          min: _getLimitType('DEB', 'min'),
          max: _getLimitType('DEB', 'max'),
          cardTypeId: cardTypes.DEB.id,
          depositTypeId: DEPOSIT_TYPES.CARD_NEW
        });
      }

      return option;
    }

    function _buildDepositOptionsOnFile(
        cardsOnFile,
        achOnFile,
        cardTypes
      ) {
      var optionsOnFile = [];

      angular.forEach(cardsOnFile, function (card) {
        if (cardTypes[card.CardTypeID]) {
          optionsOnFile.push({
            groupName: 'Cards On File',
            id: card.CardID,
            cardNumber: card.CardNumber,
            cardNumberExt: '****' + card.CardNumber,
            cardTypeId: card.CardTypeID,
            limitTypeId: card.DepositLimitTypeId,
            expirationDate: card.ExpirationDate,
            isExpired: moment(card.ExpirationDate, 'MM/YY')
              .add(1, 'month') < moment(),
            signed: card.Signed,
            name: '(****' + card.CardNumber + ') ' +
            cardTypes[card.CardTypeID].name + ' ' + card.ExpirationDate,
            ftype: 'CC',
            type: cardTypes[card.CardTypeID].abbr,
            min: _getLimitType(card.DepositLimitTypeId, 'min'),
            max: _getLimitType(card.DepositLimitTypeId, 'max'),
            depositTypeId: DEPOSIT_TYPES.CARD_ON_FILE
          });
        }
      });

      angular.forEach(achOnFile, function (ach) {
        optionsOnFile.push({
          groupName: 'BetCash Accounts On File',
          achId: ach.AppAchId,
          bankAccNumber: ach.BankAcctNumber,
          bankAcctType: ach.BankAcctType,
          bankName: ach.BankName,
          bankRoutingNumber: ach.BankRoutingNumber,
          driversLicenseNumber: ach.DriversLicenseNumber,
          driversLicenseState: ach.DriversLicenseState,
          isPending: ach.IsPending,
          name: '(****' + ach.BankAcctNumber
            .substr(ach.BankAcctNumber.length - 4) + ') ' + ach.BankName,
          ftype: 'ACH',
          type: 'ACH',
          limitTypeId: _getLimitType('ACH', 'id'),
          min: _getLimitType('ACH', 'min'),
          max: _getLimitType('ACH', 'max'),
          depositTypeId: DEPOSIT_TYPES.ACH_ON_FILE
        });
      });

      return optionsOnFile;
    }

    /**
     * Check if a type of deposit has any available option
     *
     * @param  {Array}  options      Array of deposit options
     * @param  {String} depositType  Deposit type key
     * @return {Boolean}             Deposit type is available?
     */
    function _isDepositOptionAvailable(options, depositType) {
      return (options || []).some(function (option) {
        var key = (option.Abbreviation || '').trim();
        var isAvailable = false;

        if (key === depositType) {
          isAvailable = option.IsAvailable;
        }

        return isAvailable;
      });
    }

    /**
     * Parse user's credit cards information to be rendered
     *
     * @param  {Array}  cardsOnFile   User's credit cards
     * @param  {Object} cardTypes     Credit card types hash
     * @return {Array}                Parsed user's credit cards
     */
    //eslint-disable-next-line
    function _parseCardsOnFile(cardsOnFile, cardTypes) {
      return cardsOnFile.map(function (card) {
        if (cardTypes[card.CardTypeID]) {
          return {
            groupName: 'Cards On File',
            id: card.CardID,
            cardNumber: card.CardNumber,
            cardNumberExt: '****' + card.CardNumber,
            cardTypeId: card.CardTypeID,
            limitTypeId: card.DepositLimitTypeId,
            expirationDate: card.ExpirationDate,
            isExpired: moment(card.ExpirationDate, 'MM/YY')
              .add(1, 'month') < moment(),
            signed: card.Signed,
            name: '(****' + card.CardNumber + ') ' +
            cardTypes[card.CardTypeID].name + ' ' + card.ExpirationDate,
            ftype: 'CC',
            type: cardTypes[card.CardTypeID].abbr,
            typeName: cardTypes[card.CardTypeID].name,
            cardType: cardTypes[card.CardTypeID].name,
            min: _getLimitType(card.DepositLimitTypeId, 'min'),
            max: _getLimitType(card.DepositLimitTypeId, 'max'),
            depositTypeId: DEPOSIT_TYPES.CARD_ON_FILE
          };
        }
        return undefined;
      }).filter(Boolean);
    }

    /**
     * Parse user's betcash accounts information to be rendered
     *
     * @param  {Array}  achOnFile         User's credit cards
     * @param  {Object} availableOptions  Available deposit options
     * @return {Array}                    Parsed user's credit cards
     */
    function _parseAchOnFile(achOnFile, availableOptions) {
      return achOnFile.map(function (ach) {
        return {
          groupName: 'BetCash Accounts On File',
          achId: ach.AppAchId,
          bankAccNumber: ach.BankAcctNumber,
          bankAcctType: ach.BankAcctType,
          bankName: ach.BankName,
          bankRoutingNumber: ach.BankRoutingNumber,
          driversLicenseNumber: ach.DriversLicenseNumber,
          driversLicenseState: ach.DriversLicenseState,
          isPending: ach.IsPending,
          name: '(****' + ach.BankAcctNumber
            .substr(ach.BankAcctNumber.length - 4) + ') ' + ach.BankName,
          ftype: 'ACH',
          type: 'ACH',
          limitTypeId: _getLimitType('ACH', 'id'),
          min: _getLimitType('ACH', 'min'),
          max: _getLimitType('ACH', 'max'),
          depositTypeId: DEPOSIT_TYPES.ACH_ON_FILE,
          typeName: 'BetCash',
          cardType: ach.cardType,
          isAvailable: _isDepositOptionAvailable(
            availableOptions.DepositOptions, 'ACH')
        };
      });
    }

    /**
     * Prepare user's sightline information to be rendered
     * @param {Object} sightlineData  Sightline data
     * @return {Array}                Sightline deposit options
     */
    function _parseSightlineOnFile(sightlineData) {
      var onFile = {
        groupName: 'TVG Pre Paid Card',
        name: 'Pre Paid Card',
        id: sightlineData.id,
        ftype: sightlineData.ftype,
        type: sightlineData.type,
        limitTypeId: sightlineData.limitTypeId,
        min: sightlineData.min,
        max: sightlineData.max,
        cardType: sightlineData.cardType,
        typeName: 'TVG Pre Paid Card',
        depositTypeId: DEPOSIT_TYPES.SIGHTLINE // was sightlineData.depositTypeId
      };

      return [onFile];
    }

    function _parsePayPalOnFile(paypalData) {
      var onFile = {
        groupName: 'PayPal',
        name: 'PayPal',
        typeName: 'PayPal',
        id: paypalData.id,
        ftype: paypalData.ftype,
        type: paypalData.type,
        limitTypeId: paypalData.limitTypeId,
        cardType: paypalData.cardType,
        min: paypalData.min,
        max: paypalData.max,
        depositTypeId: DEPOSIT_TYPES.PAYPAL // was sightlineData.depositTypeId
      };

      return [onFile];
    }

    function _parseApplePayOnFile(applePayData) {
      var onFile = {
        groupName: 'ApplePay',
        name: 'ApplePay',
        bankName: 'ApplePay',
        typeName: 'ApplePay',
        id: applePayData.id,
        ftype: applePayData.ftype,
        type: applePayData.type,
        limitTypeId: applePayData.limitTypeId,
        cardType: applePayData.cardType,
        min: applePayData.min,
        max: applePayData.max,
        depositTypeId: DEPOSIT_TYPES.APPLE_PAY // was sightlineData.depositTypeId
      };

      return [onFile];
    }

    function _BetCashPositionIfAvailable(depOptions) {
      var ACHPosition = depOptions.indexOf('ACH');
      var IBCPosition = depOptions.indexOf('IBC');

      if (ACHPosition === -1 && IBCPosition === -1) {
        return false;
      }

      if (_isACHAndIBCAvailable(depOptions)) {
        return Math.min(ACHPosition, IBCPosition);
      }

      return ACHPosition !== -1 ? ACHPosition : IBCPosition;
    }

    function _isACHAndIBCAvailable(depOptions) {
      return depOptions.indexOf('ACH') !== -1 &&
        depOptions.indexOf('IBC') !== -1;
    }

    /**
     * Build deposit/quick deposit payment options
     * @param  {Object} availableOptions                 All deposit options
     * @param  {Object} cardTypes                        Credit cards hash
     * @param  {Array}  cardsOnFile                      Credit cards in account
     * @param  {Array}  achOnFile                        Betcash cards in account
     * @param  {Array}  availableCMSDepositOptions       Available deposit keys
     *                                                   from CMS
     * @param  {boolean} canMakePaymentsWithActiveCard   Apple Pay user validation
     * @return {Object}                                  Filtered deposit and
     *                                                   quick deposit options
     */
    function _buildDepositOptions(
        availableOptions,
        cardTypes,
        cardsOnFile,
        achOnFile,
        availableCMSDepositOptions,
        canMakePaymentsWithActiveCard
      ) {
      var depositOptions = [];
      var quickDepositOptions = [];
      var depositObj;
      var betCashIndex = _BetCashPositionIfAvailable(availableCMSDepositOptions);

      if (betCashIndex !== false) {
        availableCMSDepositOptions.splice(betCashIndex, 0, 'BC');
        $rootScope.betCashIndex = betCashIndex;
      }

      angular.forEach(availableCMSDepositOptions, function (option) {
        switch (option) {
          case 'APPL':
            if (
              canMakePaymentsWithActiveCard ||
              ($rootScope.product === 'ios2' && $rootScope.isQuickDeposit)
            ) {
              if ($rootScope.activeFeatures.showApplePayMoreDeposit) {
                depositOptions.unshift({
                  depositTypeId: DEPOSIT_TYPES.APPLE_PAY,
                  limitTypeId: _getLimitType('APPL', 'id') ||
                      _getDepositLimitTypeByAbbr('APPL').id,
                  ftype: 'APPL',
                  name: 'Apple Pay'
                });
              }

              if ($rootScope.activeFeatures.showApplePayQuickDeposit) {
                depositObj = _.extend({}, ApplePayDepositConfig);
                depositObj.onFile = _parseApplePayOnFile(depositObj);

                quickDepositOptions.push(depositObj);
              }
            }
            break;

          case 'BC':
            depositObj = {
              name: 'eCheck',
              ftype: 'IBC',
              limitTypeId: _getLimitType('IBC', 'id') ||
                _getDepositLimitTypeByAbbr('IBC').id,
              min: _getLimitType('IBC', 'min'),
              max: _getLimitType('IBC', 'max'),
              isAvailable: true,
              depositTypeId: DEPOSIT_TYPES.ACH_NEW,
              onFile: _parseAchOnFile(achOnFile, availableOptions),
              bothACHAndIBCAvailable: _isACHAndIBCAvailable(
                availableCMSDepositOptions)
            };
            depositOptions.push(depositObj);
            quickDepositOptions.push(depositObj);
            break;

          case 'CC':
            depositObj = _buildCreditDebitCardsOption(cardTypes);
            depositOptions.push(depositObj);
            quickDepositOptions.push(depositObj);
            break;

          case 'MPAK':
            depositObj = {
              name: $rootScope.isFdrApp ? 'Cash with MoneyPak' : 'MoneyPak',
              ftype: 'MPAK',
              limitTypeId: _getLimitType('MPAK', 'id') ||
               _getDepositLimitTypeByAbbr('MPAK').id,
              min: _getLimitType('MPAK', 'min'),
              max: _getLimitType('MPAK', 'max'),
              depositTypeId: DEPOSIT_TYPES.GREENDOT_MONEY_PAK
            };
            depositOptions.push(depositObj);
            break;

          case 'SLN':
            // Sighline
            depositObj = _.extend({}, SightlineDepositConfig);
            depositObj.onFile = _parseSightlineOnFile(depositObj);

            depositOptions.push(depositObj);
            if ($rootScope.isFdrApp) {
              depositObj.name = 'FanDuel Pre Paid';
            }
            quickDepositOptions.push(depositObj);

            break;

          case 'PAY':
            depositObj = _.extend({}, PaypalDepositConfig);
            depositObj.onFile = _parsePayPalOnFile(depositObj);

            depositOptions.push(depositObj);

            break;

          case 'PNM':
            // PayNearMe. I'd prefer that the deposit options came from the
            // backend response -> Account/DepositOptions (.net api)
            depositOptions.push({
              depositTypeId: 10,
              ftype: 'PNM',
              limitTypeId: _getDepositLimitTypeByAbbr('PNM').id,
              name: $filter('CMSValue')('pnmTabName') || 'Pay Near Me'
            });
            break;

          case 'OTHER':
            // Other
            depositObj = {
              name: $rootScope.isFdrApp ? 'Other Methods' : 'Other Payment Methods',
              ftype: 'OTHER',
              limitTypeId: _getLimitType('OTHER', 'id') ||
                 _getDepositLimitTypeByAbbr('OTHER').id,
              min: 0,
              max: _getLimitType('OTHER', 'max'),
              depositTypeId: DEPOSIT_TYPES.OTHER
            };
            depositOptions.push(depositObj);
            break;

          default:
            break;
        }
      });

      return {
        depositOptions: depositOptions,
        quickDepositOptions: quickDepositOptions
      };
    }

    function _buildPaymentOptions(data, availableCMSDepositOptions, canMakePaymentsWithActiveCard) {
      var cardTypes = _buildCardTypes(data.paymentOptions);
      var availableDepositOptions = availableCMSDepositOptions.filter(function (item) {
        var existsCC = false;
        switch (item) {
          case 'SLN':
            item = 'SLP';
            break;
          case 'OTHER':
            item = 'OTR';
            break;
          case 'CC':
            existsCC = data.paymentOptions.indexOf('CC') !== -1 ||
              data.paymentOptions.indexOf('CCS') !== -1 ||
              data.paymentOptions.indexOf('DEB') !== -1 ||
              data.paymentOptions.indexOf('DEBS') !== -1;
            break;
          default:
            break;
        }
        return data.paymentOptions.indexOf(item) !== -1 || existsCC;
      });
      var depOptObj = _buildDepositOptions(
        data.paymentOptions,
        cardTypes,
        [],
        [],
        availableDepositOptions,
        canMakePaymentsWithActiveCard
      );
      var depositOptions = depOptObj.depositOptions;
      var quickDepositOptions = depOptObj.quickDepositOptions;
      return {
        cardTypes: cardTypes,
        depositOptions: depositOptions,
        quickDepositOptions: quickDepositOptions };
    }

    function _buildCardTypes(response) {
      var cardAbbr;
      var card;

      return response.reduce(function (acc, cardType, index) {
        cardAbbr = cardType;
        if (cardAbbr === 'CC' || cardAbbr === 'CCS' ||
          cardAbbr === 'DEB' || cardAbbr === 'DEBS') {
          card = {
            id: CARD_TYPES[cardType] ? CARD_TYPES[cardType].id : index,
            name: DEPOSIT_OPTIONS[cardType],
            abbr: cardType
          };

        acc[cardAbbr] = card; // eslint-disable-line
        acc[index] = card; // eslint-disable-line
        }
        return acc;
      }, {});
    }

    /**
     * Build initial data
     *
     * @param  {Object} initialData                [description]
     * @param  {Object} typeEnumMap                [description]
     * @param  {Array}  availableCMSDepositOptions [description]
     * @return {Object}                            [description]
     */
    function _buildInitialData(
        initialData,
        typeEnumMap,
        availableCMSDepositOptions
      ) {
      var cardTypes;
      var depOptObj;
      //eslint-disable-next-line
      var depositOptions;
      //eslint-disable-next-line
      var quickDepositOptions;
      var depositOptionsOnFile;
      var states;
      var accountDetails;
      var achDepositLimitExceeded;
      var ret;

      LIMIT_TYPES = _parseLimitMinMax(initialData.limitMinMax, typeEnumMap);

      cardTypes = _parseCardTypes(initialData.cardTypes);
      depOptObj = _buildDepositOptions(
        initialData.availableOptions,
        cardTypes,
        initialData.cardOnFile,
        initialData.achOnFile,
        availableCMSDepositOptions
      );

      depositOptions = depOptObj.depositOptions;
      quickDepositOptions = depOptObj.quickDepositOptions;
      depositOptionsOnFile = _buildDepositOptionsOnFile(
        initialData.cardOnFile,
        initialData.achOnFile,
        cardTypes
      );

      states = _parseStates(initialData.depositStates);
      accountDetails = _parseAccountDetails(initialData.accountDetails);
      achDepositLimitExceeded = initialData.achDepositLimitExceeded;

      ret = {
        depositOptions: [],
        quickDepositOptions: [],
        depositOptionsOnFile: depositOptionsOnFile,
        states: states,
        achDepositLimitExceeded: achDepositLimitExceeded,
        madeFirstDeposit: initialData.availableOptions.HasMadeInitialDeposit,
        defaultDepositOptions: initialData.availableOptions.DepositOptions,
        defaultLimitMinMax: initialData.limitMinMax
      };

      if (accountDetails) {
        ret.accountDetails = accountDetails;
      }

      return ret;
    }

    /**
     * Build payment initial data
     *
     * @param  {Object} initialData                [description]
     * @param  {Array}  availableCMSDepositOptions [description]
     * @return {Object}                            [description]
     */
    function _buildPaymentInitialData(
        initialData,
        availableCMSDepositOptions
      ) {
      var cardTypes = _parseCardTypes(initialData.cardTypes);
      var depOptObj = _buildDepositOptions(
        initialData.availableOptions,
        cardTypes,
        initialData.cardOnFile,
        initialData.achOnFile,
        availableCMSDepositOptions
      );

      return {
        depositOptions: depOptObj.depositOptions
      };
    }

    /**
     * Get the list of restricted deposit types according
     *
     * @param  {Object} initialData  Deposit's initial data
     * @return {Array}               Restricted deposit types
     */
    function _getDepositRestrictedTypes(initialData) {
      var restrictedTypes = [];
      var depositOpts = initialData.availableOptions.DepositOptions;

      if (_areCreditAndDebitCardRestricted(initialData.cardTypes)) {
        restrictedTypes.push('CC');
      }

      if (_isIBCRestricted(depositOpts)) {
        restrictedTypes.push('IBC');
      }

      if (_isACHRestricted(depositOpts)) {
        restrictedTypes.push('ACH');
      }

      return restrictedTypes;
    }

    function _areCreditAndDebitCardRestricted(cardTypes) {
      return (Object.keys(cardTypes).length === 0);
    }

    function _isIBCRestricted(depositOptions) {
      return !depositOptions.some(function (option) {
        return option.Abbreviation.indexOf('IBC') > -1;
      });
    }

    function _isACHRestricted(depositOptions) {
      return !depositOptions.some(function (option) {
        return option.Abbreviation.indexOf('ACH') > -1;
      });
    }

    return {
      buildPaymentInitialData: _buildPaymentInitialData,
      buildPaymentOptions: _buildPaymentOptions,
      buildCardTypes: _buildCardTypes,
      buildInitialData: _buildInitialData,
      getDepositRestrictedTypes: _getDepositRestrictedTypes,
      getLimitType: _getLimitType,
      getDepositLimitTypeByAbbr: _getDepositLimitTypeByAbbr,
      getCardType: _getCardType,
      getDepositLimitType: _getDepositLimitType,
      parseStates: _parseStates
    };
  }

  angular.module('TVG.Deposit')
    .factory('DepositInitialDataFac', DepositInitialDataFac);
}());

(function () {
  'use strict';

  DmaTvg4FeatureTogglesSvc.$inject = ['$rootScope'];
  function DMAFeatureTogglesHashContainerSvc() {
    var _toggleHashContainer = {};
    var _default = 'dma';

    function _register(key, value) {
      _toggleHashContainer[key] = value;
    }

    function _registerAsDefault(value) {
      _register(_default, value);
    }

    function _getBasedOnKey(key) {
      return	_toggleHashContainer[key] || _toggleHashContainer[_default];
    }

    return {
      register: _register,
      registerAsDefault: _registerAsDefault,
      getBasedOnKey: _getBasedOnKey
    };
  }

  function DmaTvg4FeatureTogglesSvc($rootScope) {
    return function (key) {
      return $rootScope.activeFeatures && $rootScope.activeFeatures[key];
    };
  }

  angular.module('TVG.DMAToggles')
    .factory('DMAFeatureTogglesHashContainerSvc', DMAFeatureTogglesHashContainerSvc)
    .factory('DmaTvg4FeatureTogglesSvc', DmaTvg4FeatureTogglesSvc);
}());

(function () {
  'use strict';
  FeedbackFac.$inject = ['$window'];
  function FeedbackFac($window) {
    return {
      /**
       * Is the element inside the viewport?
       * http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport
       *
       * @param {Object} el               Element to check position
       * @param {Object} [offsets]        Custom offsets
       * @param {Object} [offsets.top]    Top offset that must be respected
       * @param {Object} [offsets.right]  Right offset that must be respected
       * @param {Object} [offsets.bottom] Bottom offset that must be respected
       * @param {Object} [offsets.left]   Left offset that must be respected
       * @return {Boolean}                Is in viewport?
       * @private
       */
      _isInViewport: function (el, offsets) {
        var top = 0;
        var right = 0;
        var bottom = 0;
        var left = 0;
        var rect;

        // stop
        if (!el) { return true; }

        rect = el.getBoundingClientRect();
        offsets = offsets || {};

        top = offsets.top || 0;
        left = offsets.left || 0;
        right = ($window.innerWidth || document.documentElement.clientWidth || 0) - (offsets.right || 0);  // eslint-disable-line
        bottom = ($window.innerHeight || document.documentElement.clientHeight || 0) - (offsets.bottom || 0);  // eslint-disable-line

        return (
            rect.top >= top &&
            rect.left >= left &&
            rect.bottom <= bottom &&
            rect.right <= right
        );
      },

      /**
       * Calculate the fixed header height (if any)
       * @param {Object} el  Header element to check height
       * @return {Number}    Header's height
       * @private
       */
      _getHeaderHeight: function (headerSelector) {
        var header = document.querySelector(headerSelector || '.sticky-header'); // eslint-disable-line
        var height = 0;

        if (header) {
          height = header.getBoundingClientRect().height || 0;
        }

        return height;
      },

      //
      // PUBLIC
      //

      /**
       * Scroll into first error tooltip, if not already inside viewport
       *
       * @param {Object} [options]                 Scroll options
       * @param {String} [options.headerSelector]  Header selector
       * @param {String} [options.labelSelector]   Error label selector
       * @public
       */
      scrollIntoFirstError: function (options) {
        var opts = options || {};
        var label = document.querySelector(opts.labelSelector || '.js-error-label');  // eslint-disable-line
        var headerHeight = this._getHeaderHeight(opts.headerSelector);
        var offsetTop = 40 + headerHeight;
        var labelTop = 0;
        var left = 0;
        var top = 0;
        var inViewport = true;

        if ([
          'touch3',
          'ios2',
          'fdrmobile',
          'fdrios',
          'fdrandroid',
          'androidwrapper',
          'tvgandroid'
        ].indexOf($window.productContext) >= 0) {
          // prevent scroll to on ios iframe
          return;
        }

        // stop if there's no element
        if (!label) { return; }

        inViewport = this._isInViewport(label, { top: offsetTop });

        // do not scroll when already visible
        if (inViewport) { return; }


        label = angular.element(label);
        labelTop = label.offset().top || 0;

        top = labelTop - offsetTop;
        top = (top < 0) ? 0 : top;
        left = $window.scrollX || 0;

        $window.scrollTo(left, top);

        return;
      }
    };
  }

  angular.module('TVG.Deposit')
    .factory('FeedbackFac', FeedbackFac);
}());

(function () {
  'use strict';
  ManagePaymentMethodsSrv.$inject = ['$http', '$q', '$location', '$filter', '$window', '$timeout', '$rootScope', 'ConfigurationFac', 'DepositInitialDataFac', 'Utilities'];
  function ManagePaymentMethodsSrv(
      $http,
      $q,
      $location,
      $filter,
      $window,
      $timeout,
      $rootScope,
      ConfigurationFac,
      DepositInitialDataFac,
      Utilities
    ) {
    var payMethods;

    function _baseUrl() {
      var protocol;

      if ($rootScope.useAbsoluteRequests ||
        ConfigurationFac.absoluteRequests()) {
        protocol = ConfigurationFac
          .getBaseUrlForApplicationContext('protocol') ?
          ConfigurationFac.getBaseUrlForApplicationContext('protocol') : '//';

        return protocol + ConfigurationFac
            .getBaseUrlForApplicationContext('deposit') +
          '/deposit/api/v1.0/';
      }

      return '/deposit/api/v1.0/';
    }

    function _addHeaders() {
      var context = angular.toJson(ConfigurationFac.getApplicationContext());
      return { 'x-tvgcontext': context };
    }

    payMethods = {
      getPayMethodsInitialData: function () {
        var deferred = $q.defer();
        var url = _baseUrl() + 'managePaymentsInitialData';
        var headers = angular.extend({
          'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
          'Cache-Control': 'no-cache',
          Pragma: 'no-cache'
        }, _addHeaders());

        $http.get(url, { headers: headers })
          .success(function (data) {
            var cmsConfig;
            var response;
            var initialData;

            var depositConfigAvailableOptions = Utilities.attempt(
              function () {
                return angular.fromJson(
                  $filter('CMSValue')('depositConfigAvailableOptions'));
              },
              function () {
                return ['IBC', 'CC', 'ACH'];
              }
            );

            var paymentManagementConfigAvailableOptions = Utilities.attempt(
              function () {
                return angular.fromJson(
                  $filter('CMSValue')('paymentManagementConfigAvailableOptions'));
              },
              function () {
                return ['IBC', 'CC'];
              }
            );

            if (data && data.status === 'success') {
              cmsConfig = depositConfigAvailableOptions.filter(function (el) {
                return paymentManagementConfigAvailableOptions.indexOf(el) > -1;
              });

              response = data.response;

              initialData = DepositInitialDataFac.buildPaymentInitialData(
                response,
                cmsConfig
              );

              response.paymentMethodsOptions = initialData.depositOptions;

              deferred.resolve(response);
            } else {
              deferred.reject(data);
            }
          }).error(function (data) {
            deferred.reject(data);
          });

        return deferred.promise;
      },
      addCard: function (cardDataModel) {
        var deferred = $q.defer();

        $http({
          method: 'POST',
          url: _baseUrl() + 'addNewCard',
          data: {
            cardNumber: cardDataModel.cardNumber,
            bankName: cardDataModel.bankName,
            cardTypeId: cardDataModel.selectedCardType.cardTypeId,
            expirationMonthYear: cardDataModel.ExpirationMonthYear
          },
          headers: _addHeaders()
        }).success(function (data) {
          if (data && data.status === 'success') {
            deferred.resolve(data.response);
          } else {
            deferred.reject(data.response);
          }
        }).error(function (response) {
          deferred.reject(response);
        });

        return deferred.promise;
      },
      updateCard: function (cardDataModel, accountNumber) {
        var deferred = $q.defer();
        var accountId = $rootScope.user && $rootScope.user.accountNumber || accountNumber;
        var url = ConfigurationFac.getBaseServiceUrl() + '/ccp/v1/users/' + accountId + '/bankCards/' + cardDataModel.cardID;
        var payload = {
          bankName: cardDataModel.bankName,
          expirationMonth: cardDataModel.ExpirationMonthYear.split('/')[0],
          expirationYear: cardDataModel.ExpirationMonthYear.split('/')[1]
        };
        var method = 'PUT';

        $http({
          method: method,
          url: url,
          data: payload,
          headers: _addHeaders()
        }).success(function (data) {
          deferred.resolve(data);
        }).error(function (response) {
          deferred.reject(response);
        });

        return deferred.promise;
      },
      removeCard: function (cardID, accountNumber) {
        var accountId = $rootScope.user && $rootScope.user.accountNumber || accountNumber;
        var deferred = $q.defer();
        var url = ConfigurationFac.getBaseServiceUrl() + '/ccp/v1/users/' + accountId + '/bankCards/' + cardID;

        $http({
          method: 'DELETE',
          url: url,
          headers: _addHeaders()
        }).success(function (data) {
          deferred.resolve(data);
        }).error(function (response) {
          deferred.reject(response);
        });

        return deferred.promise;
      },
      updateLimit: function (
          depositTypeId,
          depositLimitIntervalId,
          maxLimit,
          accountNumber
        ) {
        var mapCardType = {
          2: 'CC',
          3: 'DEB',
          5: 'CCS',
          6: 'DEBS'
        };
        var deferred = $q.defer();
        var method = 'POST';
        var url = _baseUrl() + 'updateLimit';
        var payload = {
          depositTypeId: depositTypeId,
          depositLimitIntervalId: depositLimitIntervalId,
          maxLimit: maxLimit
        };
        var accountId = $rootScope.user && $rootScope.user.accountNumber || accountNumber;
        var isAchOrIbc = depositTypeId === 1 ||
        depositTypeId === 4;
        var isCC = depositTypeId === 2 || depositTypeId === 3 ||
          depositTypeId === 5 || depositTypeId === 6;
        var isApplePay = depositTypeId === 7;
        var walletEndpoint = Utilities.endpoint('uwt');

        if (isApplePay) {
          method = 'PUT';

          url = walletEndpoint('users') + '/' + accountId + '/limits/APPL/user';
          payload = {
            dailyLimit: maxLimit.daily
              ? parseFloat(maxLimit.daily)
                .toFixed(2)
                .toString()
              : null,
            weeklyLimit: maxLimit.weekly
              ? parseFloat(maxLimit.weekly)
                .toFixed(2)
                .toString()
              : null,
            monthlyLimit: maxLimit.monthly
              ? parseFloat(maxLimit.monthly)
                .toFixed(2)
                .toString()
              : null
          };
        }

        if (isAchOrIbc) {
          method = 'PUT';
          if ($rootScope.activeFeatures.useUwtForDepositLimitsOnDma) {
            url = walletEndpoint('users') + '/' + accountId + '/limits/ACH/user';
            payload = {
              dailyLimit: maxLimit.daily
                ? parseFloat(maxLimit.daily)
                    .toFixed(2)
                    .toString()
                : null,
              weeklyLimit: maxLimit.weekly
                ? parseFloat(maxLimit.weekly)
                    .toFixed(2)
                    .toString()
                : null,
              monthlyLimit: maxLimit.monthly
                ? parseFloat(maxLimit.monthly)
                    .toFixed(2)
                    .toString()
                : null
            };
          } else {
            url =
              ConfigurationFac.getBaseServiceUrl() + '/ach/v1/users/' + accountId + '/deposit/limits/user';
            payload = {
              dailyDepositLimit: maxLimit.daily ?
                parseFloat(maxLimit.daily).toFixed(2).toString() : null,
              weeklyDepositLimit: maxLimit.weekly ?
                parseFloat(maxLimit.weekly).toFixed(2).toString() : null,
              monthlyDepositLimit: maxLimit.monthly ?
                parseFloat(maxLimit.monthly).toFixed(2).toString() : null
            };
          }
        }

        if (isCC) {
          method = 'PUT';
          if ($rootScope.activeFeatures.useUwtForDepositLimitsOnDma) {
            url = walletEndpoint('users') + '/' + accountId + '/limits/' + mapCardType[depositTypeId] + '/user';
            payload = {
              dailyLimit: maxLimit.daily
                ? parseFloat(maxLimit.daily)
                    .toFixed(2)
                    .toString()
                : null,
              weeklyLimit: maxLimit.weekly
                ? parseFloat(maxLimit.weekly)
                    .toFixed(2)
                    .toString()
                : null,
              monthlyLimit: maxLimit.monthly
                ? parseFloat(maxLimit.monthly)
                    .toFixed(2)
                    .toString()
                : null
            };
          } else {
            url = ConfigurationFac.getBaseServiceUrl() + '/ccp/v1/users/' + accountId + '/deposits/limits/user?cardType=' + mapCardType[depositTypeId];
            payload = {
              dailyDepositLimit: maxLimit.daily ?
                parseFloat(maxLimit.daily).toFixed(2).toString() : null,
              weeklyDepositLimit: maxLimit.weekly ?
                parseFloat(maxLimit.weekly).toFixed(2).toString() : null,
              monthlyDepositLimit: maxLimit.monthly ?
                parseFloat(maxLimit.monthly).toFixed(2).toString() : null
            };
          }
        }

        $http({
          method: method,
          url: url,
          data: payload,
          headers: _addHeaders()
        }).success(function (data) {
          if (isAchOrIbc || isCC || isApplePay) {
            deferred.resolve(data);
          }
          if (data.status === 'success') {
            deferred.resolve(data.response);
          } else {
            deferred.reject(data);
          }
        }).error(function (response) {
          deferred.reject(response);
        });

        return deferred.promise;
      },
      getPaymentForms: function () {
        return {
          NEW: {
            CC: [
              'card-type-selector',
              'card-number-input',
              'card-exp-date'
            ],
            IBC: [
              'bank-routing-number',
              'bank-account-number',
              'bank-name',
              'driver-license-number',
              'driver-license-state',
              'account-pin-pwd'
            ]
          },
          EDIT: {
            CC: [
              'card-type-selector',
              'card-number-input',
              'card-exp-date'
            ]
          }
        };
      }
    };
    return payMethods;
  }

  angular.module('TVG.ManagePaymentMethods')
    .factory('ManagePaymentMethodsSrv', ManagePaymentMethodsSrv);
}());

(function () {
  'use strict';

  notificationService.$inject = ['$compile', '$rootScope', '$q', '$document', '$window'];
  function notificationService($compile, $rootScope, $q, $document, $window) {
    var TEMPLATE = '<banner data-message="message" data-callback="callback" data-type="type" class="banner"></banner>';
    var notify = {};

    function buildArgs(title, message, elementBeforeBanner, callback, scroll) {
      return {
        title: title,
        message: message,
        elementBeforeBanner: elementBeforeBanner,
        callback: callback,
        scroll: scroll
      };
    }

    function closeExistingBanner() {
      $document.find('banner').remove();
    }

    function scrollTop() {
      var elem = $document[0].querySelectorAll('.banner')[0];
      if (elem) {
        if ([
          'touch3',
          'ios2',
          'fdrmobile',
          'fdrios',
          'fdrandroid',
          'androidwrapper',
          'tvgandroid'
        ].indexOf($window.productContext) >= 0) {
          // prevent scroll to on ios iframe
          return;
        }

        elem.scrollIntoView(false);
      }
    }

    notify.buildDialog = function (args, type) {
      var scope = $rootScope.$new();
      var templateElement;

      args.type = type;
      angular.extend(scope, args);

      templateElement = $compile(TEMPLATE)(scope);

      // Append to element
      if (args.elementBeforeBanner && args.elementBeforeBanner !== '') {
        if ($rootScope.isQuickDeposit) {
          angular.element($document[0].querySelector(args.elementBeforeBanner))
            .prepend(templateElement);
        }
        if ($rootScope.isFdrApp) {
          angular.element($document[0].querySelector('withdraw-type-selector'))
            .after(templateElement);
        } else {
          angular.element($document[0].querySelector(args.elementBeforeBanner))
            .after(templateElement);
        }
      } else {
        angular.element(
            $document[0].querySelector('deposit .tvg-deposit .deposit-form .methods-wrapper'))
          .prepend(templateElement);
      }

      if ([
        'touch3',
        'ios2',
        'fdrmobile',
        'fdrios',
        'fdrandroid',
        'androidwrapper',
        'tvgandroid'
      ].indexOf($window.productContext) < 0) {
        // prevent scroll to on ios iframe
        scrollTop();
      }

      return $q.when(scope);
    };

    notify.clearBanner = closeExistingBanner;

    /**
     * @param {String} title THIS VALUE IS NOT BEING USED. IT'S HERE JUST TO AVOID COMPATIBILITY ISSUES.
     * @param {String} message The banner's body message.
     * @param {String} elementBeforeBanner The element that is going to be the left sibling of the banner.
     * @param {function, optional} callback
     * @returns {Promise} promise resolved with the scope object used to create the banner element.
     */
    notify.success = function (title, message, elementBeforeBanner, callback, scroll) {
      var successOptions = buildArgs(title, message, elementBeforeBanner, callback, scroll);
      closeExistingBanner();
      return this.buildDialog(successOptions, 'success');
    };

    /**
     * @param {String} title THIS VALUE IS NOT BEING USED. IT'S HERE JUST TO AVOID COMPATIBILITY ISSUES.
     * @param {String} message The banner's body message.
     * @param {String} elementBeforeBanner The element that is going to be the left sibling of the banner.
     * @param {function, optional} callback
     * @returns {Promise} promise resolved with the scope object used to create the banner element.
     */
    notify.error = function (title, message, elementBeforeBanner, callback, scroll) {
      var errorOptions = buildArgs(title, message, elementBeforeBanner, callback, scroll);
      closeExistingBanner();
      return this.buildDialog(errorOptions, 'error');
    };

    /**
     * @param {String} title THIS VALUE IS NOT BEING USED. IT'S HERE JUST TO AVOID COMPATIBILITY ISSUES.
     * @param {String} message The banner's body message.
     * @param {String} elementBeforeBanner The element that is going to be the left sibling of the banner.
     * @param {function, optional} callback
     * @returns {Promise} promise resolved with the scope object used to create the banner element.
     */
    notify.cancel = function (title, message, elementBeforeBanner, callback, scroll) {
      var cancelOptions = buildArgs(title, message, elementBeforeBanner, callback, scroll);
      closeExistingBanner();
      return this.buildDialog(cancelOptions, 'cancel');
    };

    /**
     * @param {String} title THIS VALUE IS NOT BEING USED. IT'S HERE JUST TO AVOID COMPATIBILITY ISSUES.
     * @param {String} message The banner's body message.
     * @param {String} elementBeforeBanner The element that is going to be the left sibling of the banner.
     * @param {function, optional} callback
     * @returns {Promise} promise resolved with the scope object used to create the banner element.
     */
    notify.confirm = function (title, message, elementBeforeBanner, callback, scroll) {
      var confirmOptions = buildArgs(title, message, elementBeforeBanner, callback, scroll);
      closeExistingBanner();
      return this.buildDialog(confirmOptions, 'confirm');
    };

    notify.warning = function (title, message, elementBeforeBanner, callback, scroll) {
      var confirmOptions = buildArgs(title, message, elementBeforeBanner, callback, scroll);
      closeExistingBanner();
      return this.buildDialog(confirmOptions, 'warning');
    };

    return notify;
  }

  angular
    .module('TVG.Deposit')
    .factory('NotificationService', notificationService);
}());

(function () {
  'use strict';

  PayNearMeFac.$inject = ['$http', '$q', 'ConfigurationFac'];
  function PayNearMeFac($http, $q, ConfigurationFac) {
    var url = ConfigurationFac.getBaseServiceUrl();

    /**
     * @returns {Object} [Headers object. App context, Caching Headers]
     * @private
     */
    function _addHeaders() {
      var context = angular.toJson(ConfigurationFac.getApplicationContext());
      return {
        'x-tvgcontext': context,
        'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
        'Cache-Control': 'no-cache',
        Pragma: 'no-cache'
      };
    }

    /**
     * Get PNM Id
     * @param accountNumber
     * @returns {*}
     * @private
     */
    function _getPayNearMeId(accountNumber) {
      return $http({
        method: 'GET',
        url: url + '/pnm/v1/users/' + accountNumber + '/id',
        params: {},
        headers: _addHeaders()
      });
    }


    /**
     * Create PNM ID
     * @param accountNumber
     * @returns {*}
     * @private
     */
    function _createPayNearMeId(accountNumber) {
      return $http({
        method: 'POST',
        url: url + '/pnm/v1/users/' + accountNumber + '/id',
        data: {},
        headers: _addHeaders()
      });
    }

    return {
      getPayNearMeId: _getPayNearMeId,
      createPayNearMeId: _createPayNearMeId
    };
  }

  angular.module('TVG.Deposit').factory('PayNearMeFac', PayNearMeFac);
}());

(function () {
  'use strict';

  SightlineSrv.$inject = ['$http', '$q', 'Utilities', 'DepositPath', 'ConfigurationFac', '$location', '$window', 'RequestContextHeaders', '$log', '$rootScope'];
  function SightlineSrv(
      $http,
      $q,
      Utilities,
      DepositPath,
      ConfigurationFac,
      $location,
      $window,
      RequestContextHeaders,
      $log,
      $rootScope
    ) {
    var _isRedirectingToSightlineAddFunds = false;
    var _accountId = '';

    /**
     * Create an API error instance
     * @param  {Object} response  HTTP Response with nested errors
     * @return {Object}           Extracted errors
     */
    var createApiError = function (response) {
      var apiError = new ApiError();
      var responseError = response.data.errors[0];

      apiError.uri = response.config.url;
      apiError.message = responseError.message;
      apiError.code = responseError.code;

      return apiError;
    };

    /**
     * Create an API error instance from new HTTP code errors
     * @param  {Object} response  HTTP Response with nested errors
     * @return {Object}           Extracted errors
     */
    var createApiErrorFromHttpError = function (response, customData) {
      var apiError = new ApiError();
      var responseError = response.data || {};

      apiError.uri = (response.config || {}).url;
      apiError.message = responseError.message;
      apiError.code = responseError.exception || responseError.code;
      apiError.status = responseError.status;
      apiError.name = customData || undefined;

      return apiError;
    };

    /**
     * createSightlineAccount
     * @param  {object} user
     * @param  {object} user.accountNumber
     * @param  {object} user.firstName
     * @param  {object} user.lastName
     * @param  {object} user.ssn
     * @return {SightlineAccount}
     */
    var createSightlineAccount = function (user) {
      var account = new SightlineAccount(user);
      return account;
    };

    var createMerchant = function (merchantInfo) {
      return new Merchant(merchantInfo);
    };

    /**
     * endpoint
     * Give the endpoint resources, build the final URI.
     * @param {string} service being used to create URL
     * @return {string} URI
     */
    var endpoint = function (service) {
      return function (/* resources */) {
        var separator = '/';
        var resources = [].slice.call(arguments, 0);
        var baseUrl = ConfigurationFac.getServiceApiUrl(service) || '';
        var version = '/v1';

        if (service === 'slp') {
          version = '/v2';
          baseUrl = baseUrl.replace('/v1', version);
        }

        if (!baseUrl || baseUrl === 'false') {
          baseUrl = '/' + service + version;
        }

        if (service === 'slp' && baseUrl.indexOf(_accountId) !== 1) {
          return [baseUrl].concat(resources).concat(_accountId).join(separator);
        }
        return [baseUrl].concat(resources).join(separator);
      };
    };

    var sightlineEndpoint = endpoint('slp');
    var walletEndpoint = endpoint('uwt');

    /**
     * checkTransaction
     * Check if the transaction failed, although the request did not return
     * any error status code.
     *
     * @param  {$httpResponse} response the response object from the $http call
     * @return {Promise}
     * @FIXME angular doesn't respect the Promise A+ standard
     */
    var checkTransaction = function (response) {
      return $q(function (resolve, reject) {
        if (Utilities.prop('data.errors', response)) {
          return reject(createApiError(response));
        }

        return resolve(response);
      });
    };

    /**
     * request
     * @param  {Object} data
     * @param  {string} data.url
     * @param  {string} data.method
     * @param  {string} data.headers
     * @param  {Object} data.data
     *
     * @return {Promise}
     */
    var request = function (data, fullResponse, customData) {
      if (data) {
        data.headers = prepareHeaders(data.headers);
      }

      return $http(data)
        .then(checkTransaction)
        .then(function (response) { return fullResponse ? response : response.data; })
        .catch(function (err) {
          return $q.reject(createApiErrorFromHttpError(err, customData));
        });
    };

    /**
     * Add default headers if needed
     * @param  {Object} headers  Headers to send
     * @return {Object}          Headers with defaults
     */
    var prepareHeaders = function (headers) {
      var defaultHeaders = {};
      var xTvgContext = RequestContextHeaders[$window.clientApp + '_' + $window.locationContext];

      defaultHeaders['Content-Type'] = 'application/json';
      defaultHeaders['x-tvg-context'] = xTvgContext;

      return _.defaults(headers || {}, defaultHeaders);
    };

    /**
     * Return the merchant name, ID and application for the current environment
     *
     * @return {Promise} $http
     */
    var getMerchantInformation = Utilities.memoize(function () {
      var preUrl = sightlineEndpoint('merchant');
      var url = preUrl.substring(0, preUrl.indexOf('merchant') + 8);
      return request({
        url: url,
        method: 'GET'
      }).then(createMerchant);
    });

    var getBaseUrl = function (replaceState) {
      var product = ConfigurationFac.getApplicationContextItem('product');
      var location = ConfigurationFac.getApplicationContextItem('location');
      var wrapper = ConfigurationFac.getApplicationContextItem('wrapper');
      var callback = $location.search().callback && decodeURIComponent($location.search().callback);
      var path = (!replaceState && !wrapper) ? DepositPath[product] : $window.location.pathname;
      var qs = {
        njx: '?location=nj&product=njx',
        ios: '?product=ios',
        ios2: '?wrapper=true&product=ios2&location=' + location +
          '&callback=' + callback,
        touch3: '?wrapper=true&product=touch3&location=' + location +
          '&callback=' + callback,
        fdrmobile: '?wrapper=true&product=fdrmobile&location=' + location +
          '&callback=' + callback,
        fdrios: '?wrapper=true&product=fdrios&location=' + location +
          '&callback=' + callback,
        fdrandroid: '?wrapper=true&product=fdrandroid&location=' + location +
          '&callback=' + callback,
        androidwrapper: '?wrapper=true&product=androidwrapper&location=' + location +
          '&callback=' + callback,
        tvgandroid: '?wrapper=true&product=tvgandroid&location=' + location +
          '&callback=' + callback
      };
      var finalUrl;

      if ($rootScope.fullPage && path.indexOf('/registration') > -1) {
        path = path.replace('/registration', '/deposit/deposit');
      }

      finalUrl = Utilities.supplant('{protocol}://{host}{port}{path}', {
        protocol: $location.protocol(),
        host: !replaceState && callback ? callback.split('/')[0] : $location.host(),
        port: !replaceState && callback ? '' : ':' + $location.port(),
        path: (replaceState && _.has(qs, product)) ?
          path.concat(qs[product]) : path
      });

      $log.info(finalUrl);
      return finalUrl;
    };

    /**
     *
     * Sightline User Type
     * @typedef {Object} SightlineUser
     * @property {string} memberName
     * @property {string} firstName
     * @property {string} lastName
     * @property {string} email
     * @property {string} address
     * @property {string} city
     * @property {string} state
     * @property {string} country
     * @property {string} postalCode
     * @property {string} identityToken
     */

    /**
     * Sightline Account Type
     * @typedef {Object} SightlineAccount
     * @property  {string} sightlineAccount    Use the Member Number here
     * @property  {string} firstName
     * @property  {string} lastName
     */
    function SightlineAccount(user) {
      this.firstName = user.firstName;
      this.lastName = user.lastName;
      this.sightlineAccount = user.accountNumber;
    }

    /**
     * Sightline Transaction Type
     * @typedef {Object} SightlineTransaction
     * @property {string} merchantTransactionId
     * @property {string} paymentProcessorTransactionId
     */

    /**
     * Merchant Type
     * @typedef {Object} Merchant
     * @property {string} merchantId,
     * @property {string} merchantApplication
     * @property {string} merchantTransactionId
     * @property {string} merchantName
     */
    function Merchant(data) {
      this.merchantId = data.merchantId;
      this.merchantName = data.merchantName;
      this.merchantApplication = data.merchantApplication;
      this.merchantTransactionId = Utilities.uuid().replace(/-/g, '').slice(0, 30);
    }

    /**
     * @class ApiError
     * @extends Error
     */
    function ApiError() {
      this.uri = '';
      this.name = '';
      this.message = '';
      this.code = '';
      this.status = '';
      Error.apply(this, [].slice.call(arguments, 0));
    }

    ApiError.prototype = Object.create(Error.prototype);
    ApiError.prototype.constructor = ApiError;

    /**
     * @class
     * @constructor
     * @param {Object} data
     * @param {string} [data.accountNumber='']
     * @param {string} data.firstName
     * @param {string} data.lastName
     * @param {string} data.phoneNumber
     * @param {string} data.emailAddress
     * @param {string} data.Address1
     * @param {string} data.City
     * @param {string} data.StateAbbr
     * @param {string} [data.country='US']
     * @param {string} data.Zip
     * @param {string} data.identityToken
     */
    function SightlineUser(data) {
      var originTab = data.originTab || '';
      var wrapper = ConfigurationFac.getApplicationContextItem('wrapper') ? '&wrapper=true' : '';

      this.memberNumber = data.accountNumber || '';
      this.firstName = data.firstName || null;
      this.lastName = data.lastName || null;
      this.phoneNumber = data.phoneNumber || null;
      this.email = data.emailAddress || null;
      this.address = [
        Utilities.prop('homeAddress.streetNumber', data),
        Utilities.prop('homeAddress.address1', data),
        Utilities.prop('homeAddress.address2', data)
      ].filter(Boolean).join(' ') || null;
      this.city = data.homeAddress.city || data.homeAddress.City || null;
      this.state = data.homeAddress.state || data.homeAddress.StateAbbr || null;
      this.country = data.country || 'US';
      this.postalCode = data.homeAddress.zipCode || data.homeAddress.Zip || null;
      this.identityToken = data.identityToken;
      this.returnURL = getBaseUrl(false).concat(Utilities.returnToTab('sightline+' + originTab)) +
          ($rootScope.fullPage ? '&wrapper=true&fullPage=true&callback='
          + $rootScope.returnUrl : wrapper);
      this.merchantId = data.merchantId;
      this.merchantApplication = data.merchantApplication;
      this.merchantTransactionId = data.merchantTransactionId;
      this.merchantName = data.merchantName;
    }

    function depositErrorHandler(error) {
      var apiError = new ApiError();
      if (error.status === 500) {
        apiError.uri = error.uri;
        apiError.code = error.code;
        apiError.status = error.status;
        apiError.name = 'depositStatusPoller';

        if (error.code === 'SLP_WITHDRAW_FROM_SLP_DECLINED') {
          apiError.message = 'scenario1';
        } else if (error.code === 'SLP_TOTE_DEPOSIT_FAILED') {
          apiError.message = 'scenario3a';
        }
      }
      throw apiError;
    }

    return {
      createSightlineAccount: createSightlineAccount,

      /**
       * Check if the TVG user has enrolled a sightline card
       * @param {SightlineAccount} sightlineAccount
       * @return {Promise}
       */
      isSightlineUser: function (sightlineAccount) {
        return request({
          url: sightlineEndpoint('user') + '/account-info',
          method: 'GET',
          headers: prepareHeaders(),
          data: sightlineAccount
        }).then(Utilities.pick([
          'enrolled',
          'balance',
          'last4SSN'
        ]));
      },

      /**
       * Enroll user's sightline card with TVG
       * @return {Promise}
       */
      enrollSightlineUser: function (termsAccepted) {
        var data = {
          termsAccepted: termsAccepted || 0
        };
        return request({
          url: sightlineEndpoint('user') + '/enroll',
          method: 'POST',
          data: data
        });
      },

      /**
       * getToken
       * @param  {string} [id=''] Account Identifier
       * @return {Promise<SightlineUser, Error>}    $http
       */
      getToken: function (user, originTab) {
        var activeMenuTab = '+'.concat(originTab);
        var userObj = user || {};
        var fetchToken = function (accountNumber) {
          return request({
            url: sightlineEndpoint('user') + '/token',
            method: 'POST',
            data: { sightlineAccount: accountNumber || '' }
          })
          .then(Utilities.pick('identityToken'));
        };

        return $q.all([
          getMerchantInformation(),
          fetchToken(userObj.accountNumber)
        ])
        .then(function (data) {
          var merchant = data[0];
          var token = data[1];

          return new SightlineUser(angular.extend(
            {},
            userObj,
            merchant,
            token,
            { originTab: activeMenuTab }
          ));
        });
      },

      /**
       * Return the balance available in the card.
       *
       * @param  {SightlineAccount} account
       * @return {Promise<Number, Error>} $http
       */
      getBalance: function (account) {
        return request({
          url: sightlineEndpoint('balance'),
          method: 'POST',
          data: account
        })
          .then(Utilities.prop('balance'));
      },

      /**
       * Return the balance available in the card.
       *
       * @param  {string} id  The id of the transaction
       * @return {Promise} $http
       * @TODO Check response format with Tiago Costa
       */
      getTransactionStatus: function (id) {
        return request({
          url: sightlineEndpoint('transaction', id, 'status'),
          method: 'GET'
        })
        .then(Utilities.pick([
          'friendlyMessage',
          'transactionStatus'
        ]));
      },

          /**
       * transferToSightline
       * @param  {SightlineAccount} account [description]
       * @param  {Number} amount [description]
       * @return {Promise}
       */
      transferToSightline: function (amount) {
        var baseUrl = sightlineEndpoint('users').indexOf(_accountId) === -1 ? sightlineEndpoint('users') + '/' + _accountId : sightlineEndpoint('users');
        var url = baseUrl + '/withdrawal';
        return $http({
          method: 'POST',
          url: url,
          data: { amount: amount },
          headers: prepareHeaders()
        });
      },

      /**
       * transferToTVG
       * @param  {SightlineAccount} account [description]
       * @param  {Number} amount [description]
       * @return {Promise}
       */
      transferToTVG: Utilities.curry(function (account, amount) {
        var baseUrl = sightlineEndpoint('user').indexOf(_accountId) === -1 ? sightlineEndpoint('user') + '/' + _accountId : sightlineEndpoint('user');
        var url = baseUrl + '/deposit';

        return request({
          url: url,
          method: 'POST',
          data: angular.extend({}, account, {
            tvgAccount: account.sightlineAccount,
            amount: amount
          }, true)
        }, true)
        .then(function (res) {
          return res;
        })
        .then(function (data) {
          data.requestedAmount = amount;
          data.depositAvailableDate = 'immediately';
          return data;
        });
      }),

      fundAndTransferToTVG: function (depositData) {
        var fundUrl = sightlineEndpoint('user') + '/funding/' + depositData.selectedCardType.id;
        return request({
          url: fundUrl,
          method: 'POST',
          data: {
            amount: +depositData.amount + depositData.sightlineUser_v2.depositFee,
            paymentCard: {
              id: depositData.selectedCardType.id,
              securityNumber: depositData.cardSecurityNumber
            }
          }
        }, true, 'fundingError')
          // fund success  --> deposit
          .then(function () {
            return request({
              url: sightlineEndpoint('user') + '/deposit',
              method: 'POST',
              data: {
                amount: depositData.amount
              }
            }, true, 'fundSuccessDepositFail');
          })
        // fund or deposit error
        .catch(function (error) {
          // if fund error --> try deposit
          if (error.name === 'fundingError') {
            return request({
              url: sightlineEndpoint('user') + '/deposit',
              method: 'POST',
              data: {
                amount: depositData.amount
              }
            }, true, 'depositFailFundFail').catch(function (depError) {
              return depositErrorHandler(depError);
            });
          }
          throw error;
        });
      },


      cancelWithdrawal: function (withdrawalId) {
        return request({
          url: walletEndpoint('withdrawal', withdrawalId, 'cancel'),
          method: 'POST'
        });
      },

      setInfo: function (accountId) {
        if (accountId && accountId !== _accountId) {
          _accountId = accountId;
        }
      },

      /**
       * Get/set the "_isRedirectingToSightlineAddFunds" flag
       * (used because of TVG3 not having the same rootScope as TVG4)
       *
       * @param {Boolean} [val]  New redirecting flag value
       * @return {Boolean}       Whether is redirecting
       */
      isRedirectingToSightlineAddFunds: function (val) {
        if (typeof val === 'boolean') {
          _isRedirectingToSightlineAddFunds = val;
        }

        return _isRedirectingToSightlineAddFunds;
      },

      getSightlineFlowVersion: function (accountId) {
        var deferred = $q.defer();
        var headers = prepareHeaders();
        var userEndpoint;
        var baseUrl;

        _accountId = accountId;

        userEndpoint = sightlineEndpoint('user');
        baseUrl = userEndpoint.indexOf(accountId) > -1 ? userEndpoint : userEndpoint + '/' + accountId;

        /* eslint-disable */
        $http.get(baseUrl + '/version', { headers: headers }).success(function (data) {
          deferred.resolve(data.versionName);
        }).error(function (error) {
          deferred.resolve('SLN version error');
        });

        return deferred.promise;
      }

    };
  }

  /* eslint-disable */
  angular
    .module('TVG.Deposit')
    .service('SightlineSrv', SightlineSrv);
  /* eslint-enable */
}());

(function () {
  'use strict';

  TransferSrv.$inject = ['$http', '$q', '$location', '$filter', '$window', '$timeout', '$rootScope', 'ConfigurationFac', 'Utilities'];
  function TransferSrv($http,
            $q,
            $location,
            $filter,
            $window,
            $timeout,
            $rootScope,
            ConfigurationFac,
            Utilities) {
    var _optionsAccounts = [ // --> Temp.
      {
        id: 1,
        name: 'Tote',
        label: '4NJBETS',
        availableAmount: 0
      },
      {
        id: 2,
        name: 'NJExchange',
        label: 'NJExchange',
        availableAmount: 0
      }
    ];

    var transfer;
    var _accountId = '';
    var usaEndpoint = Utilities.endpoint('usa');
    var exwEndpoint = Utilities.endpoint('exw');
    var _failedExchange = true;
    var _failedSession = false;
    var _failedContext = true;

    function _addHeaders(token) {
      var context = angular.toJson(ConfigurationFac.getApplicationContext());
      return {
        'x-tvgcontext': context,
        userToken: token
      };
    }

    function getContext(token) {
      var deferred = $q.defer();
      $http.get(usaEndpoint('session') + '/context', { headers: _addHeaders(token) })
        .success(function (data) {
          if (data.accountNumber) {
            _accountId = data.accountNumber;
          }
          _failedContext = false;
          deferred.resolve(data.accountNumber);
        })
        .catch(function (err) {
          if (err.status && err.status === 401) {
            _failedSession = true;
          }
          _failedContext = true;
          deferred.resolve(err);
        });
      return deferred.promise;
    }

    function getExchangeId(token) {
      var deferred = $q.defer();
      if (_failedSession || _failedContext) {
        deferred.resolve({});
        return deferred.promise;
      }
      $http.get(exwEndpoint('users') + '/' + _accountId, { headers: _addHeaders(token) })
        .success(function (data) {
          _failedExchange = false;
          deferred.resolve(data);
        })
        .catch(function (err) {
          _failedExchange = true;
          deferred.resolve(err);
        });
      return deferred.promise;
    }

    function _getTransferInitialData(token) {
      return getContext(token).then(function () {
        return getExchangeId(token);
      });
    }

    function _makeTransfer(transferData, token) {
      var deferred = $q.defer();
      var end = transferData.destination === 'Tote' ? 'deposit' : 'withdrawal';

      $http({
        method: 'POST',
        url: exwEndpoint('users') + '/' + _accountId + '/' + end,
        headers: _addHeaders(token),
        data: {
          amount: transferData.amount.toString()
        }
      }).success(function (data, status) {
        deferred.resolve({ response: data, status: status });
      }).error(function (data) {
        deferred.reject(data);
      });

      return deferred.promise;
    }

    transfer = {
      failedSession: function () { return _failedSession; },
      failedContext: function () { return _failedContext; },
      failedExchange: function () { return _failedExchange; },
      getTransferInitialData: function () {
        var deferred = $q.defer();
        var currentUserSession;

        if (ConfigurationFac.getApplicationContextItem('product') !== 'njx') {
          _.attempt(function () {
            if ($window.document.domain === $window.parent.document.domain) {
              currentUserSession = $window.parent.getCurrentUserSession;
            }
          });
        }

        if (currentUserSession) {
          $window.parent.getCurrentUserSession(
            function (data) { // --> Success to get Token
              var token = data ? data.sessionToken : undefined;
              _getTransferInitialData(token).then(
                function (response) {
                  deferred.resolve(response);
                },
                function (err) {
                  deferred.resolve(err);
                });
            },
            function () {
              _getTransferInitialData().then(
                function (response) {
                  deferred.resolve(response);
                },
                function (data) {
                  deferred.resolve(data);
                });
            });
        } else { // --> No function to get Token
          _getTransferInitialData().then(
            function (response) {
              deferred.resolve(response);
            },
            function (data) {
              deferred.resolve(data);
            });
        }

        return deferred.promise;
      },
      makeTransfer: function (transferData) {
        var deferred = $q.defer();
        var currentUserSession;

        _.attempt(function () {
          currentUserSession = $window.parent.getCurrentUserSession;
        });

        if (currentUserSession) {
          $window.parent.getCurrentUserSession(
            function (data) { // --> Success to get Token
              var token = data ? data.sessionToken : undefined;

              _makeTransfer(transferData, token).then(
                function (response) {
                  deferred.resolve(response);
                },
                function (err) {
                  deferred.reject(err);
                });
            },
            function () { // --> Failure to get Token
              _makeTransfer(transferData).then(
                function (response) {
                  deferred.resolve(response);
                },
                function (err) {
                  deferred.reject(err);
                });
            });
        } else { // --> No function to get Token
          _makeTransfer(transferData).then(
            function (response) {
              deferred.resolve(response);
            },
            function (err) {
              deferred.reject(err);
            });
        }

        return deferred.promise;
      },
      getOptionsAccounts: function () {
        return _optionsAccounts;
      }
    };
    return transfer;
  }

  angular.module('TVG.Transfer').factory('TransferSrv', TransferSrv);
}());

(function () {
  'use strict';

  UserFactory.$inject = ['Utilities'];
  function UserFactory(Utilities) {
    var pickAndLowerFirst = Utilities.compose(
      Utilities.pick([
        'accountNumber',
        'dateOfBirth',
        'emailAddress',
        'exchangeSubAccountNumber',
        'firstName',
        'gender',
        'homeAddress',
        'lastName',
        'mailingAddress',
        'primaryPhone',
        'secondaryPhone',
        'signalProviderID',
        'transportID',
        'username',
        'userName',
        'wageringStatus'
      ]),
      Utilities.mapKeys(Utilities.lowerFirst)
    );

    var isSet = function (value) {
      return (angular.isDefined(value) && value !== null);
    };

    var setOrDefault = Utilities.curry(function (defaultValue, value) {
      return (isSet(value)) ? value : defaultValue;
    });

    var setOrNull = setOrDefault(null);

    function User(props) {
      var data = props || {}; // avoid breaking and fail silently

      this.accountNumber = setOrNull(data.accountNumber);
      this.dateOfBirth = setOrNull(data.dateOfBirth);
      this.emailAddress = setOrNull(data.emailAddress);
      this.exchangeSubAccountNumber = setOrNull(data.exchangeSubAccountNumber);
      this.firstName = setOrNull(data.firstName);
      this.gender = setOrNull(data.gender);
      this.homeAddress = setOrNull(data.homeAddress);
      this.lastName = setOrNull(data.lastName);
      this.mailingAddress = setOrNull(data.mailingAddress);
      this.phoneNumber = setOrNull(data.primaryPhone);
      this.secondaryPhone = setOrNull(data.secondaryPhone);
      this.signalProviderID = setOrNull(data.signalProviderID);
      this.transportID = setOrNull(data.transportID);
      this.username = setOrNull(data.username) || setOrNull(data.userName);
      this.wageringStatus = setOrNull(data.wageringStatus);
    }

    User.prototype = {

      constructor: User, // Restore the constructor reference

      /**
       * has
       * Check if the instance has the given property
       * Note: if a property is `false` the result is still `true`
       * since it *has* the property
       *
       * @param  {string}  prop Object property or property path
       * @return {Boolean}
       */
      has: function (prop) {
        var value = Utilities.prop(prop, this);
        return isSet(value);
      },
      /**
       * get
       * Return the specified property. If no arguments are given, return the
       * saved data
       *
       * @param  {string} [prop]
       * @return {mixed}
       */
      get: function (prop) {
        if (!prop) {
          return this;
        }
        return Utilities.prop(prop, this);
      },

      /**
       * set
       * Set properties to the user object
       *
       * @param {string} prop Name of the property to be set
       * @param {mixed} data Data to be saved
       * @return {object}
       */
      set: function (prop, data) {
        this[prop] = data;
        return this.data;
      }
    };

    User.build = function (data) {
      return new User(pickAndLowerFirst(data || {}));
    };

    return User;
  }

  angular
    .module('TVG.Deposit')
    .factory('UserFactory', UserFactory);
}());

'use strict';

angular
  .module('TVG.Withdraw')
  .constant('SightlineConfig', {
    id: 'SLN',
    name: 'TVG Pre Paid Card',
    min: 10,
    max: 25000
  })
  .constant('PaypalConfig', {
    id: 'PAY',
    name: 'PayPal',
    min: 10,
    max: 25000
  })
  .constant('CreditCardConfig', {
    id: 'DEBIT_CARD',
    name: 'Debit Card',
    min: 10,
    max: 10000
  })
  .constant('BetCashConfig', {
    id: 'BETCASH',
    name: 'eCheck',
    min: 10,
    max: 10000
  })
  .constant('CheckRequestConfig', {
    id: 'CHECK',
    name: 'Check Request',
    min: 10,
    max: 10000
  });

(function () {
  'use strict';

  WithdrawFac.$inject = ['$http', '$q', 'ConfigurationFac', 'SightlineConfig', 'PaypalConfig', 'SightlineSrv', 'CreditCardConfig', 'CheckRequestConfig', 'BetCashConfig', 'paypalService', 'Utilities', '$rootScope', '$window', 'RequestContextHeaders', '$timeout'];
  function WithdrawFac($http,
                       $q,
                       ConfigurationFac,
                       SightlineConfig,
                       PaypalConfig,
                       SightlineSrv,
                       CreditCardConfig,
                       CheckRequestConfig,
                       BetCashConfig,
                       paypalService,
                       Utilities,
                       $rootScope,
                       $window,
                       RequestContextHeaders,
                       $timeout) {
    var _accountId = '';
    var ccpEndpoint = Utilities.endpoint('ccp');

    /**
     * Returns available forms
     * @returns
     * {{CHECK: {HOME: string[], MAIL: string[]}, DIRECT: {DIRECT: string[]}}}
     * @private
     */
    function _getForms() {
      return {
        CHECK: [
          'withdraw-account-info',
          'withdraw-home-mail-selector',
          'withdraw-amount-input'
        ],
        DEBIT_CARD: [
          'withdraw-account-info',
          'withdraw-card-selector',
          'withdraw-amount-input',
          'withdraw-total-cost'
        ],
        BETCASH: [
          'withdraw-account-info',
          'withdraw-betcash-selector',
          'withdraw-amount-input'
        ],
        SLN: [
          'withdraw-account-info',
          'withdraw-amount-input'
        ],
        PAY: [
          'withdraw-account-info',
          'withdraw-amount-input',
          'withdraw-provider-email'
        ]
      };
    }

    //eslint-disable-next-line
    var usaEndpoint = Utilities.endpoint('usa');
    //eslint-disable-next-line
    var walletEndpoint = Utilities.endpoint('uwt');


    function _getWithdrawOptions(opts) {
      var config = {
        SLN: SightlineConfig,
        PAY: PaypalConfig,
        DEBIT_CARD: CreditCardConfig,
        CHECK: CheckRequestConfig,
        BETCASH: BetCashConfig
      };
      if ($rootScope.isFdrApp) {
        BetCashConfig.name = 'eCheck';
        SightlineConfig.name = 'FanDuel Pre Paid';
      }

      return opts.map(function (opt) {
        return config[opt];
      }).filter(Boolean);
    }

    /**
     * Fetches withdraw initial data
     * @returns promise
     * @private
     */
    function _getData() {
      return _makeGETRequest(_baseUrl() +
        'withdrawalInitialData', _initialDataParser);
    }

    function _getWithdrawalProfile() {
      _accountId = '';
      return _getAccountBalance().then(function (response) {
        var url = '/uam/v1/users/' + _accountId + '/profile';
        url = ConfigurationFac.getBaseServiceUrl() + url;
        return $http({
          method: 'GET',
          url: url,
          headers: _addHeaders()
        }).then(function (res) {
          return response ?
           Object.assign(response, res.data) : res.data;
        })
        .catch(function () {
          return { response: response, failure: true };
        });
      });
    }

     /**
       * Get user account number incase it's not previously loaded
       */
    function _getAccountNumber() {
      return $http({
        url: usaEndpoint('session') + '/context',
        method: 'GET',
        headers: _addHeaders()
      }).then(function (data) {
        if (data.data.accountNumber) {
          _accountId = data.data.accountNumber;
        }
        return data.data.accountNumber;
      }).catch(function (err) {
        return err;
      });
    }

    function _getAccountId() {
      var deferred = $q.defer();
      return !_accountId ? _getAccountNumber() : $timeout(function () {
        deferred.resolve(_accountId);
        return deferred.promise;
      }, 200);
    }

    function _getPlainAccountId() {
      return _accountId;
    }

    function _getAccountBalance() {
      return _getAccountId().then(function (accountId) {
        return $http({
          url: walletEndpoint('users') + '/' + accountId + '/withdrawal/balance',
          method: 'GET',
          headers: _addHeaders()
        }).then(function (data) {
          return data.data;
        }).catch(function (err) {
          return err;
        });
      });
    }

    /**
     * Withdraws a specified amount using betCash payment method
     * @param amount - amount to withdraw
     * @param achId - betCash account id
     * @returns promise
     * @private
     */
    function _withdrawBetCash(amount, achId) {
      return _makeGETRequest(_baseUrl() +
        'withdrawalAch?amount=' +
        amount +
        '&achId=' +
        achId, undefined);
    }

    function _withdrawNewDepositFlow(amount, accountId, paymentType) {
      var url = '/uwt/v1/users/' + accountId + '/withdrawal';
      url = ConfigurationFac.getBaseServiceUrl() + url;
      return $http({
        method: 'POST',
        url: url,
        data: { amount: amount, paymentType: paymentType },
        headers: _addHeaders()
      });
    }

    function _withdrawBetcashNewDepositFlow(amount, accountId, achId) {
      var url = '/ach/v1/users/' + accountId + '/withdrawals';
      url = ConfigurationFac.getBaseServiceUrl() + url;
      return $http({
        method: 'POST',
        url: url,
        data: { amount: amount, achId: achId },
        headers: _addHeaders()
      });
    }

    function _withdrawDebitCard(amount, accountId, ccid) {
      var url = '/ccp/v1/users/' + accountId + '/bankCard/' + ccid + '/withdrawal';
      url = ConfigurationFac.getBaseServiceUrl() + url;
      return $http({
        method: 'POST',
        url: url,
        data: { amount: amount },
        headers: _addHeaders()
      });
    }

    /**
     * Withdraws a specified amount using check payment method
     * @param amount - amount to withdraw
     * @param accountNumber - accountNumber
     * @param locationCode - MAILING or RESIDENTIAL
     * @returns promise
     * @private
     */
    function _withdrawCheck(amount, accountNumber, locationCode) {
      return $http({
        method: 'POST',
        url: ConfigurationFac.getBaseServiceUrl() + '/chk/v1/users/' + accountNumber + '/withdrawal',
        data: {
          amount: amount.toString(),
          address: locationCode
        },
        headers: _addHeaders()
      });
    }

    /**
     * Get list of pending Withdraws
     * @returns promise
     * @private
     */
    function _withdrawPendingList() {
      var options = {
        headers: _addHeaders({ cache: true })
      };

      var url = '/uwt/v1/users/' + _accountId + '/withdrawals/pending';

      url = ConfigurationFac.getBaseServiceUrl() + url;

      return $http.get(url, options)
        .then(Utilities.prop('data.pendingWithdrawalsList'));
    }

    function _withdrawCancel(withdrawId) {
      return $http({
        method: 'DELETE',
        url: ConfigurationFac.getBaseServiceUrl() + '/uwt/v1/users/' + _accountId + '/withdrawals/' + withdrawId,
        headers: _addHeaders()
      });
    }

    /**
     * Withdraw data parser
     * @param response - response from server
     * @returns {{locationTypes: *, achAccounts: *, accountInfo: *}}
     * @private
     */
    function _initialDataParser(response) {
      _accountId = response.accountInfo.accountNumber;

      SightlineSrv.setInfo(_accountId);

      return {
        locationTypes: _locationTypeParser(response.locationTypes,
          response.accountInfo || {
            homeAddress: {},
            mailingAddress: {}
          }
        ),
        achAccounts: _betCashAccountsParser(response.achOnFile.AchAccounts),
        accountInfo: _accountInfoParser(response.accountInfo || {}),
        responseData: response
      };
    }

    /**
     * Location types parser
     * @param locationTypes - location types from server
     * @param accountInfo - account info from server
     * @returns {Array} - array of location types
     * @private
     */
    function _locationTypeParser(locationTypes, accountInfo) {
      var locationTypeList = [];
      var addressObj = {
        home: _buildAddressText(accountInfo.homeAddress),
        mail: _buildAddressText(accountInfo.mailingAddress)
      };

      angular.forEach(locationTypes, function (locationType) {
        var address;

        if (locationType.Id === 0) {
          address = addressObj.home;
        } else if (locationType.Id === 1) {
          address = addressObj.mail;
        }

        if (locationType.Id === 0 || locationType.Id === 1) {
          locationTypeList.push({
            id: locationType.Id,
            name: locationType.Name,
            address: address
          });
        }
      });

      return locationTypeList;
    }


    /**
     * Build address text
     * @param address - available in account info object from server
     * @returns {string} - parsed address or empty string if
     * argument is undefined
     * @private
     */
    function _buildAddressText(address) {
      var trimmedObj = {
        StreetNumber: '',
        Address1: '',
        Address2: '',
        City: '',
        StateAbbr: '',
        Zip: ''
      };

      angular.forEach(address, function (value, key) {
        if (angular.isString(value)) {
          trimmedObj[key] = value.trim() + ' ';
        }
      });

      return (
        trimmedObj.StreetNumber +
        trimmedObj.Address1 +
        trimmedObj.Address2 +
        trimmedObj.City +
        trimmedObj.StateAbbr +
        trimmedObj.Zip
      ).trim();
    }

    /**
     * BetCash accounts parser
     * @param response - response from server
     * @returns {Array} - array of betCash account objects
     * @private
     */
    function _betCashAccountsParser(response) {
      var achAccountList = [];
      angular.forEach(response, function (achAccount) {
        var name = '(*****' + achAccount.BankAcctNumber.substr(achAccount.BankAcctNumber.length - 4)
          + ') ' + achAccount.BankName;

        achAccountList.push({
          name: name,
          achId: achAccount.AppAchId,
          bankName: achAccount.BankName
        });
      });
      return achAccountList;
    }

    /**
     * Parses account info data
     * @param accountInfo - account info from server
     * @private
     */
    function _accountInfoParser(accountInfo) {
      return {
        avBalance: accountInfo.availableWithdrawAmount,
        balance: accountInfo.currentBalance,
        accountNumber: accountInfo.accountNumber,
        minWithdraw: accountInfo.minWithdraw,
        user: accountInfo
      };
    }

    /**
     * Returns the base url for all the http requests based on location host
     * @returns {string} - base URL
     * @private
     */
    function _baseUrl() {
      var protocol;

      if ($rootScope.useAbsoluteRequests ||
        ConfigurationFac.absoluteRequests()) {
        protocol = ConfigurationFac
          .getBaseUrlForApplicationContext('protocol') ?
          ConfigurationFac.getBaseUrlForApplicationContext('protocol') : '//';

        return protocol +
          ConfigurationFac.getBaseUrlForApplicationContext('deposit') +
          '/deposit/api/v1.0/';
      }

      return '/deposit/api/v1.0/';
    }

    /**
     * Make GET requests
     * @param url - URL to request
     * @param parser - optional function to execute if success response
     * @returns {Deferred.promise|*}
     * @private
     */
    function _makeGETRequest(url, parser) {
      var deferred = $q.defer();
      var headers = _addHeaders({
        cache: true
      });

      $http.get(url, { headers: headers }).success(function (data) {
        if (data.status === 'success') {
          if (parser && angular.isFunction(parser)) {
            deferred.resolve(parser(data.response));
          } else {
            deferred.resolve(data.response);
          }
        } else {
          deferred.reject(data.response);
        }
      }).error(function (data) {
        var rsp;
        if (data) {
          rsp = data.response;
        }
        deferred.reject(rsp);
      });

      return deferred.promise;
    }

    function _addHeaders(options) {
      var headers = {
        'x-tvgcontext': angular.toJson(ConfigurationFac.getApplicationContext()),
        'x-tvg-context': RequestContextHeaders[
          $window.productContext + '_' + $window.locationContext
        ]
      };

      if (options && options.cache) {
        angular.extend(headers, {
          'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
          'Cache-Control': 'no-cache',
          Pragma: 'no-cache'
        });
      }

      return headers;
    }

    /**
     * Get cards on file for withdraw
     * @param accountId
     * @private
     */
    function _getCardsOnFile(accountId) {
      var deferred = $q.defer();
      var headers = _addHeaders({ cache: true });
      var url = ccpEndpoint('users') + '/' + accountId + '/bankCards?filterAvailable=true&filterWithdrawalAllowed=true';

      $http.get(url,
        { headers: headers })
        .success(function (data) {
          deferred.resolve(data);
        }).error(function (data) {
          deferred.reject(data);
        });

      return deferred.promise;
    }

    /**
     * Public interface
     */
    return {
      getData: _getData,
      getAccountNumber: _getAccountNumber,
      getAccountId: _getAccountId,
      getAccountBalance: _getAccountBalance,
      getWithdrawalProfile: _getWithdrawalProfile,
      getPlainAccountId: _getPlainAccountId,
      withdrawBetCash: _withdrawBetCash,
      withdrawCheck: _withdrawCheck,
      withdrawBetcashNewDepositFlow: _withdrawBetcashNewDepositFlow,
      withdrawNewDepositFlow: _withdrawNewDepositFlow,
      withdrawPaypal: paypalService.withdraw,
      withdrawDebitCard: _withdrawDebitCard,
      withdrawPendingList: _withdrawPendingList,
      withdrawCancel: _withdrawCancel,
      getForms: _getForms,
      getWithdrawOptions: _getWithdrawOptions,
      getCardsOnFile: _getCardsOnFile
    };
  }

  angular.module('TVG.Withdraw').factory('WithdrawFac', WithdrawFac);
}());

define("Deposit", ["angular"], function(){});

../node_modules/@tvg/deposit-gtm/build/bundle.js
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define('DepositGTM',[], factory);
	else {
		var a = factory();
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// identity function for calling harmony imports with the correct context
/******/ 	__webpack_require__.i = function(value) { return value; };
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 274);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

module.exports = isArray;

/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var freeGlobal = __webpack_require__(87);

/** Detect free variable `self`. */
var freeSelf = (typeof self === 'undefined' ? 'undefined' : _typeof(self)) == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

module.exports = root;

/***/ }),
/* 2 */
/***/ (function(module, exports) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return value != null && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'object';
}

module.exports = isObjectLike;

/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var bind = __webpack_require__(64);
var isBuffer = __webpack_require__(137);

/*global toString:true*/

// utils is a library of generic helper functions non-specific to axios

var toString = Object.prototype.toString;

/**
 * Determine if a value is an Array
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an Array, otherwise false
 */
function isArray(val) {
  return toString.call(val) === '[object Array]';
}

/**
 * Determine if a value is an ArrayBuffer
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an ArrayBuffer, otherwise false
 */
function isArrayBuffer(val) {
  return toString.call(val) === '[object ArrayBuffer]';
}

/**
 * Determine if a value is a FormData
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an FormData, otherwise false
 */
function isFormData(val) {
  return typeof FormData !== 'undefined' && val instanceof FormData;
}

/**
 * Determine if a value is a view on an ArrayBuffer
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
 */
function isArrayBufferView(val) {
  var result;
  if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) {
    result = ArrayBuffer.isView(val);
  } else {
    result = val && val.buffer && val.buffer instanceof ArrayBuffer;
  }
  return result;
}

/**
 * Determine if a value is a String
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a String, otherwise false
 */
function isString(val) {
  return typeof val === 'string';
}

/**
 * Determine if a value is a Number
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Number, otherwise false
 */
function isNumber(val) {
  return typeof val === 'number';
}

/**
 * Determine if a value is undefined
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if the value is undefined, otherwise false
 */
function isUndefined(val) {
  return typeof val === 'undefined';
}

/**
 * Determine if a value is an Object
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an Object, otherwise false
 */
function isObject(val) {
  return val !== null && (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object';
}

/**
 * Determine if a value is a Date
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Date, otherwise false
 */
function isDate(val) {
  return toString.call(val) === '[object Date]';
}

/**
 * Determine if a value is a File
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a File, otherwise false
 */
function isFile(val) {
  return toString.call(val) === '[object File]';
}

/**
 * Determine if a value is a Blob
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Blob, otherwise false
 */
function isBlob(val) {
  return toString.call(val) === '[object Blob]';
}

/**
 * Determine if a value is a Function
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Function, otherwise false
 */
function isFunction(val) {
  return toString.call(val) === '[object Function]';
}

/**
 * Determine if a value is a Stream
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Stream, otherwise false
 */
function isStream(val) {
  return isObject(val) && isFunction(val.pipe);
}

/**
 * Determine if a value is a URLSearchParams object
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a URLSearchParams object, otherwise false
 */
function isURLSearchParams(val) {
  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
}

/**
 * Trim excess whitespace off the beginning and end of a string
 *
 * @param {String} str The String to trim
 * @returns {String} The String freed of excess whitespace
 */
function trim(str) {
  return str.replace(/^\s*/, '').replace(/\s*$/, '');
}

/**
 * Determine if we're running in a standard browser environment
 *
 * This allows axios to run in a web worker, and react-native.
 * Both environments support XMLHttpRequest, but not fully standard globals.
 *
 * web workers:
 *  typeof window -> undefined
 *  typeof document -> undefined
 *
 * react-native:
 *  navigator.product -> 'ReactNative'
 */
function isStandardBrowserEnv() {
  if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
    return false;
  }
  return typeof window !== 'undefined' && typeof document !== 'undefined';
}

/**
 * Iterate over an Array or an Object invoking a function for each item.
 *
 * If `obj` is an Array callback will be called passing
 * the value, index, and complete array for each item.
 *
 * If 'obj' is an Object callback will be called passing
 * the value, key, and complete object for each property.
 *
 * @param {Object|Array} obj The object to iterate
 * @param {Function} fn The callback to invoke for each item
 */
function forEach(obj, fn) {
  // Don't bother if no value provided
  if (obj === null || typeof obj === 'undefined') {
    return;
  }

  // Force an array if not already something iterable
  if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' && !isArray(obj)) {
    /*eslint no-param-reassign:0*/
    obj = [obj];
  }

  if (isArray(obj)) {
    // Iterate over array values
    for (var i = 0, l = obj.length; i < l; i++) {
      fn.call(null, obj[i], i, obj);
    }
  } else {
    // Iterate over object keys
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fn.call(null, obj[key], key, obj);
      }
    }
  }
}

/**
 * Accepts varargs expecting each argument to be an object, then
 * immutably merges the properties of each object and returns result.
 *
 * When multiple objects contain the same key the later object in
 * the arguments list will take precedence.
 *
 * Example:
 *
 * ```js
 * var result = merge({foo: 123}, {foo: 456});
 * console.log(result.foo); // outputs 456
 * ```
 *
 * @param {Object} obj1 Object to merge
 * @returns {Object} Result of all merge properties
 */
function merge() /* obj1, obj2, obj3, ... */{
  var result = {};
  function assignValue(val, key) {
    if (_typeof(result[key]) === 'object' && (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') {
      result[key] = merge(result[key], val);
    } else {
      result[key] = val;
    }
  }

  for (var i = 0, l = arguments.length; i < l; i++) {
    forEach(arguments[i], assignValue);
  }
  return result;
}

/**
 * Extends object a by mutably adding to it the properties of object b.
 *
 * @param {Object} a The object to be extended
 * @param {Object} b The object to copy properties from
 * @param {Object} thisArg The object to bind function to
 * @return {Object} The resulting value of object a
 */
function extend(a, b, thisArg) {
  forEach(b, function assignValue(val, key) {
    if (thisArg && typeof val === 'function') {
      a[key] = bind(val, thisArg);
    } else {
      a[key] = val;
    }
  });
  return a;
}

module.exports = {
  isArray: isArray,
  isArrayBuffer: isArrayBuffer,
  isBuffer: isBuffer,
  isFormData: isFormData,
  isArrayBufferView: isArrayBufferView,
  isString: isString,
  isNumber: isNumber,
  isObject: isObject,
  isUndefined: isUndefined,
  isDate: isDate,
  isFile: isFile,
  isBlob: isBlob,
  isFunction: isFunction,
  isStream: isStream,
  isURLSearchParams: isURLSearchParams,
  isStandardBrowserEnv: isStandardBrowserEnv,
  forEach: forEach,
  merge: merge,
  extend: extend,
  trim: trim
};

/***/ }),
/* 4 */
/***/ (function(module, exports) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
  return value != null && (type == 'object' || type == 'function');
}

module.exports = isObject;

/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {

var _Symbol = __webpack_require__(11),
    getRawTag = __webpack_require__(191),
    objectToString = __webpack_require__(223);

/** `Object#toString` result references. */
var nullTag = '[object Null]',
    undefinedTag = '[object Undefined]';

/** Built-in value references. */
var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;

/**
 * The base implementation of `getTag` without fallbacks for buggy environments.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
    if (value == null) {
        return value === undefined ? undefinedTag : nullTag;
    }
    return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
}

module.exports = baseGetTag;

/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsNative = __webpack_require__(158),
    getValue = __webpack_require__(192);

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

module.exports = getNative;

/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {

var convert = __webpack_require__(14),
    func = convert('cloneDeep', __webpack_require__(240), __webpack_require__(32));

func.placeholder = __webpack_require__(9);
module.exports = func;

/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {

var convert = __webpack_require__(14),
    func = convert('merge', __webpack_require__(264));

func.placeholder = __webpack_require__(9);
module.exports = func;

/***/ }),
/* 9 */
/***/ (function(module, exports) {

/**
 * The default argument placeholder value for methods.
 *
 * @type {Object}
 */
module.exports = {};

/***/ }),
/* 10 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = GTMEvent;
/* harmony export (immutable) */ __webpack_exports__["b"] = isCard;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_extend__ = __webpack_require__(248);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_extend___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_extend__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_isString__ = __webpack_require__(250);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_isString___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_isString__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_lodash_fp_isUndefined__ = __webpack_require__(251);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_lodash_fp_isUndefined___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_fp_isUndefined__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty__ = __webpack_require__(249);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__constants_screenNames__ = __webpack_require__(275);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__constants_screenNames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4__constants_screenNames__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__constants_sectionNames__ = __webpack_require__(276);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5__constants_sectionNames__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_lodash_get__ = __webpack_require__(138);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_lodash_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_lodash_get__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__tvg_conf_classic__ = __webpack_require__(119);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__tvg_conf_classic___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7__tvg_conf_classic__);





var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };



// eslint-disable-line



function GTMEvent() {
    var sendCondition = true;
    return {
        when: function when(condition) {
            if (sendCondition) {
                sendCondition = condition;
            }
            return this;
        },
        send: function send(defaultConfig, _eventName, aditionalParams, sendEvent) {
            if (sendCondition) {
                return sendGTMEvent(defaultConfig, _eventName, aditionalParams, sendEvent);
            } else {
                return false;
            }
        }
    };
}

function isCard(type) {
    if (type === 'CC' || type === 'DEB') {
        return true;
    }

    return false;
}

var baseParams = function baseParams(defaultConfig) {
    var siteVersion = __WEBPACK_IMPORTED_MODULE_7__tvg_conf_classic___default()().product;
    var accountId = defaultConfig.userSession && defaultConfig.user ? defaultConfig.user.accountNumber : '';
    var residentState = __WEBPACK_IMPORTED_MODULE_6_lodash_get___default()(defaultConfig, 'user.homeAddress.StateAbbr') || __WEBPACK_IMPORTED_MODULE_6_lodash_get___default()(defaultConfig, 'user.homeAddress.state', '');
    var eventParams = {};

    eventParams.amountOption = undefined;
    eventParams.betAmount = undefined;
    eventParams.betName = undefined;
    eventParams.betType = undefined;
    eventParams.cableProvider = undefined;
    eventParams.cardType = undefined;
    eventParams.customerStatus = defaultConfig.hasInitialDeposit;
    eventParams.dedicatedTVGChannel = undefined;
    eventParams.depositAmount = undefined;
    eventParams.depositMethod = undefined;
    eventParams.depositType = undefined;
    eventParams.errorMessage = undefined;
    eventParams.errorType = undefined;
    eventParams.gaEventAction = undefined;
    eventParams.gaEventCategory = undefined;
    eventParams.gaEventLabel = undefined;
    eventParams.gaEventValue = undefined;
    eventParams.loginStatus = undefined;
    eventParams.netDepositFee = undefined;
    eventParams.paymentMethod = undefined;
    eventParams.promoCode = undefined;
    eventParams.raceName = undefined;
    eventParams.raceNumber = undefined;
    eventParams.raceStatus = undefined;
    eventParams.registrationStatus = undefined;
    eventParams.residenceState = undefined;
    eventParams.referrer = undefined;
    eventParams.runnerSelectionList = undefined;
    eventParams.screenName = undefined;
    eventParams.siteVersion = undefined;
    eventParams.videoName = undefined;
    eventParams.videoType = undefined;
    eventParams.withdrawAmount = undefined;
    eventParams.withdrawType = undefined;
    eventParams.trackName = undefined;
    eventParams.eventLabel = undefined;
    eventParams.url = undefined;
    eventParams.wagerAmount = undefined;
    eventParams.wagerName = undefined;
    eventParams.wagerType = undefined;
    eventParams.withdrawalAmount = undefined;
    eventParams.withdrawalType = undefined;
    eventParams.event = 'deposit';
    eventParams.accountId = accountId;
    eventParams.residenceState = residentState;
    eventParams.loginStatus = defaultConfig.userSession ? 'Logged In' : 'Logged Out';
    eventParams.registrationStatus = defaultConfig.userSession ? 'Registered' : 'Unregistered';
    eventParams.screenName = tvg4ScreenName();
    eventParams.sectionName = tvg4SectionName();
    eventParams.siteVersion = getSiteVersion(siteVersion), eventParams.productVersion = getProduct(siteVersion), eventParams.sport = undefined;
    return eventParams;
};

var sendGTMEvent = function sendGTMEvent(defaultConfig, _eventName, aditionalParams, sendEvent) {
    sendEvent = typeof sendEvent !== 'undefined' ? sendEvent : true;

    if (defaultConfig.enableGTM && sendEvent) {
        var finalParams = baseParams(defaultConfig);
        if ((typeof aditionalParams === 'undefined' ? 'undefined' : _typeof(aditionalParams)) === 'object') {
            finalParams = __WEBPACK_IMPORTED_MODULE_0_lodash_fp_extend___default()(finalParams, aditionalParams);
        }

        if (window.dataLayer) {
            window.dataLayer.push(finalParams);
        }
        return finalParams;
    } else {
        return '';
    }
};

var tvg4SectionNameByURLSharp = function tvg4SectionNameByURLSharp(name, params) {
    var parts = URLParse(name),
        section = parts.pathname.replace('/', '').replace('-', ''),
        hash = parts.hash.replace('#', ''),
        splitHash = hash.split('+'),
        translation = [section, 'translation'].join('.'),
        firstSection = __WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty___default()(splitHash[0]) ? '' : [section, splitHash[0]].join('.'),
        sectionName = __WEBPACK_IMPORTED_MODULE_6_lodash_get___default()(__WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a, translation),
        fullSectionName = void 0;

    if (splitHash.length > 1) {
        var secondSection = [section, splitHash[1]].join('.');
        fullSectionName = [sectionName, __WEBPACK_IMPORTED_MODULE_6_lodash_get___default()(__WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a, firstSection, ''), __WEBPACK_IMPORTED_MODULE_6_lodash_get___default()(__WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a, secondSection, '')].join(' | ');
    } else {
        fullSectionName = __WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty___default()(firstSection) ? sectionName : [sectionName, __WEBPACK_IMPORTED_MODULE_6_lodash_get___default()(__WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a, firstSection, '')].join(' | ');
    }

    return __WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty___default()(params) ? fullSectionName : fullSectionName.concat(' | ').concat(params.sectionName);
};

var URLParse = function URLParse(url) {
    var parser = document.createElement('a');
    parser.href = url;

    return {
        pathname: parser.pathname,
        hash: parser.hash
    };
};

var tvg4SectionNameByURLToken = function tvg4SectionNameByURLToken(key, name, params) {
    var sectionName = void 0;

    if (__WEBPACK_IMPORTED_MODULE_1_lodash_fp_isString___default()(name) && !__WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty___default()(name) && __WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a[key][name]) {
        sectionName = __WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a[key].translation + ' | ' + __WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a[key][name];
    } else {
        sectionName = __WEBPACK_IMPORTED_MODULE_5__constants_sectionNames___default.a[key].translation;
    }

    if (!__WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty___default()(params) && !__WEBPACK_IMPORTED_MODULE_3_lodash_fp_isEmpty___default()(params.sectionName)) {
        sectionName += ' | ' + params.sectionName;
    }

    return sectionName;
};

var getURLForRetroCompatibleGTM = function getURLForRetroCompatibleGTM() {
    var url = window.location.href;

    if (url.indexOf('my-funds/deposit') > -1) {
        return '/my-profile#funds+deposit';
    } else if (url.indexOf('my-funds/bank') > -1) {
        return '/my-profile#funds+bank';
    } else if (url.indexOf('my-funds/withdraw') > -1) {
        return '/my-profile#funds+withdraw';
    }

    return url;
};

// hack for gtm hardcode strings
var getSiteVersion = function getSiteVersion(product) {
    var siteVersionKeys = {
        'touch3': 'v2-revamp',
        'ios2': 'iOS',
        'fdrmobile': 'fdrmobileWeb',
        'fdrios': 'fdriOS',
        'iosnative': 'native',
        'androidnative': 'native',
        'androidwrapper': __WEBPACK_IMPORTED_MODULE_7__tvg_conf_classic___default()().brand === "fdr" ? "fdr-android-gps" : "tvg-android-gps"
    };
    return siteVersionKeys[product] ? siteVersionKeys[product] : product.toUpperCase();
};

var getProduct = function getProduct(product) {
    var productKeys = {
        'touch3': 'MEP-01',
        'ios2': 'iOS',
        'fdrmobile': 'FDR-01',
        'fdrios': 'FDR-01'
    };
    return productKeys[product] ? productKeys[product] : product.toUpperCase();
};

var tvg4SectionName = function tvg4SectionName(params) {
    var url = getURLForRetroCompatibleGTM().split('/');
    var urlToken = url[1].indexOf('?') > -1 ? url[1].split('?')[0] : url[1];

    if (urlToken.indexOf('#') > -1) {
        return tvg4SectionNameByURLSharp(urlToken, params);
    } else {
        switch (urlToken) {
            case 'my-funds':
                return tvg4SectionNameByURLToken('my-profile', 'funds', params);
            default:
                return '';
        }
    }
};

var tvg4ScreenName = function tvg4ScreenName() {
    var path = window.location.pathname + window.location.search,
        url = path.split('/'),
        urlToken = url[1],
        screenName = __WEBPACK_IMPORTED_MODULE_4__constants_screenNames___default.a[urlToken];

    if (__WEBPACK_IMPORTED_MODULE_2_lodash_fp_isUndefined___default()(screenName)) {
        return '';
    }

    return screenName;
};

/***/ }),
/* 11 */
/***/ (function(module, exports, __webpack_require__) {

var root = __webpack_require__(1);

/** Built-in value references. */
var _Symbol = root.Symbol;

module.exports = _Symbol;

/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {

var assignValue = __webpack_require__(71),
    baseAssignValue = __webpack_require__(45);

/**
 * Copies properties of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy properties from.
 * @param {Array} props The property identifiers to copy.
 * @param {Object} [object={}] The object to copy properties to.
 * @param {Function} [customizer] The function to customize copied values.
 * @returns {Object} Returns `object`.
 */
function copyObject(source, props, object, customizer) {
  var isNew = !object;
  object || (object = {});

  var index = -1,
      length = props.length;

  while (++index < length) {
    var key = props[index];

    var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined;

    if (newValue === undefined) {
      newValue = source[key];
    }
    if (isNew) {
      baseAssignValue(object, key, newValue);
    } else {
      assignValue(object, key, newValue);
    }
  }
  return object;
}

module.exports = copyObject;

/***/ }),
/* 13 */
/***/ (function(module, exports, __webpack_require__) {

var DataView = __webpack_require__(139),
    Map = __webpack_require__(40),
    Promise = __webpack_require__(141),
    Set = __webpack_require__(142),
    WeakMap = __webpack_require__(67),
    baseGetTag = __webpack_require__(5),
    toSource = __webpack_require__(103);

/** `Object#toString` result references. */
var mapTag = '[object Map]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    setTag = '[object Set]',
    weakMapTag = '[object WeakMap]';

var dataViewTag = '[object DataView]';

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
    mapCtorString = toSource(Map),
    promiseCtorString = toSource(Promise),
    setCtorString = toSource(Set),
    weakMapCtorString = toSource(WeakMap);

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = baseGetTag;

// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map && getTag(new Map()) != mapTag || Promise && getTag(Promise.resolve()) != promiseTag || Set && getTag(new Set()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
    getTag = function getTag(value) {
        var result = baseGetTag(value),
            Ctor = result == objectTag ? value.constructor : undefined,
            ctorString = Ctor ? toSource(Ctor) : '';

        if (ctorString) {
            switch (ctorString) {
                case dataViewCtorString:
                    return dataViewTag;
                case mapCtorString:
                    return mapTag;
                case promiseCtorString:
                    return promiseTag;
                case setCtorString:
                    return setTag;
                case weakMapCtorString:
                    return weakMapTag;
            }
        }
        return result;
    };
}

module.exports = getTag;

/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {

var baseConvert = __webpack_require__(244),
    util = __webpack_require__(246);

/**
 * Converts `func` of `name` to an immutable auto-curried iteratee-first data-last
 * version with conversion `options` applied. If `name` is an object its methods
 * will be converted.
 *
 * @param {string} name The name of the function to wrap.
 * @param {Function} [func] The function to wrap.
 * @param {Object} [options] The options object. See `baseConvert` for more details.
 * @returns {Function|Object} Returns the converted function or object.
 */
function convert(name, func, options) {
  return baseConvert(util, name, func, options);
}

module.exports = convert;

/***/ }),
/* 15 */
/***/ (function(module, exports) {

/**
 * Copies the values of `source` to `array`.
 *
 * @private
 * @param {Array} source The array to copy values from.
 * @param {Array} [array=[]] The array to copy values to.
 * @returns {Array} Returns `array`.
 */
function copyArray(source, array) {
  var index = -1,
      length = source.length;

  array || (array = Array(length));
  while (++index < length) {
    array[index] = source[index];
  }
  return array;
}

module.exports = copyArray;

/***/ }),
/* 16 */
/***/ (function(module, exports, __webpack_require__) {

var isSymbol = __webpack_require__(21);

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/**
 * Converts `value` to a string key if it's not a string or symbol.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {string|symbol} Returns the key.
 */
function toKey(value) {
  if (typeof value == 'string' || isSymbol(value)) {
    return value;
  }
  var result = value + '';
  return result == '0' && 1 / value == -INFINITY ? '-0' : result;
}

module.exports = toKey;

/***/ }),
/* 17 */
/***/ (function(module, exports) {

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || value !== value && other !== other;
}

module.exports = eq;

/***/ }),
/* 18 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsArguments = __webpack_require__(153),
    isObjectLike = __webpack_require__(2);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Built-in value references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
var isArguments = baseIsArguments(function () {
    return arguments;
}()) ? baseIsArguments : function (value) {
    return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
};

module.exports = isArguments;

/***/ }),
/* 19 */
/***/ (function(module, exports, __webpack_require__) {

var isFunction = __webpack_require__(34),
    isLength = __webpack_require__(58);

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

module.exports = isArrayLike;

/***/ }),
/* 20 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(module) {var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var root = __webpack_require__(1),
    stubFalse = __webpack_require__(268);

/** Detect free variable `exports`. */
var freeExports = ( false ? 'undefined' : _typeof(exports)) == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && ( false ? 'undefined' : _typeof(module)) == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Built-in value references. */
var Buffer = moduleExports ? root.Buffer : undefined;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;

/**
 * Checks if `value` is a buffer.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
 * @example
 *
 * _.isBuffer(new Buffer(2));
 * // => true
 *
 * _.isBuffer(new Uint8Array(2));
 * // => false
 */
var isBuffer = nativeIsBuffer || stubFalse;

module.exports = isBuffer;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(37)(module)))

/***/ }),
/* 21 */
/***/ (function(module, exports, __webpack_require__) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var baseGetTag = __webpack_require__(5),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
    return (typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
}

module.exports = isSymbol;

/***/ }),
/* 22 */
/***/ (function(module, exports, __webpack_require__) {

var arrayLikeKeys = __webpack_require__(68),
    baseKeysIn = __webpack_require__(162),
    isArrayLike = __webpack_require__(19);

/**
 * Creates an array of the own and inherited enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keysIn(new Foo);
 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
 */
function keysIn(object) {
  return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
}

module.exports = keysIn;

/***/ }),
/* 23 */
/***/ (function(module, exports, __webpack_require__) {

var listCacheClear = __webpack_require__(208),
    listCacheDelete = __webpack_require__(209),
    listCacheGet = __webpack_require__(210),
    listCacheHas = __webpack_require__(211),
    listCacheSet = __webpack_require__(212);

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;

    this.clear();
    while (++index < length) {
        var entry = entries[index];
        this.set(entry[0], entry[1]);
    }
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

module.exports = ListCache;

/***/ }),
/* 24 */
/***/ (function(module, exports, __webpack_require__) {

var ListCache = __webpack_require__(23),
    stackClear = __webpack_require__(229),
    stackDelete = __webpack_require__(230),
    stackGet = __webpack_require__(231),
    stackHas = __webpack_require__(232),
    stackSet = __webpack_require__(233);

/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  var data = this.__data__ = new ListCache(entries);
  this.size = data.size;
}

// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;

module.exports = Stack;

/***/ }),
/* 25 */
/***/ (function(module, exports, __webpack_require__) {

var eq = __webpack_require__(17);

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

module.exports = assocIndexOf;

/***/ }),
/* 26 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(4);

/** Built-in value references. */
var objectCreate = Object.create;

/**
 * The base implementation of `_.create` without support for assigning
 * properties to the created object.
 *
 * @private
 * @param {Object} proto The object to inherit from.
 * @returns {Object} Returns the new object.
 */
var baseCreate = function () {
  function object() {}
  return function (proto) {
    if (!isObject(proto)) {
      return {};
    }
    if (objectCreate) {
      return objectCreate(proto);
    }
    object.prototype = proto;
    var result = new object();
    object.prototype = undefined;
    return result;
  };
}();

module.exports = baseCreate;

/***/ }),
/* 27 */
/***/ (function(module, exports, __webpack_require__) {

var baseCreate = __webpack_require__(26),
    isObject = __webpack_require__(4);

/**
 * Creates a function that produces an instance of `Ctor` regardless of
 * whether it was invoked as part of a `new` expression or by `call` or `apply`.
 *
 * @private
 * @param {Function} Ctor The constructor to wrap.
 * @returns {Function} Returns the new wrapped function.
 */
function createCtor(Ctor) {
  return function () {
    // Use a `switch` statement to work with class constructors. See
    // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
    // for more details.
    var args = arguments;
    switch (args.length) {
      case 0:
        return new Ctor();
      case 1:
        return new Ctor(args[0]);
      case 2:
        return new Ctor(args[0], args[1]);
      case 3:
        return new Ctor(args[0], args[1], args[2]);
      case 4:
        return new Ctor(args[0], args[1], args[2], args[3]);
      case 5:
        return new Ctor(args[0], args[1], args[2], args[3], args[4]);
      case 6:
        return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
      case 7:
        return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
    }
    var thisBinding = baseCreate(Ctor.prototype),
        result = Ctor.apply(thisBinding, args);

    // Mimic the constructor's `return` behavior.
    // See https://es5.github.io/#x13.2.2 for more details.
    return isObject(result) ? result : thisBinding;
  };
}

module.exports = createCtor;

/***/ }),
/* 28 */
/***/ (function(module, exports, __webpack_require__) {

var isKeyable = __webpack_require__(205);

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key) ? data[typeof key == 'string' ? 'string' : 'hash'] : data.map;
}

module.exports = getMapData;

/***/ }),
/* 29 */
/***/ (function(module, exports) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
  length = length == null ? MAX_SAFE_INTEGER : length;

  return !!length && (type == 'number' || type != 'symbol' && reIsUint.test(value)) && value > -1 && value % 1 == 0 && value < length;
}

module.exports = isIndex;

/***/ }),
/* 30 */
/***/ (function(module, exports) {

/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = typeof Ctor == 'function' && Ctor.prototype || objectProto;

  return value === proto;
}

module.exports = isPrototype;

/***/ }),
/* 31 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(6);

/* Built-in method references that are verified to be native. */
var nativeCreate = getNative(Object, 'create');

module.exports = nativeCreate;

/***/ }),
/* 32 */
/***/ (function(module, exports) {

module.exports = {
  'cap': false,
  'curry': false,
  'fixed': false,
  'immutable': false,
  'rearg': false
};

/***/ }),
/* 33 */
/***/ (function(module, exports) {

/**
 * This method returns the first argument it receives.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Util
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'a': 1 };
 *
 * console.log(_.identity(object) === object);
 * // => true
 */
function identity(value) {
  return value;
}

module.exports = identity;

/***/ }),
/* 34 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetTag = __webpack_require__(5),
    isObject = __webpack_require__(4);

/** `Object#toString` result references. */
var asyncTag = '[object AsyncFunction]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    proxyTag = '[object Proxy]';

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
    if (!isObject(value)) {
        return false;
    }
    // The use of `Object#toString` avoids issues with the `typeof` operator
    // in Safari 9 which returns 'object' for typed arrays and other constructors.
    var tag = baseGetTag(value);
    return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}

module.exports = isFunction;

/***/ }),
/* 35 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsTypedArray = __webpack_require__(160),
    baseUnary = __webpack_require__(49),
    nodeUtil = __webpack_require__(55);

/* Node.js helper references. */
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

module.exports = isTypedArray;

/***/ }),
/* 36 */
/***/ (function(module, exports, __webpack_require__) {

var arrayLikeKeys = __webpack_require__(68),
    baseKeys = __webpack_require__(47),
    isArrayLike = __webpack_require__(19);

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

module.exports = keys;

/***/ }),
/* 37 */
/***/ (function(module, exports) {

module.exports = function (module) {
	if (!module.webpackPolyfill) {
		module.deprecate = function () {};
		module.paths = [];
		// module.parent = undefined by default
		if (!module.children) module.children = [];
		Object.defineProperty(module, "loaded", {
			enumerable: true,
			get: function get() {
				return module.l;
			}
		});
		Object.defineProperty(module, "id", {
			enumerable: true,
			get: function get() {
				return module.i;
			}
		});
		module.webpackPolyfill = 1;
	}
	return module;
};

/***/ }),
/* 38 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(process) {

var utils = __webpack_require__(3);
var normalizeHeaderName = __webpack_require__(134);

var DEFAULT_CONTENT_TYPE = {
  'Content-Type': 'application/x-www-form-urlencoded'
};

function setContentTypeIfUnset(headers, value) {
  if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
    headers['Content-Type'] = value;
  }
}

function getDefaultAdapter() {
  var adapter;
  if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = __webpack_require__(60);
  } else if (typeof process !== 'undefined') {
    // For node use HTTP adapter
    adapter = __webpack_require__(60);
  }
  return adapter;
}

var defaults = {
  adapter: getDefaultAdapter(),

  transformRequest: [function transformRequest(data, headers) {
    normalizeHeaderName(headers, 'Content-Type');
    if (utils.isFormData(data) || utils.isArrayBuffer(data) || utils.isBuffer(data) || utils.isStream(data) || utils.isFile(data) || utils.isBlob(data)) {
      return data;
    }
    if (utils.isArrayBufferView(data)) {
      return data.buffer;
    }
    if (utils.isURLSearchParams(data)) {
      setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
      return data.toString();
    }
    if (utils.isObject(data)) {
      setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
      return JSON.stringify(data);
    }
    return data;
  }],

  transformResponse: [function transformResponse(data) {
    /*eslint no-param-reassign:0*/
    if (typeof data === 'string') {
      try {
        data = JSON.parse(data);
      } catch (e) {/* Ignore */}
    }
    return data;
  }],

  timeout: 0,

  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',

  maxContentLength: -1,

  validateStatus: function validateStatus(status) {
    return status >= 200 && status < 300;
  }
};

defaults.headers = {
  common: {
    'Accept': 'application/json, text/plain, */*'
  }
};

utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
  defaults.headers[method] = {};
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
});

module.exports = defaults;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(108)))

/***/ }),
/* 39 */
/***/ (function(module, exports, __webpack_require__) {

var baseCreate = __webpack_require__(26),
    baseLodash = __webpack_require__(48);

/** Used as references for the maximum length and index of an array. */
var MAX_ARRAY_LENGTH = 4294967295;

/**
 * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
 *
 * @private
 * @constructor
 * @param {*} value The value to wrap.
 */
function LazyWrapper(value) {
  this.__wrapped__ = value;
  this.__actions__ = [];
  this.__dir__ = 1;
  this.__filtered__ = false;
  this.__iteratees__ = [];
  this.__takeCount__ = MAX_ARRAY_LENGTH;
  this.__views__ = [];
}

// Ensure `LazyWrapper` is an instance of `baseLodash`.
LazyWrapper.prototype = baseCreate(baseLodash.prototype);
LazyWrapper.prototype.constructor = LazyWrapper;

module.exports = LazyWrapper;

/***/ }),
/* 40 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(6),
    root = __webpack_require__(1);

/* Built-in method references that are verified to be native. */
var Map = getNative(root, 'Map');

module.exports = Map;

/***/ }),
/* 41 */
/***/ (function(module, exports, __webpack_require__) {

var mapCacheClear = __webpack_require__(213),
    mapCacheDelete = __webpack_require__(214),
    mapCacheGet = __webpack_require__(215),
    mapCacheHas = __webpack_require__(216),
    mapCacheSet = __webpack_require__(217);

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;

    this.clear();
    while (++index < length) {
        var entry = entries[index];
        this.set(entry[0], entry[1]);
    }
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

module.exports = MapCache;

/***/ }),
/* 42 */
/***/ (function(module, exports) {

/**
 * A faster alternative to `Function#apply`, this function invokes `func`
 * with the `this` binding of `thisArg` and the arguments of `args`.
 *
 * @private
 * @param {Function} func The function to invoke.
 * @param {*} thisArg The `this` binding of `func`.
 * @param {Array} args The arguments to invoke `func` with.
 * @returns {*} Returns the result of `func`.
 */
function apply(func, thisArg, args) {
  switch (args.length) {
    case 0:
      return func.call(thisArg);
    case 1:
      return func.call(thisArg, args[0]);
    case 2:
      return func.call(thisArg, args[0], args[1]);
    case 3:
      return func.call(thisArg, args[0], args[1], args[2]);
  }
  return func.apply(thisArg, args);
}

module.exports = apply;

/***/ }),
/* 43 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.forEach` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns `array`.
 */
function arrayEach(array, iteratee) {
  var index = -1,
      length = array == null ? 0 : array.length;

  while (++index < length) {
    if (iteratee(array[index], index, array) === false) {
      break;
    }
  }
  return array;
}

module.exports = arrayEach;

/***/ }),
/* 44 */
/***/ (function(module, exports) {

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

module.exports = arrayPush;

/***/ }),
/* 45 */
/***/ (function(module, exports, __webpack_require__) {

var defineProperty = __webpack_require__(85);

/**
 * The base implementation of `assignValue` and `assignMergeValue` without
 * value checks.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function baseAssignValue(object, key, value) {
  if (key == '__proto__' && defineProperty) {
    defineProperty(object, key, {
      'configurable': true,
      'enumerable': true,
      'value': value,
      'writable': true
    });
  } else {
    object[key] = value;
  }
}

module.exports = baseAssignValue;

/***/ }),
/* 46 */
/***/ (function(module, exports, __webpack_require__) {

var Stack = __webpack_require__(24),
    arrayEach = __webpack_require__(43),
    assignValue = __webpack_require__(71),
    baseAssign = __webpack_require__(72),
    baseAssignIn = __webpack_require__(147),
    cloneBuffer = __webpack_require__(78),
    copyArray = __webpack_require__(15),
    copySymbols = __webpack_require__(177),
    copySymbolsIn = __webpack_require__(178),
    getAllKeys = __webpack_require__(88),
    getAllKeysIn = __webpack_require__(188),
    getTag = __webpack_require__(13),
    initCloneArray = __webpack_require__(200),
    initCloneByTag = __webpack_require__(201),
    initCloneObject = __webpack_require__(92),
    isArray = __webpack_require__(0),
    isBuffer = __webpack_require__(20),
    isMap = __webpack_require__(257),
    isObject = __webpack_require__(4),
    isSet = __webpack_require__(258),
    keys = __webpack_require__(36);

/** Used to compose bitmasks for cloning. */
var CLONE_DEEP_FLAG = 1,
    CLONE_FLAT_FLAG = 2,
    CLONE_SYMBOLS_FLAG = 4;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    objectTag = '[object Object]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/** Used to identify `toStringTag` values supported by `_.clone`. */
var cloneableTags = {};
cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;

/**
 * The base implementation of `_.clone` and `_.cloneDeep` which tracks
 * traversed objects.
 *
 * @private
 * @param {*} value The value to clone.
 * @param {boolean} bitmask The bitmask flags.
 *  1 - Deep clone
 *  2 - Flatten inherited properties
 *  4 - Clone symbols
 * @param {Function} [customizer] The function to customize cloning.
 * @param {string} [key] The key of `value`.
 * @param {Object} [object] The parent object of `value`.
 * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
 * @returns {*} Returns the cloned value.
 */
function baseClone(value, bitmask, customizer, key, object, stack) {
  var result,
      isDeep = bitmask & CLONE_DEEP_FLAG,
      isFlat = bitmask & CLONE_FLAT_FLAG,
      isFull = bitmask & CLONE_SYMBOLS_FLAG;

  if (customizer) {
    result = object ? customizer(value, key, object, stack) : customizer(value);
  }
  if (result !== undefined) {
    return result;
  }
  if (!isObject(value)) {
    return value;
  }
  var isArr = isArray(value);
  if (isArr) {
    result = initCloneArray(value);
    if (!isDeep) {
      return copyArray(value, result);
    }
  } else {
    var tag = getTag(value),
        isFunc = tag == funcTag || tag == genTag;

    if (isBuffer(value)) {
      return cloneBuffer(value, isDeep);
    }
    if (tag == objectTag || tag == argsTag || isFunc && !object) {
      result = isFlat || isFunc ? {} : initCloneObject(value);
      if (!isDeep) {
        return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value));
      }
    } else {
      if (!cloneableTags[tag]) {
        return object ? value : {};
      }
      result = initCloneByTag(value, tag, isDeep);
    }
  }
  // Check for circular references and return its corresponding clone.
  stack || (stack = new Stack());
  var stacked = stack.get(value);
  if (stacked) {
    return stacked;
  }
  stack.set(value, result);

  if (isSet(value)) {
    value.forEach(function (subValue) {
      result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
    });

    return result;
  }

  if (isMap(value)) {
    value.forEach(function (subValue, key) {
      result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
    });

    return result;
  }

  var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;

  var props = isArr ? undefined : keysFunc(value);
  arrayEach(props || value, function (subValue, key) {
    if (props) {
      key = subValue;
      subValue = value[key];
    }
    // Recursively populate clone (susceptible to call stack limits).
    assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
  });
  return result;
}

module.exports = baseClone;

/***/ }),
/* 47 */
/***/ (function(module, exports, __webpack_require__) {

var isPrototype = __webpack_require__(30),
    nativeKeys = __webpack_require__(221);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

module.exports = baseKeys;

/***/ }),
/* 48 */
/***/ (function(module, exports) {

/**
 * The function whose prototype chain sequence wrappers inherit from.
 *
 * @private
 */
function baseLodash() {
  // No operation performed.
}

module.exports = baseLodash;

/***/ }),
/* 49 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.unary` without support for storing metadata.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @returns {Function} Returns the new capped function.
 */
function baseUnary(func) {
  return function (value) {
    return func(value);
  };
}

module.exports = baseUnary;

/***/ }),
/* 50 */
/***/ (function(module, exports, __webpack_require__) {

var Uint8Array = __webpack_require__(66);

/**
 * Creates a clone of `arrayBuffer`.
 *
 * @private
 * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
 * @returns {ArrayBuffer} Returns the cloned array buffer.
 */
function cloneArrayBuffer(arrayBuffer) {
  var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
  new Uint8Array(result).set(new Uint8Array(arrayBuffer));
  return result;
}

module.exports = cloneArrayBuffer;

/***/ }),
/* 51 */
/***/ (function(module, exports, __webpack_require__) {

var baseSetData = __webpack_require__(76),
    createBind = __webpack_require__(182),
    createCurry = __webpack_require__(183),
    createHybrid = __webpack_require__(83),
    createPartial = __webpack_require__(184),
    getData = __webpack_require__(89),
    mergeData = __webpack_require__(220),
    setData = __webpack_require__(99),
    setWrapToString = __webpack_require__(100),
    toInteger = __webpack_require__(106);

/** Error message constants. */
var FUNC_ERROR_TEXT = 'Expected a function';

/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1,
    WRAP_BIND_KEY_FLAG = 2,
    WRAP_CURRY_FLAG = 8,
    WRAP_CURRY_RIGHT_FLAG = 16,
    WRAP_PARTIAL_FLAG = 32,
    WRAP_PARTIAL_RIGHT_FLAG = 64;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * Creates a function that either curries or invokes `func` with optional
 * `this` binding and partially applied arguments.
 *
 * @private
 * @param {Function|string} func The function or method name to wrap.
 * @param {number} bitmask The bitmask flags.
 *    1 - `_.bind`
 *    2 - `_.bindKey`
 *    4 - `_.curry` or `_.curryRight` of a bound function
 *    8 - `_.curry`
 *   16 - `_.curryRight`
 *   32 - `_.partial`
 *   64 - `_.partialRight`
 *  128 - `_.rearg`
 *  256 - `_.ary`
 *  512 - `_.flip`
 * @param {*} [thisArg] The `this` binding of `func`.
 * @param {Array} [partials] The arguments to be partially applied.
 * @param {Array} [holders] The `partials` placeholder indexes.
 * @param {Array} [argPos] The argument positions of the new function.
 * @param {number} [ary] The arity cap of `func`.
 * @param {number} [arity] The arity of `func`.
 * @returns {Function} Returns the new wrapped function.
 */
function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
  var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
  if (!isBindKey && typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  var length = partials ? partials.length : 0;
  if (!length) {
    bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
    partials = holders = undefined;
  }
  ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
  arity = arity === undefined ? arity : toInteger(arity);
  length -= holders ? holders.length : 0;

  if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
    var partialsRight = partials,
        holdersRight = holders;

    partials = holders = undefined;
  }
  var data = isBindKey ? undefined : getData(func);

  var newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];

  if (data) {
    mergeData(newData, data);
  }
  func = newData[0];
  bitmask = newData[1];
  thisArg = newData[2];
  partials = newData[3];
  holders = newData[4];
  arity = newData[9] = newData[9] === undefined ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0);

  if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
    bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
  }
  if (!bitmask || bitmask == WRAP_BIND_FLAG) {
    var result = createBind(func, bitmask, thisArg);
  } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
    result = createCurry(func, bitmask, arity);
  } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
    result = createPartial(func, bitmask, thisArg, partials);
  } else {
    result = createHybrid.apply(undefined, newData);
  }
  var setter = data ? baseSetData : setData;
  return setWrapToString(setter(result, newData), func, bitmask);
}

module.exports = createWrap;

/***/ }),
/* 52 */
/***/ (function(module, exports, __webpack_require__) {

var overArg = __webpack_require__(96);

/** Built-in value references. */
var getPrototype = overArg(Object.getPrototypeOf, Object);

module.exports = getPrototype;

/***/ }),
/* 53 */
/***/ (function(module, exports, __webpack_require__) {

var arrayFilter = __webpack_require__(144),
    stubArray = __webpack_require__(105);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Built-in value references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols;

/**
 * Creates an array of the own enumerable symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of symbols.
 */
var getSymbols = !nativeGetSymbols ? stubArray : function (object) {
  if (object == null) {
    return [];
  }
  object = Object(object);
  return arrayFilter(nativeGetSymbols(object), function (symbol) {
    return propertyIsEnumerable.call(object, symbol);
  });
};

module.exports = getSymbols;

/***/ }),
/* 54 */
/***/ (function(module, exports, __webpack_require__) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var isArray = __webpack_require__(0),
    isSymbol = __webpack_require__(21);

/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
    reIsPlainProp = /^\w*$/;

/**
 * Checks if `value` is a property name and not a property path.
 *
 * @private
 * @param {*} value The value to check.
 * @param {Object} [object] The object to query keys on.
 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 */
function isKey(value, object) {
  if (isArray(value)) {
    return false;
  }
  var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
  if (type == 'number' || type == 'symbol' || type == 'boolean' || value == null || isSymbol(value)) {
    return true;
  }
  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
}

module.exports = isKey;

/***/ }),
/* 55 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(module) {var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var freeGlobal = __webpack_require__(87);

/** Detect free variable `exports`. */
var freeExports = ( false ? 'undefined' : _typeof(exports)) == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && ( false ? 'undefined' : _typeof(module)) == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && freeGlobal.process;

/** Used to access faster Node.js helpers. */
var nodeUtil = function () {
  try {
    // Use `util.types` for Node.js 10+.
    var types = freeModule && freeModule.require && freeModule.require('util').types;

    if (types) {
      return types;
    }

    // Legacy `process.binding('util')` for Node.js < 10.
    return freeProcess && freeProcess.binding && freeProcess.binding('util');
  } catch (e) {}
}();

module.exports = nodeUtil;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(37)(module)))

/***/ }),
/* 56 */
/***/ (function(module, exports) {

/** Used as the internal argument placeholder. */
var PLACEHOLDER = '__lodash_placeholder__';

/**
 * Replaces all `placeholder` elements in `array` with an internal placeholder
 * and returns an array of their indexes.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {*} placeholder The placeholder to replace.
 * @returns {Array} Returns the new array of placeholder indexes.
 */
function replaceHolders(array, placeholder) {
  var index = -1,
      length = array.length,
      resIndex = 0,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (value === placeholder || value === PLACEHOLDER) {
      array[index] = PLACEHOLDER;
      result[resIndex++] = index;
    }
  }
  return result;
}

module.exports = replaceHolders;

/***/ }),
/* 57 */
/***/ (function(module, exports, __webpack_require__) {

var baseSetToString = __webpack_require__(170),
    shortOut = __webpack_require__(101);

/**
 * Sets the `toString` method of `func` to return `string`.
 *
 * @private
 * @param {Function} func The function to modify.
 * @param {Function} string The `toString` result.
 * @returns {Function} Returns `func`.
 */
var setToString = shortOut(baseSetToString);

module.exports = setToString;

/***/ }),
/* 58 */
/***/ (function(module, exports) {

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

module.exports = isLength;

/***/ }),
/* 59 */
/***/ (function(module, exports, __webpack_require__) {

module.exports = __webpack_require__(120);

/***/ }),
/* 60 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(process) {

var utils = __webpack_require__(3);
var settle = __webpack_require__(126);
var buildURL = __webpack_require__(129);
var parseHeaders = __webpack_require__(135);
var isURLSameOrigin = __webpack_require__(133);
var createError = __webpack_require__(63);
var btoa = typeof window !== 'undefined' && window.btoa && window.btoa.bind(window) || __webpack_require__(128);

module.exports = function xhrAdapter(config) {
  return new Promise(function dispatchXhrRequest(resolve, reject) {
    var requestData = config.data;
    var requestHeaders = config.headers;

    if (utils.isFormData(requestData)) {
      delete requestHeaders['Content-Type']; // Let the browser set it
    }

    var request = new XMLHttpRequest();
    var loadEvent = 'onreadystatechange';
    var xDomain = false;

    // For IE 8/9 CORS support
    // Only supports POST and GET calls and doesn't returns the response headers.
    // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest.
    if (process.env.NODE_ENV !== 'test' && typeof window !== 'undefined' && window.XDomainRequest && !('withCredentials' in request) && !isURLSameOrigin(config.url)) {
      request = new window.XDomainRequest();
      loadEvent = 'onload';
      xDomain = true;
      request.onprogress = function handleProgress() {};
      request.ontimeout = function handleTimeout() {};
    }

    // HTTP basic authentication
    if (config.auth) {
      var username = config.auth.username || '';
      var password = config.auth.password || '';
      requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
    }

    request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true);

    // Set the request timeout in MS
    request.timeout = config.timeout;

    // Listen for ready state
    request[loadEvent] = function handleLoad() {
      if (!request || request.readyState !== 4 && !xDomain) {
        return;
      }

      // The request errored out and we didn't get a response, this will be
      // handled by onerror instead
      // With one exception: request that using file: protocol, most browsers
      // will return status as 0 even though it's a successful request
      if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
        return;
      }

      // Prepare the response
      var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
      var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;
      var response = {
        data: responseData,
        // IE sends 1223 instead of 204 (https://github.com/mzabriskie/axios/issues/201)
        status: request.status === 1223 ? 204 : request.status,
        statusText: request.status === 1223 ? 'No Content' : request.statusText,
        headers: responseHeaders,
        config: config,
        request: request
      };

      settle(resolve, reject, response);

      // Clean up request
      request = null;
    };

    // Handle low level network errors
    request.onerror = function handleError() {
      // Real errors are hidden from us by the browser
      // onerror should only fire if it's a network error
      reject(createError('Network Error', config, null, request));

      // Clean up request
      request = null;
    };

    // Handle timeout
    request.ontimeout = function handleTimeout() {
      reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', request));

      // Clean up request
      request = null;
    };

    // Add xsrf header
    // This is only done if running in a standard browser environment.
    // Specifically not if we're in a web worker, or react-native.
    if (utils.isStandardBrowserEnv()) {
      var cookies = __webpack_require__(131);

      // Add xsrf header
      var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ? cookies.read(config.xsrfCookieName) : undefined;

      if (xsrfValue) {
        requestHeaders[config.xsrfHeaderName] = xsrfValue;
      }
    }

    // Add headers to the request
    if ('setRequestHeader' in request) {
      utils.forEach(requestHeaders, function setRequestHeader(val, key) {
        if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
          // Remove Content-Type if data is undefined
          delete requestHeaders[key];
        } else {
          // Otherwise add header to the request
          request.setRequestHeader(key, val);
        }
      });
    }

    // Add withCredentials to request if needed
    if (config.withCredentials) {
      request.withCredentials = true;
    }

    // Add responseType to request if needed
    if (config.responseType) {
      try {
        request.responseType = config.responseType;
      } catch (e) {
        // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
        // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
        if (config.responseType !== 'json') {
          throw e;
        }
      }
    }

    // Handle progress if needed
    if (typeof config.onDownloadProgress === 'function') {
      request.addEventListener('progress', config.onDownloadProgress);
    }

    // Not all browsers support upload events
    if (typeof config.onUploadProgress === 'function' && request.upload) {
      request.upload.addEventListener('progress', config.onUploadProgress);
    }

    if (config.cancelToken) {
      // Handle cancellation
      config.cancelToken.promise.then(function onCanceled(cancel) {
        if (!request) {
          return;
        }

        request.abort();
        reject(cancel);
        // Clean up request
        request = null;
      });
    }

    if (requestData === undefined) {
      requestData = null;
    }

    // Send the request
    request.send(requestData);
  });
};
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(108)))

/***/ }),
/* 61 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * A `Cancel` is an object that is thrown when an operation is canceled.
 *
 * @class
 * @param {string=} message The message.
 */

function Cancel(message) {
  this.message = message;
}

Cancel.prototype.toString = function toString() {
  return 'Cancel' + (this.message ? ': ' + this.message : '');
};

Cancel.prototype.__CANCEL__ = true;

module.exports = Cancel;

/***/ }),
/* 62 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


module.exports = function isCancel(value) {
  return !!(value && value.__CANCEL__);
};

/***/ }),
/* 63 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var enhanceError = __webpack_require__(125);

/**
 * Create an Error with the specified message, config, error code, request and response.
 *
 * @param {string} message The error message.
 * @param {Object} config The config.
 * @param {string} [code] The error code (for example, 'ECONNABORTED').
 * @param {Object} [request] The request.
 * @param {Object} [response] The response.
 * @returns {Error} The created error.
 */
module.exports = function createError(message, config, code, request, response) {
  var error = new Error(message);
  return enhanceError(error, config, code, request, response);
};

/***/ }),
/* 64 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


module.exports = function bind(fn, thisArg) {
  return function wrap() {
    var args = new Array(arguments.length);
    for (var i = 0; i < args.length; i++) {
      args[i] = arguments[i];
    }
    return fn.apply(thisArg, args);
  };
};

/***/ }),
/* 65 */
/***/ (function(module, exports, __webpack_require__) {

var baseCreate = __webpack_require__(26),
    baseLodash = __webpack_require__(48);

/**
 * The base constructor for creating `lodash` wrapper objects.
 *
 * @private
 * @param {*} value The value to wrap.
 * @param {boolean} [chainAll] Enable explicit method chain sequences.
 */
function LodashWrapper(value, chainAll) {
  this.__wrapped__ = value;
  this.__actions__ = [];
  this.__chain__ = !!chainAll;
  this.__index__ = 0;
  this.__values__ = undefined;
}

LodashWrapper.prototype = baseCreate(baseLodash.prototype);
LodashWrapper.prototype.constructor = LodashWrapper;

module.exports = LodashWrapper;

/***/ }),
/* 66 */
/***/ (function(module, exports, __webpack_require__) {

var root = __webpack_require__(1);

/** Built-in value references. */
var Uint8Array = root.Uint8Array;

module.exports = Uint8Array;

/***/ }),
/* 67 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(6),
    root = __webpack_require__(1);

/* Built-in method references that are verified to be native. */
var WeakMap = getNative(root, 'WeakMap');

module.exports = WeakMap;

/***/ }),
/* 68 */
/***/ (function(module, exports, __webpack_require__) {

var baseTimes = __webpack_require__(171),
    isArguments = __webpack_require__(18),
    isArray = __webpack_require__(0),
    isBuffer = __webpack_require__(20),
    isIndex = __webpack_require__(29),
    isTypedArray = __webpack_require__(35);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  var isArr = isArray(value),
      isArg = !isArr && isArguments(value),
      isBuff = !isArr && !isArg && isBuffer(value),
      isType = !isArr && !isArg && !isBuff && isTypedArray(value),
      skipIndexes = isArr || isArg || isBuff || isType,
      result = skipIndexes ? baseTimes(value.length, String) : [],
      length = result.length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (
    // Safari 9 has enumerable `arguments.length` in strict mode.
    key == 'length' ||
    // Node.js 0.10 has enumerable non-index properties on buffers.
    isBuff && (key == 'offset' || key == 'parent') ||
    // PhantomJS 2 has enumerable non-index properties on typed arrays.
    isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset') ||
    // Skip index properties.
    isIndex(key, length)))) {
      result.push(key);
    }
  }
  return result;
}

module.exports = arrayLikeKeys;

/***/ }),
/* 69 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.map` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the new mapped array.
 */
function arrayMap(array, iteratee) {
  var index = -1,
      length = array == null ? 0 : array.length,
      result = Array(length);

  while (++index < length) {
    result[index] = iteratee(array[index], index, array);
  }
  return result;
}

module.exports = arrayMap;

/***/ }),
/* 70 */
/***/ (function(module, exports, __webpack_require__) {

var baseAssignValue = __webpack_require__(45),
    eq = __webpack_require__(17);

/**
 * This function is like `assignValue` except that it doesn't assign
 * `undefined` values.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function assignMergeValue(object, key, value) {
  if (value !== undefined && !eq(object[key], value) || value === undefined && !(key in object)) {
    baseAssignValue(object, key, value);
  }
}

module.exports = assignMergeValue;

/***/ }),
/* 71 */
/***/ (function(module, exports, __webpack_require__) {

var baseAssignValue = __webpack_require__(45),
    eq = __webpack_require__(17);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Assigns `value` to `key` of `object` if the existing value is not equivalent
 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * for equality comparisons.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function assignValue(object, key, value) {
  var objValue = object[key];
  if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined && !(key in object)) {
    baseAssignValue(object, key, value);
  }
}

module.exports = assignValue;

/***/ }),
/* 72 */
/***/ (function(module, exports, __webpack_require__) {

var copyObject = __webpack_require__(12),
    keys = __webpack_require__(36);

/**
 * The base implementation of `_.assign` without support for multiple sources
 * or `customizer` functions.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @returns {Object} Returns `object`.
 */
function baseAssign(object, source) {
  return object && copyObject(source, keys(source), object);
}

module.exports = baseAssign;

/***/ }),
/* 73 */
/***/ (function(module, exports, __webpack_require__) {

var castPath = __webpack_require__(77),
    toKey = __webpack_require__(16);

/**
 * The base implementation of `_.get` without support for default values.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @returns {*} Returns the resolved value.
 */
function baseGet(object, path) {
  path = castPath(path, object);

  var index = 0,
      length = path.length;

  while (object != null && index < length) {
    object = object[toKey(path[index++])];
  }
  return index && index == length ? object : undefined;
}

module.exports = baseGet;

/***/ }),
/* 74 */
/***/ (function(module, exports, __webpack_require__) {

var arrayPush = __webpack_require__(44),
    isArray = __webpack_require__(0);

/**
 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
 * symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @param {Function} symbolsFunc The function to get the symbols of `object`.
 * @returns {Array} Returns the array of property names and symbols.
 */
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
  var result = keysFunc(object);
  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}

module.exports = baseGetAllKeys;

/***/ }),
/* 75 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsEqualDeep = __webpack_require__(154),
    isObjectLike = __webpack_require__(2);

/**
 * The base implementation of `_.isEqual` which supports partial comparisons
 * and tracks traversed objects.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {boolean} bitmask The bitmask flags.
 *  1 - Unordered comparison
 *  2 - Partial comparison
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, bitmask, customizer, stack) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
    return value !== value && other !== other;
  }
  return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}

module.exports = baseIsEqual;

/***/ }),
/* 76 */
/***/ (function(module, exports, __webpack_require__) {

var identity = __webpack_require__(33),
    metaMap = __webpack_require__(95);

/**
 * The base implementation of `setData` without support for hot loop shorting.
 *
 * @private
 * @param {Function} func The function to associate metadata with.
 * @param {*} data The metadata.
 * @returns {Function} Returns `func`.
 */
var baseSetData = !metaMap ? identity : function (func, data) {
  metaMap.set(func, data);
  return func;
};

module.exports = baseSetData;

/***/ }),
/* 77 */
/***/ (function(module, exports, __webpack_require__) {

var isArray = __webpack_require__(0),
    isKey = __webpack_require__(54),
    stringToPath = __webpack_require__(102),
    toString = __webpack_require__(107);

/**
 * Casts `value` to a path array if it's not one.
 *
 * @private
 * @param {*} value The value to inspect.
 * @param {Object} [object] The object to query keys on.
 * @returns {Array} Returns the cast property path array.
 */
function castPath(value, object) {
  if (isArray(value)) {
    return value;
  }
  return isKey(value, object) ? [value] : stringToPath(toString(value));
}

module.exports = castPath;

/***/ }),
/* 78 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(module) {var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var root = __webpack_require__(1);

/** Detect free variable `exports`. */
var freeExports = ( false ? 'undefined' : _typeof(exports)) == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && ( false ? 'undefined' : _typeof(module)) == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Built-in value references. */
var Buffer = moduleExports ? root.Buffer : undefined,
    allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;

/**
 * Creates a clone of  `buffer`.
 *
 * @private
 * @param {Buffer} buffer The buffer to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Buffer} Returns the cloned buffer.
 */
function cloneBuffer(buffer, isDeep) {
  if (isDeep) {
    return buffer.slice();
  }
  var length = buffer.length,
      result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);

  buffer.copy(result);
  return result;
}

module.exports = cloneBuffer;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(37)(module)))

/***/ }),
/* 79 */
/***/ (function(module, exports, __webpack_require__) {

var cloneArrayBuffer = __webpack_require__(50);

/**
 * Creates a clone of `typedArray`.
 *
 * @private
 * @param {Object} typedArray The typed array to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned typed array.
 */
function cloneTypedArray(typedArray, isDeep) {
  var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
  return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
}

module.exports = cloneTypedArray;

/***/ }),
/* 80 */
/***/ (function(module, exports) {

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * Creates an array that is the composition of partially applied arguments,
 * placeholders, and provided arguments into a single array of arguments.
 *
 * @private
 * @param {Array} args The provided arguments.
 * @param {Array} partials The arguments to prepend to those provided.
 * @param {Array} holders The `partials` placeholder indexes.
 * @params {boolean} [isCurried] Specify composing for a curried function.
 * @returns {Array} Returns the new array of composed arguments.
 */
function composeArgs(args, partials, holders, isCurried) {
  var argsIndex = -1,
      argsLength = args.length,
      holdersLength = holders.length,
      leftIndex = -1,
      leftLength = partials.length,
      rangeLength = nativeMax(argsLength - holdersLength, 0),
      result = Array(leftLength + rangeLength),
      isUncurried = !isCurried;

  while (++leftIndex < leftLength) {
    result[leftIndex] = partials[leftIndex];
  }
  while (++argsIndex < holdersLength) {
    if (isUncurried || argsIndex < argsLength) {
      result[holders[argsIndex]] = args[argsIndex];
    }
  }
  while (rangeLength--) {
    result[leftIndex++] = args[argsIndex++];
  }
  return result;
}

module.exports = composeArgs;

/***/ }),
/* 81 */
/***/ (function(module, exports) {

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * This function is like `composeArgs` except that the arguments composition
 * is tailored for `_.partialRight`.
 *
 * @private
 * @param {Array} args The provided arguments.
 * @param {Array} partials The arguments to append to those provided.
 * @param {Array} holders The `partials` placeholder indexes.
 * @params {boolean} [isCurried] Specify composing for a curried function.
 * @returns {Array} Returns the new array of composed arguments.
 */
function composeArgsRight(args, partials, holders, isCurried) {
  var argsIndex = -1,
      argsLength = args.length,
      holdersIndex = -1,
      holdersLength = holders.length,
      rightIndex = -1,
      rightLength = partials.length,
      rangeLength = nativeMax(argsLength - holdersLength, 0),
      result = Array(rangeLength + rightLength),
      isUncurried = !isCurried;

  while (++argsIndex < rangeLength) {
    result[argsIndex] = args[argsIndex];
  }
  var offset = argsIndex;
  while (++rightIndex < rightLength) {
    result[offset + rightIndex] = partials[rightIndex];
  }
  while (++holdersIndex < holdersLength) {
    if (isUncurried || argsIndex < argsLength) {
      result[offset + holders[holdersIndex]] = args[argsIndex++];
    }
  }
  return result;
}

module.exports = composeArgsRight;

/***/ }),
/* 82 */
/***/ (function(module, exports, __webpack_require__) {

var baseRest = __webpack_require__(169),
    isIterateeCall = __webpack_require__(204);

/**
 * Creates a function like `_.assign`.
 *
 * @private
 * @param {Function} assigner The function to assign values.
 * @returns {Function} Returns the new assigner function.
 */
function createAssigner(assigner) {
  return baseRest(function (object, sources) {
    var index = -1,
        length = sources.length,
        customizer = length > 1 ? sources[length - 1] : undefined,
        guard = length > 2 ? sources[2] : undefined;

    customizer = assigner.length > 3 && typeof customizer == 'function' ? (length--, customizer) : undefined;

    if (guard && isIterateeCall(sources[0], sources[1], guard)) {
      customizer = length < 3 ? undefined : customizer;
      length = 1;
    }
    object = Object(object);
    while (++index < length) {
      var source = sources[index];
      if (source) {
        assigner(object, source, index, customizer);
      }
    }
    return object;
  });
}

module.exports = createAssigner;

/***/ }),
/* 83 */
/***/ (function(module, exports, __webpack_require__) {

var composeArgs = __webpack_require__(80),
    composeArgsRight = __webpack_require__(81),
    countHolders = __webpack_require__(180),
    createCtor = __webpack_require__(27),
    createRecurry = __webpack_require__(84),
    getHolder = __webpack_require__(90),
    reorder = __webpack_require__(225),
    replaceHolders = __webpack_require__(56),
    root = __webpack_require__(1);

/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1,
    WRAP_BIND_KEY_FLAG = 2,
    WRAP_CURRY_FLAG = 8,
    WRAP_CURRY_RIGHT_FLAG = 16,
    WRAP_ARY_FLAG = 128,
    WRAP_FLIP_FLAG = 512;

/**
 * Creates a function that wraps `func` to invoke it with optional `this`
 * binding of `thisArg`, partial application, and currying.
 *
 * @private
 * @param {Function|string} func The function or method name to wrap.
 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
 * @param {*} [thisArg] The `this` binding of `func`.
 * @param {Array} [partials] The arguments to prepend to those provided to
 *  the new function.
 * @param {Array} [holders] The `partials` placeholder indexes.
 * @param {Array} [partialsRight] The arguments to append to those provided
 *  to the new function.
 * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
 * @param {Array} [argPos] The argument positions of the new function.
 * @param {number} [ary] The arity cap of `func`.
 * @param {number} [arity] The arity of `func`.
 * @returns {Function} Returns the new wrapped function.
 */
function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
  var isAry = bitmask & WRAP_ARY_FLAG,
      isBind = bitmask & WRAP_BIND_FLAG,
      isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
      isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
      isFlip = bitmask & WRAP_FLIP_FLAG,
      Ctor = isBindKey ? undefined : createCtor(func);

  function wrapper() {
    var length = arguments.length,
        args = Array(length),
        index = length;

    while (index--) {
      args[index] = arguments[index];
    }
    if (isCurried) {
      var placeholder = getHolder(wrapper),
          holdersCount = countHolders(args, placeholder);
    }
    if (partials) {
      args = composeArgs(args, partials, holders, isCurried);
    }
    if (partialsRight) {
      args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
    }
    length -= holdersCount;
    if (isCurried && length < arity) {
      var newHolders = replaceHolders(args, placeholder);
      return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, thisArg, args, newHolders, argPos, ary, arity - length);
    }
    var thisBinding = isBind ? thisArg : this,
        fn = isBindKey ? thisBinding[func] : func;

    length = args.length;
    if (argPos) {
      args = reorder(args, argPos);
    } else if (isFlip && length > 1) {
      args.reverse();
    }
    if (isAry && ary < length) {
      args.length = ary;
    }
    if (this && this !== root && this instanceof wrapper) {
      fn = Ctor || createCtor(fn);
    }
    return fn.apply(thisBinding, args);
  }
  return wrapper;
}

module.exports = createHybrid;

/***/ }),
/* 84 */
/***/ (function(module, exports, __webpack_require__) {

var isLaziable = __webpack_require__(206),
    setData = __webpack_require__(99),
    setWrapToString = __webpack_require__(100);

/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1,
    WRAP_BIND_KEY_FLAG = 2,
    WRAP_CURRY_BOUND_FLAG = 4,
    WRAP_CURRY_FLAG = 8,
    WRAP_PARTIAL_FLAG = 32,
    WRAP_PARTIAL_RIGHT_FLAG = 64;

/**
 * Creates a function that wraps `func` to continue currying.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
 * @param {Function} wrapFunc The function to create the `func` wrapper.
 * @param {*} placeholder The placeholder value.
 * @param {*} [thisArg] The `this` binding of `func`.
 * @param {Array} [partials] The arguments to prepend to those provided to
 *  the new function.
 * @param {Array} [holders] The `partials` placeholder indexes.
 * @param {Array} [argPos] The argument positions of the new function.
 * @param {number} [ary] The arity cap of `func`.
 * @param {number} [arity] The arity of `func`.
 * @returns {Function} Returns the new wrapped function.
 */
function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
  var isCurry = bitmask & WRAP_CURRY_FLAG,
      newHolders = isCurry ? holders : undefined,
      newHoldersRight = isCurry ? undefined : holders,
      newPartials = isCurry ? partials : undefined,
      newPartialsRight = isCurry ? undefined : partials;

  bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG;
  bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);

  if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
    bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
  }
  var newData = [func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, newHoldersRight, argPos, ary, arity];

  var result = wrapFunc.apply(undefined, newData);
  if (isLaziable(func)) {
    setData(result, newData);
  }
  result.placeholder = placeholder;
  return setWrapToString(result, func, bitmask);
}

module.exports = createRecurry;

/***/ }),
/* 85 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(6);

var defineProperty = function () {
  try {
    var func = getNative(Object, 'defineProperty');
    func({}, '', {});
    return func;
  } catch (e) {}
}();

module.exports = defineProperty;

/***/ }),
/* 86 */
/***/ (function(module, exports, __webpack_require__) {

var SetCache = __webpack_require__(143),
    arraySome = __webpack_require__(146),
    cacheHas = __webpack_require__(173);

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `array` and `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
    return false;
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(array);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var index = -1,
      result = true,
      seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined;

  stack.set(array, other);
  stack.set(other, array);

  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index];

    if (customizer) {
      var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack);
    }
    if (compared !== undefined) {
      if (compared) {
        continue;
      }
      result = false;
      break;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (seen) {
      if (!arraySome(other, function (othValue, othIndex) {
        if (!cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
          return seen.push(othIndex);
        }
      })) {
        result = false;
        break;
      }
    } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
      result = false;
      break;
    }
  }
  stack['delete'](array);
  stack['delete'](other);
  return result;
}

module.exports = equalArrays;

/***/ }),
/* 87 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/** Detect free variable `global` from Node.js. */
var freeGlobal = (typeof global === 'undefined' ? 'undefined' : _typeof(global)) == 'object' && global && global.Object === Object && global;

module.exports = freeGlobal;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(109)))

/***/ }),
/* 88 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetAllKeys = __webpack_require__(74),
    getSymbols = __webpack_require__(53),
    keys = __webpack_require__(36);

/**
 * Creates an array of own enumerable property names and symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names and symbols.
 */
function getAllKeys(object) {
  return baseGetAllKeys(object, keys, getSymbols);
}

module.exports = getAllKeys;

/***/ }),
/* 89 */
/***/ (function(module, exports, __webpack_require__) {

var metaMap = __webpack_require__(95),
    noop = __webpack_require__(265);

/**
 * Gets metadata for `func`.
 *
 * @private
 * @param {Function} func The function to query.
 * @returns {*} Returns the metadata for `func`.
 */
var getData = !metaMap ? noop : function (func) {
  return metaMap.get(func);
};

module.exports = getData;

/***/ }),
/* 90 */
/***/ (function(module, exports) {

/**
 * Gets the argument placeholder value for `func`.
 *
 * @private
 * @param {Function} func The function to inspect.
 * @returns {*} Returns the placeholder value.
 */
function getHolder(func) {
  var object = func;
  return object.placeholder;
}

module.exports = getHolder;

/***/ }),
/* 91 */
/***/ (function(module, exports, __webpack_require__) {

var arrayPush = __webpack_require__(44),
    getPrototype = __webpack_require__(52),
    getSymbols = __webpack_require__(53),
    stubArray = __webpack_require__(105);

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols;

/**
 * Creates an array of the own and inherited enumerable symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of symbols.
 */
var getSymbolsIn = !nativeGetSymbols ? stubArray : function (object) {
  var result = [];
  while (object) {
    arrayPush(result, getSymbols(object));
    object = getPrototype(object);
  }
  return result;
};

module.exports = getSymbolsIn;

/***/ }),
/* 92 */
/***/ (function(module, exports, __webpack_require__) {

var baseCreate = __webpack_require__(26),
    getPrototype = __webpack_require__(52),
    isPrototype = __webpack_require__(30);

/**
 * Initializes an object clone.
 *
 * @private
 * @param {Object} object The object to clone.
 * @returns {Object} Returns the initialized clone.
 */
function initCloneObject(object) {
    return typeof object.constructor == 'function' && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
}

module.exports = initCloneObject;

/***/ }),
/* 93 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(4);

/**
 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` if suitable for strict
 *  equality comparisons, else `false`.
 */
function isStrictComparable(value) {
  return value === value && !isObject(value);
}

module.exports = isStrictComparable;

/***/ }),
/* 94 */
/***/ (function(module, exports) {

/**
 * A specialized version of `matchesProperty` for source values suitable
 * for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function matchesStrictComparable(key, srcValue) {
  return function (object) {
    if (object == null) {
      return false;
    }
    return object[key] === srcValue && (srcValue !== undefined || key in Object(object));
  };
}

module.exports = matchesStrictComparable;

/***/ }),
/* 95 */
/***/ (function(module, exports, __webpack_require__) {

var WeakMap = __webpack_require__(67);

/** Used to store function metadata. */
var metaMap = WeakMap && new WeakMap();

module.exports = metaMap;

/***/ }),
/* 96 */
/***/ (function(module, exports) {

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function (arg) {
    return func(transform(arg));
  };
}

module.exports = overArg;

/***/ }),
/* 97 */
/***/ (function(module, exports, __webpack_require__) {

var apply = __webpack_require__(42);

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * A specialized version of `baseRest` which transforms the rest array.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @param {Function} transform The rest array transform.
 * @returns {Function} Returns the new function.
 */
function overRest(func, start, transform) {
  start = nativeMax(start === undefined ? func.length - 1 : start, 0);
  return function () {
    var args = arguments,
        index = -1,
        length = nativeMax(args.length - start, 0),
        array = Array(length);

    while (++index < length) {
      array[index] = args[start + index];
    }
    index = -1;
    var otherArgs = Array(start + 1);
    while (++index < start) {
      otherArgs[index] = args[index];
    }
    otherArgs[start] = transform(array);
    return apply(func, this, otherArgs);
  };
}

module.exports = overRest;

/***/ }),
/* 98 */
/***/ (function(module, exports) {

/**
 * Gets the value at `key`, unless `key` is "__proto__".
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function safeGet(object, key) {
  return key == '__proto__' ? undefined : object[key];
}

module.exports = safeGet;

/***/ }),
/* 99 */
/***/ (function(module, exports, __webpack_require__) {

var baseSetData = __webpack_require__(76),
    shortOut = __webpack_require__(101);

/**
 * Sets metadata for `func`.
 *
 * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
 * period of time, it will trip its breaker and transition to an identity
 * function to avoid garbage collection pauses in V8. See
 * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
 * for more details.
 *
 * @private
 * @param {Function} func The function to associate metadata with.
 * @param {*} data The metadata.
 * @returns {Function} Returns `func`.
 */
var setData = shortOut(baseSetData);

module.exports = setData;

/***/ }),
/* 100 */
/***/ (function(module, exports, __webpack_require__) {

var getWrapDetails = __webpack_require__(193),
    insertWrapDetails = __webpack_require__(202),
    setToString = __webpack_require__(57),
    updateWrapDetails = __webpack_require__(235);

/**
 * Sets the `toString` method of `wrapper` to mimic the source of `reference`
 * with wrapper details in a comment at the top of the source body.
 *
 * @private
 * @param {Function} wrapper The function to modify.
 * @param {Function} reference The reference function.
 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
 * @returns {Function} Returns `wrapper`.
 */
function setWrapToString(wrapper, reference, bitmask) {
  var source = reference + '';
  return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
}

module.exports = setWrapToString;

/***/ }),
/* 101 */
/***/ (function(module, exports) {

/** Used to detect hot functions by number of calls within a span of milliseconds. */
var HOT_COUNT = 800,
    HOT_SPAN = 16;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeNow = Date.now;

/**
 * Creates a function that'll short out and invoke `identity` instead
 * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
 * milliseconds.
 *
 * @private
 * @param {Function} func The function to restrict.
 * @returns {Function} Returns the new shortable function.
 */
function shortOut(func) {
  var count = 0,
      lastCalled = 0;

  return function () {
    var stamp = nativeNow(),
        remaining = HOT_SPAN - (stamp - lastCalled);

    lastCalled = stamp;
    if (remaining > 0) {
      if (++count >= HOT_COUNT) {
        return arguments[0];
      }
    } else {
      count = 0;
    }
    return func.apply(undefined, arguments);
  };
}

module.exports = shortOut;

/***/ }),
/* 102 */
/***/ (function(module, exports, __webpack_require__) {

var memoizeCapped = __webpack_require__(219);

/** Used to match property names within property paths. */
var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

/**
 * Converts `string` to a property path array.
 *
 * @private
 * @param {string} string The string to convert.
 * @returns {Array} Returns the property path array.
 */
var stringToPath = memoizeCapped(function (string) {
  var result = [];
  if (string.charCodeAt(0) === 46 /* . */) {
      result.push('');
    }
  string.replace(rePropName, function (match, number, quote, subString) {
    result.push(quote ? subString.replace(reEscapeChar, '$1') : number || match);
  });
  return result;
});

module.exports = stringToPath;

/***/ }),
/* 103 */
/***/ (function(module, exports) {

/** Used for built-in method references. */
var funcProto = Function.prototype;

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to convert.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return func + '';
    } catch (e) {}
  }
  return '';
}

module.exports = toSource;

/***/ }),
/* 104 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetTag = __webpack_require__(5),
    getPrototype = __webpack_require__(52),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var objectTag = '[object Object]';

/** Used for built-in method references. */
var funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to infer the `Object` constructor. */
var objectCtorString = funcToString.call(Object);

/**
 * Checks if `value` is a plain object, that is, an object created by the
 * `Object` constructor or one with a `[[Prototype]]` of `null`.
 *
 * @static
 * @memberOf _
 * @since 0.8.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 * }
 *
 * _.isPlainObject(new Foo);
 * // => false
 *
 * _.isPlainObject([1, 2, 3]);
 * // => false
 *
 * _.isPlainObject({ 'x': 0, 'y': 0 });
 * // => true
 *
 * _.isPlainObject(Object.create(null));
 * // => true
 */
function isPlainObject(value) {
  if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
    return false;
  }
  var proto = getPrototype(value);
  if (proto === null) {
    return true;
  }
  var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
  return typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
}

module.exports = isPlainObject;

/***/ }),
/* 105 */
/***/ (function(module, exports) {

/**
 * This method returns a new empty array.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {Array} Returns the new empty array.
 * @example
 *
 * var arrays = _.times(2, _.stubArray);
 *
 * console.log(arrays);
 * // => [[], []]
 *
 * console.log(arrays[0] === arrays[1]);
 * // => false
 */
function stubArray() {
  return [];
}

module.exports = stubArray;

/***/ }),
/* 106 */
/***/ (function(module, exports, __webpack_require__) {

var toFinite = __webpack_require__(269);

/**
 * Converts `value` to an integer.
 *
 * **Note:** This method is loosely based on
 * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {number} Returns the converted integer.
 * @example
 *
 * _.toInteger(3.2);
 * // => 3
 *
 * _.toInteger(Number.MIN_VALUE);
 * // => 0
 *
 * _.toInteger(Infinity);
 * // => 1.7976931348623157e+308
 *
 * _.toInteger('3.2');
 * // => 3
 */
function toInteger(value) {
  var result = toFinite(value),
      remainder = result % 1;

  return result === result ? remainder ? result - remainder : result : 0;
}

module.exports = toInteger;

/***/ }),
/* 107 */
/***/ (function(module, exports, __webpack_require__) {

var baseToString = __webpack_require__(172);

/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 * @example
 *
 * _.toString(null);
 * // => ''
 *
 * _.toString(-0);
 * // => '-0'
 *
 * _.toString([1, 2, 3]);
 * // => '1,2,3'
 */
function toString(value) {
  return value == null ? '' : baseToString(value);
}

module.exports = toString;

/***/ }),
/* 108 */
/***/ (function(module, exports) {

// shim for using process in browser
var process = module.exports = {};

// cached from whatever global is present so that test runners that stub it
// don't break things.  But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals.  It's inside a
// function because try/catches deoptimize in certain engines.

var cachedSetTimeout;
var cachedClearTimeout;

function defaultSetTimout() {
    throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout() {
    throw new Error('clearTimeout has not been defined');
}
(function () {
    try {
        if (typeof setTimeout === 'function') {
            cachedSetTimeout = setTimeout;
        } else {
            cachedSetTimeout = defaultSetTimout;
        }
    } catch (e) {
        cachedSetTimeout = defaultSetTimout;
    }
    try {
        if (typeof clearTimeout === 'function') {
            cachedClearTimeout = clearTimeout;
        } else {
            cachedClearTimeout = defaultClearTimeout;
        }
    } catch (e) {
        cachedClearTimeout = defaultClearTimeout;
    }
})();
function runTimeout(fun) {
    if (cachedSetTimeout === setTimeout) {
        //normal enviroments in sane situations
        return setTimeout(fun, 0);
    }
    // if setTimeout wasn't available but was latter defined
    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
        cachedSetTimeout = setTimeout;
        return setTimeout(fun, 0);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedSetTimeout(fun, 0);
    } catch (e) {
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
            return cachedSetTimeout.call(null, fun, 0);
        } catch (e) {
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
            return cachedSetTimeout.call(this, fun, 0);
        }
    }
}
function runClearTimeout(marker) {
    if (cachedClearTimeout === clearTimeout) {
        //normal enviroments in sane situations
        return clearTimeout(marker);
    }
    // if clearTimeout wasn't available but was latter defined
    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
        cachedClearTimeout = clearTimeout;
        return clearTimeout(marker);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedClearTimeout(marker);
    } catch (e) {
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
            return cachedClearTimeout.call(null, marker);
        } catch (e) {
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
            return cachedClearTimeout.call(this, marker);
        }
    }
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;

function cleanUpNextTick() {
    if (!draining || !currentQueue) {
        return;
    }
    draining = false;
    if (currentQueue.length) {
        queue = currentQueue.concat(queue);
    } else {
        queueIndex = -1;
    }
    if (queue.length) {
        drainQueue();
    }
}

function drainQueue() {
    if (draining) {
        return;
    }
    var timeout = runTimeout(cleanUpNextTick);
    draining = true;

    var len = queue.length;
    while (len) {
        currentQueue = queue;
        queue = [];
        while (++queueIndex < len) {
            if (currentQueue) {
                currentQueue[queueIndex].run();
            }
        }
        queueIndex = -1;
        len = queue.length;
    }
    currentQueue = null;
    draining = false;
    runClearTimeout(timeout);
}

process.nextTick = function (fun) {
    var args = new Array(arguments.length - 1);
    if (arguments.length > 1) {
        for (var i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i];
        }
    }
    queue.push(new Item(fun, args));
    if (queue.length === 1 && !draining) {
        runTimeout(drainQueue);
    }
};

// v8 likes predictible objects
function Item(fun, array) {
    this.fun = fun;
    this.array = array;
}
Item.prototype.run = function () {
    this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};

function noop() {}

process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;

process.listeners = function (name) {
    return [];
};

process.binding = function (name) {
    throw new Error('process.binding is not supported');
};

process.cwd = function () {
    return '/';
};
process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
};
process.umask = function () {
    return 0;
};

/***/ }),
/* 109 */
/***/ (function(module, exports) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var g;

// This works in non-strict mode
g = function () {
	return this;
}();

try {
	// This works if eval is allowed (see CSP)
	g = g || Function("return this")() || (1, eval)("this");
} catch (e) {
	// This works if the window reference is available
	if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === "object") g = window;
}

// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}

module.exports = g;

/***/ }),
/* 110 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__event_emitter_event_emitter__ = __webpack_require__(118);
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }



/**
 * Notifies interested parties about user generated actions
 *
 * @class UserActionEvents
 * @extends EventEmitter
 */

var UserActionEvents = function (_EventsEmitter) {
  _inherits(UserActionEvents, _EventsEmitter);

  function UserActionEvents(emitter /* $rootScope */) {
    _classCallCheck(this, UserActionEvents);

    var _this = _possibleConstructorReturn(this, (UserActionEvents.__proto__ || Object.getPrototypeOf(UserActionEvents)).call(this, emitter));

    _this.namespace = 'useraction';
    return _this;
  }

  return UserActionEvents;
}(__WEBPACK_IMPORTED_MODULE_0__event_emitter_event_emitter__["a" /* default */]);

/* harmony default export */ __webpack_exports__["a"] = (UserActionEvents);

/***/ }),
/* 111 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = register;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers_gtm__ = __webpack_require__(10);





var defaultProps = {
    gaEventCategory: 'Deposit',
    loginStatus: 'Logged In',
    registrationStatus: 'Registered',
    module: 'My Funds',
    depositType: 'BetCash'
};

var _merge = function _merge(evt) {
    return __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default()(defaultProps), evt);
};

//clicks
var _addNewAccountClick = function _addNewAccountClick(defaultConfig) {
    return function () {
        var gtmPropsToMerge = {
            gaEventAction: 'Opened',
            gaEventLabel: 'Add New Account ',
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'AddNewAccountClick', _merge(gtmPropsToMerge));
    };
};

var _accountsOnFileClick = function _accountsOnFileClick(defaultConfig) {
    return function () {
        var gtmPropsToMerge = {
            gaEventAction: 'Opened',
            gaEventLabel: 'Accounts on File',
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'AccountsOnFileClick', _merge(gtmPropsToMerge));
    };
};

var _tooltipClick = function _tooltipClick(defaultConfig) {
    return function () {
        var gtmPropsToMerge = {
            gaEventAction: 'Clicked Tooltip',
            gaEventLabel: 'Bank Routing Number',
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'TooltipClick', _merge(gtmPropsToMerge));
    };
};

var _termsAndConditionsClick = function _termsAndConditionsClick(defaultConfig) {
    return function () {
        var gtmPropsToMerge = {
            gaEventAction: 'Opened',
            gaEventLabel: 'Terms and Conditions',
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'OpenTermsAndConditions', _merge(gtmPropsToMerge));
    };
};

//selected / completed - logs
var _selectedAuthorizedAccount = function _selectedAuthorizedAccount(defaultConfig) {
    return function (bankName) {
        var gtmPropsToMerge = {
            gaEventAction: 'Selected Account',
            gaEventLabel: bankName
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'SelectedAuthorizedAccount', _merge(gtmPropsToMerge));
    };
};

var _selectedDriverLicence = function _selectedDriverLicence(defaultConfig) {
    return function (driverLicenceState) {
        var gtmPropsToMerge = {
            gaEventAction: 'Selected Drivers Licence State',
            gaEventLabel: driverLicenceState,
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'SelectedDriverLicence', _merge(gtmPropsToMerge));
    };
};

var _completedFieldAndBlursAway = function _completedFieldAndBlursAway(defaultConfig) {
    return function (fieldName) {
        var gtmPropsToMerge = {
            gaEventAction: 'Field Complete',
            gaEventLabel: fieldName,
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'CompletedFieldAndBlursAway', _merge(gtmPropsToMerge));
    };
};

var _successfullyAddNewAccount = function _successfullyAddNewAccount(defaultConfig) {
    return function () {
        var gtmPropsToMerge = {
            gaEventAction: 'New Account Success',
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'SuccessfullyAddNewAccount', _merge(gtmPropsToMerge));
    };
};

//error logs
var _attemptToCompleteOtherAmount = function _attemptToCompleteOtherAmount(defaultConfig) {
    return function (errorMsg) {
        var gtmPropsToMerge = {
            gaEventAction: 'Other Amount Field Error',
            gaEventLabel: errorMsg
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'AttemptToCompleteOtherAmountIBC', _merge(gtmPropsToMerge));
    };
};

var _unsuccessfullyAddNewAccount = function _unsuccessfullyAddNewAccount(defaultConfig) {
    return function (errorMsg) {
        var gtmPropsToMerge = {
            gaEventAction: 'New Account Submit Error',
            gaEventLabel: errorMsg,
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'UnsuccessfullyAddNewAccount', _merge(gtmPropsToMerge));
    };
};

var _newAccountFormFieldError = function _newAccountFormFieldError(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: data.fieldName + ' Field Error',
            gaEventLabel: data.errorText,
            module: 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'NewAccountFormFieldError', _merge(gtmPropsToMerge));
    };
};

var _standardDepositStart = function _standardDepositStart(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            event: 'depositStandardStart',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Start',
            gaEventLabel: 'Standard Deposit Start | ' + data.gaEventLabel,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            depositType: data.depositType,
            cardType: data.cardType,
            netDepositFee: data.depositFee,
            module: 'My Funds'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositStandardStart', _merge(gtmPropsToMerge));
    };
};

var _standardDepositSuccess = function _standardDepositSuccess(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            event: 'depositStandardSuccess',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Success',
            eventLabel: 'StandardDeposit-' + data.eventLabel,
            gaEventLabel: 'Standard Deposit Success | ' + data.gaEventLabel,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            depositType: data.depositType,
            netDepositFee: data.netDepositFee,
            module: 'My Funds'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositStandardSuccess', _merge(gtmPropsToMerge));
    };
};

var _standardDepositError = function _standardDepositError(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            event: 'depositStandardError',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Error',
            gaEventLabel: data.errorMsg,
            cardType: data.cardType,
            depositType: data.depositType,
            module: data.module
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositStandardError', _merge(gtmPropsToMerge));
    };
};

function register(events, defaultConfig) {
    events.on('AddNewAccountClick', _addNewAccountClick(defaultConfig));
    events.on('AccountsOnFileClick', _accountsOnFileClick(defaultConfig));
    events.on('TooltipClick', _tooltipClick(defaultConfig));
    events.on('TermsAndConditionsClick', _termsAndConditionsClick(defaultConfig));
    events.on('SelectedAuthorizedAccount', _selectedAuthorizedAccount(defaultConfig));
    events.on('SelectedDriverLicence', _selectedDriverLicence(defaultConfig));
    events.on('CompletedFieldAndBlursAway', _completedFieldAndBlursAway(defaultConfig));
    events.on('SuccessfullyAddNewAccount', _successfullyAddNewAccount(defaultConfig));
    events.on('UnsuccessfullyAddNewAccount', _unsuccessfullyAddNewAccount(defaultConfig));
    events.on('AttemptToCompleteOtherAmountIBC', _attemptToCompleteOtherAmount(defaultConfig));
    events.on('NewAccountFormFieldError', _newAccountFormFieldError(defaultConfig));
    events.on('StandardDepositStart', _standardDepositStart(defaultConfig));
    events.on('StandardDepositSuccess', _standardDepositSuccess(defaultConfig));
    events.on('StandardDepositError', _standardDepositError(defaultConfig));
}

/***/ }),
/* 112 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = register;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers_gtm__ = __webpack_require__(10);





var defaultParams = {
    depositType: 'Card',
    gaEventCategory: 'Deposit',
    loginStatus: 'Logged In',
    registrationStatus: 'Registered',
    module: 'My Funds'
};

var _merge = function _merge(evt) {
    return __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default()(defaultParams), evt);
};

var _FieldFill = function _FieldFill(defaultConfig) {
    return function (info) {
        var m = 'My Funds';
        if (info.module && info.module === 'new') {
            m = 'My Funds - New Account';
        }
        var gtmEvent = {
            'gaEventAction': 'Field Complete',
            'module': m,
            'gaEventLabel': info.field.$name
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'FieldFill', _merge(gtmEvent));
    };
};

var _FieldFillError = function _FieldFillError(defaultConfig) {
    return function (info) {
        var m = 'My Funds - New Account';
        if (info.module && info.module === 'added') {
            m = 'My Funds';
        }
        if (Object.keys((info.field || {}).$error).length) {
            var msg = void 0;
            if (info.field.$error.minlength && info.field.$name === 'cardNumber') {
                msg = 'Invalid card number (16 digit number)';
            } else if (info.field.$error.required) {
                msg = 'The field is Required';
            } else if (info.field.$error.pattern) {
                msg = 'Invalid Value';
            } else if (info.field.$error.min) {
                msg = 'Invalid Year';
            } else if (info.field.$error.minlength && info.field.$name === 'cardCvn') {
                msg = 'Invalid CVV';
            } else if (info.field.$error.max && info.field.$name === 'cardExpYr') {
                msg = 'Invalid Year (valid numbers are between 17-67) *****Expiracy Year fields only';
            } else if (info.field.$error.max && info.field.$name === 'cardExpMonth') {
                msg = 'Invalid Month (valid numbers are between 1-12) *****Expiracy Month fields only';
            }

            var gtmEvent = {
                'gaEventAction': info.field.$name + ' Field Error',
                'gaEventLabel': msg,
                'module': m
            };
            __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'FieldFillError', _merge(gtmEvent));
        } else {
            _FieldFill(defaultConfig)(info);
        }
    };
};

var _CreditTooltip = function _CreditTooltip(defaultConfig) {
    return function () {
        var gtmEvent = {
            'gaEventAction': 'Clicked Tooltip',
            'gaEventLabel': 'CVV'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'FieldFill', _merge(gtmEvent));
    };
};

var _CreditChangeCard = function _CreditChangeCard(defaultConfig) {
    return function (card) {
        var gtmEvent = {
            'gaEventAction': 'Selected Account',
            'cardType': card.typeName
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'CreditChangeCard', _merge(gtmEvent));
    };
};

var _ChangeCreditMethod = function _ChangeCreditMethod(defaultConfig) {
    return function (method) {
        var tab = method === 'NEW' ? 'Add New Card' : 'Cards On File';
        var gtmEvent = {
            'gaEventAction': 'Opened',
            'gaEventLabel': tab,
            'module': 'My Funds - New Account'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'ChangeCreditMethod', _merge(gtmEvent));
    };
};

var _CVVInfoClick = function _CVVInfoClick(defaultConfig) {
    return function (AmountType) {
        var gtmEvent = {
            'gaEventAction': 'Clicked Tooltip',
            'gaEventLabel': 'CVV',
            'amountOption': AmountType
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'CVVInfoClick', _merge(gtmEvent));
    };
};

var _attemptToCompleteOtherAmount = function _attemptToCompleteOtherAmount(defaultConfig) {
    return function (errorMsg) {
        var gtmPropsToMerge = {
            gaEventAction: 'Other Amount Field Error',
            gaEventLabel: errorMsg
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'AttemptToCompleteOtherAmountCC', _merge(gtmPropsToMerge));
    };
};

var _authorizeDepositClick = function _authorizeDepositClick(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: 'Deposit Attempt',
            depositAmount: data && data.amount ? parseInt(data.amount, 10) : undefined,
            amountOption: data.wasDefaultAmountUsed,
            module: 'My Funds'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'AuthorizeDepositClickCC', _merge(gtmPropsToMerge));
    };
};

var _discoverCardRedirect = function _discoverCardRedirect(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: 'Deposit Re-Direct',
            gaEventLabel: 'Re-Directed to Sightline',
            gaEventValue: data && data.depositAmount ? parseFloat(data.depositAmount) : undefined, // pass as an integer!
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined, // pass as a JS decimal - not a string!
            amountOption: data.amountOption,
            cardType: data.cardType, // 'Debit' || 'Credit'
            module: data.module,
            microApp: 'non-Microapp'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'DiscoverCardRedirect', _merge(gtmPropsToMerge));
    };
};

function register(events, defaultConfig) {
    events.on('FieldFill', _FieldFill(defaultConfig));
    events.on('CVVInfoClick', _CVVInfoClick(defaultConfig));
    events.on('FieldFillError', _FieldFillError(defaultConfig));
    events.on('CreditChangeCard', _CreditChangeCard(defaultConfig));
    events.on('CreditTooltip', _CreditTooltip(defaultConfig));
    events.on('ChangeCreditMethod', _ChangeCreditMethod(defaultConfig));
    events.on('AuthorizeDepositClickCC', _authorizeDepositClick(defaultConfig));
    events.on('AttemptToCompleteOtherAmountCC', _attemptToCompleteOtherAmount(defaultConfig));
    events.on('DiscoverCardRedirect', _discoverCardRedirect(defaultConfig));
}

/***/ }),
/* 113 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = register;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers_gtm__ = __webpack_require__(10);





var defaultProps = {
    event: 'deposit',
    gaEventCategory: 'Deposit',
    loginStatus: 'Logged In',
    microApp: 'Deposit',
    registrationStatus: 'Registered',
    module: 'My Funds',
    depositType: 'BetCash'
};

var _merge = function _merge(evt) {
    return __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default()(defaultProps), evt);
};

var _attemptDeposit = function _attemptDeposit(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: 'Deposit Attempt',
            gaEventValue: data && data.depositAmount ? parseFloat(data.depositAmount) : undefined,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            amountOption: data.amountOption,
            module: data.module,
            depositType: data.depositType
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'Deposit Attempt', _merge(gtmPropsToMerge));
    };
};

var _successDeposit = function _successDeposit(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: 'Deposit Success',
            gaEventValue: data && data.depositAmount ? parseFloat(data.depositAmount) : undefined,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            amountOption: data.amountOption,
            module: data.module,
            depositType: data.depositType,
            isFeePaid: data.isFeePaid
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'Deposit Success', _merge(gtmPropsToMerge));
    };
};

var _errorDeposit = function _errorDeposit(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: 'Deposit Error',
            gaEventLabel: data.errorMessage,
            gaEventValue: data && data.depositAmount ? parseFloat(data.depositAmount) : undefined,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            amountOption: data.amountOption,
            module: data.module,
            depositType: data.depositType
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'Deposit Error', _merge(gtmPropsToMerge));
    };
};

function register(events, defaultConfig) {
    events.on('depositAttempt', _attemptDeposit(defaultConfig));
    events.on('depositSuccess', _successDeposit(defaultConfig));
    events.on('depositError', _errorDeposit(defaultConfig));
}

/***/ }),
/* 114 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = register;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers_gtm__ = __webpack_require__(10);





var defaultParams = {
    depositType: 'MoneyPak',
    event: 'deposit',
    gaEventCategory: 'Deposit',
    loginStatus: 'Logged In',
    registrationStatus: 'Registered',
    module: 'My Funds',
    microApp: 'Deposit'
};

var _merge = function _merge(evt) {
    return __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default()(defaultParams), evt);
};

var _moneyPakFAQ = function _moneyPakFAQ(defaultConfig) {
    return function () {
        var gtmEvent = {
            gaEventAction: 'Opened',
            gaEventLabel: 'FAQ'
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'moneyPakFAQ', _merge(gtmEvent));
    };
};

var _moneyPakTooltip = function _moneyPakTooltip(defaultConfig) {
    return function () {
        var gtmEvent = {
            gaEventAction: 'Clicked Tooltip'
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'moneyPakTooltip', _merge(gtmEvent));
    };
};

var _moneyPakFill = function _moneyPakFill(defaultConfig) {
    return function (error) {
        var msg = false;
        if (error) {
            if (error.mask) {
                msg = 'The MoneyPak number is invalid';
            } else if (error.required) {
                msg = 'Please enter your MoneyPak number';
            }
        }
        var gtmEvent = {
            gaEventLabel: msg || 'Field Complete',
            gaEventAction: 'MoneyPak Number' + (msg ? ' Field Error' : '')
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'moneyPakFill', _merge(gtmEvent));
    };
};

var _depositAttemptMoneyPak = function _depositAttemptMoneyPak(defaultConfig) {
    return function (value) {
        var gtmEvent = {
            event: 'deposit',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Attempt',
            module: 'My Funds',
            depositType: 'MoneyPak',
            gaEventLabel: value,
            netDepositFee: 0
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'DepositAttemptMoneyPak', _merge(gtmEvent));
    };
};

var _depositSuccessMoneyPak = function _depositSuccessMoneyPak(defaultConfig) {
    return function (amount, isFeePaid) {
        var gtmEvent = {
            gaEventAction: 'Deposit Success',
            depositAmount: parseInt(amount, 10),
            gaEventValue: parseFloat(amount),
            netDepositFee: 0,
            isFeePaid: isFeePaid
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositSuccessMoneyPak', _merge(gtmEvent));
    };
};

var _depositErrorMoneyPak = function _depositErrorMoneyPak(defaultConfig) {
    return function (message) {
        var gtmEvent = {
            gaEventAction: 'Deposit Error',
            gaEventLabel: message,
            netDepositFee: 0
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositErrorMoneyPak', _merge(gtmEvent));
    };
};

var _moneyPakStart = function _moneyPakStart(defaultConfig) {
    return function () {
        var gtmEvent = {
            gaEventAction: 'Deposit Start'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'moneyPakStart', _merge(gtmEvent));
    };
};

function register(events, defaultConfig) {
    events.on('depositAttemptMoneyPak', _depositAttemptMoneyPak(defaultConfig));
    events.on('depositSuccessMoneyPak', _depositSuccessMoneyPak(defaultConfig));
    events.on('depositErrorMoneyPak', _depositErrorMoneyPak(defaultConfig));
    events.on('moneyPakFAQ', _moneyPakFAQ(defaultConfig));
    events.on('moneyPakTooltip', _moneyPakTooltip(defaultConfig));
    events.on('moneyPakFill', _moneyPakFill(defaultConfig));
    events.on('moneyPakStart', _moneyPakStart(defaultConfig));
}

/***/ }),
/* 115 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = register;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers_gtm__ = __webpack_require__(10);





var defaultParams = {
    depositType: 'PayPal',
    gaEventCategory: 'Deposit',
    loginStatus: 'Logged In',
    module: 'My Funds',
    microApp: 'Deposit',
    registrationStatus: 'Registered'
};

var _merge = function _merge(evt) {
    return __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default()(defaultParams), evt);
};

var _amountChange = function _amountChange(defaultConfig) {
    return function (data) {
        var depositType = data.defaultAmount ? 'Default Amount' : 'Other Amount';
        var gtmEvent = {
            gaEventLabel: 'Standard Deposit Start | ' + depositType,
            depositAmount: data && data.amount ? parseInt(data.amount, 10) : undefined,
            gaEventAction: 'Deposit Start',
            netDepositFee: data.fee
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositSelectAmount', _merge(gtmEvent));
    };
};

var _depositAttemptPayPal = function _depositAttemptPayPal(defaultConfig) {
    return function (data) {
        var depositType = data.defaultAmount ? 'Default Amount' : 'Other Amount';
        var gtmEvent = {
            gaEventAction: 'Deposit Attempt',
            gaEventValue: data && data.amount ? parseFloat(data.amount) : undefined,
            depositAmount: data && data.amount ? parseInt(data.amount) : undefined,
            amountOption: depositType,
            netDepositFee: data.fee
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'DepositAttemptPayPal', _merge(gtmEvent));
    };
};

var _depositSuccessPayPal = function _depositSuccessPayPal(defaultConfig) {
    return function (data) {
        var amount = (data || {}).amount;
        var fee = (data || {}).fee;
        var isFeePaid = (data || {}).isFeePaid;
        var total = void 0;
        if (amount && fee) {
            total = amount - fee;
        }
        var depositType = data.defaultAmount ? 'Default Amount' : 'Other Amount';
        var gtmEvent = {
            gaEventAction: 'Deposit Success',
            gaEventValue: total ? parseFloat(total) : undefined,
            depositAmount: total ? parseInt(total, 10) : undefined,
            netDepositFee: fee,
            amountOption: total ? depositType : undefined,
            isFeePaid: isFeePaid
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositStandardSuccess', _merge(gtmEvent));
    };
};

var _depositErrorPayPal = function _depositErrorPayPal(defaultConfig) {
    return function (data) {
        var amount = (data.details || {}).amount;
        var fee = (data.details || {}).fee;
        var total = void 0;
        if (amount && fee) {
            total = amount - fee;
        }
        var gtmEvent = {
            gaEventAction: 'Deposit Error',
            gaEventLabel: data.message,
            gaEventValue: total,
            depositAmount: total,
            netDepositFee: fee
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositStandardError', _merge(gtmEvent));
    };
};

var _paypalCancelDeposit = function _paypalCancelDeposit(defaultConfig) {
    return function () {
        var gtmEvent = {
            gaEventAction: 'PayPal Page Click',
            gaEventLabel: 'Cancel PayPal Deposit',
            screenName: 'PayPal Page',
            sectionName: 'PayPal | Deposit Page',
            eventLabel: 'PaypalCancelDeposit'
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'siteClick', _merge(gtmEvent));
    };
};

var _paypalSubmitDeposit = function _paypalSubmitDeposit(defaultConfig) {
    return function () {
        var gtmEvent = {
            gaEventAction: 'PayPal Page Click',
            gaEventLabel: 'Confirm PayPal Deposit',
            screenName: 'PayPal Page',
            sectionName: 'PayPal | Deposit Page',
            eventLabel: 'PaypalSubmitDeposit'
        };

        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'siteClick', _merge(gtmEvent));
    };
};

var _payPalFill = function _payPalFill(defaultConfig) {
    return function (error) {
        if (Object.keys(error).length) {
            var msg = false;
            if (error.max) {
                msg = 'Maximum amount reached';
            } else if (error.min) {
                msg = 'Minimum $10.00';
            } else if (error.required) {
                msg = 'Required Field';
            }
            var gtmEvent = {
                gaEventLabel: msg,
                gaEventAction: 'Paypal Amount Field Error'
            };
            __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'payPalFill', _merge(gtmEvent));
        }
    };
};

function register(events, defaultConfig) {
    events.on('depositAttemptPayPal', _depositAttemptPayPal(defaultConfig));
    events.on('depositSuccessPayPal', _depositSuccessPayPal(defaultConfig));
    events.on('depositErrorPayPal', _depositErrorPayPal(defaultConfig));
    events.on('amountChange', _amountChange(defaultConfig));
    events.on('paypalCancelDeposit', _paypalCancelDeposit(defaultConfig));
    events.on('paypalSubmitDeposit', _paypalSubmitDeposit(defaultConfig));
    events.on('payPalFill', _payPalFill(defaultConfig));
}

/***/ }),
/* 116 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = register;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers_gtm__ = __webpack_require__(10);





var defaultProps = {
    gaEventCategory: 'Deposit',
    loginStatus: 'Logged In',
    registrationStatus: 'Registered',
    module: 'Quick Deposit'
};

var _merge = function _merge(evt) {
    return __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default()(defaultProps), evt);
};

//clicks
var _attemptToCompleteOtherAmount = function _attemptToCompleteOtherAmount(defaultConfig) {
    return function (errorMsg) {
        var event = {
            gaEventAction: 'Other Amount Field Error',
            gaEventLabel: errorMsg
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'AttemptToCompleteOtherAmountQuick', _merge(event));
    };
};

var _selectAccount = function _selectAccount(defaultConfig) {
    return function (card) {
        var name = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["b" /* isCard */])(card.ftype) ? 'Card' : 'Betcash';
        var event = {
            gaEventAction: 'Selected Account',
            gaEventLabel: card.type,
            depositType: name
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'selectAccount', _merge(event));
    };
};

var _selectDefaultAmount = function _selectDefaultAmount(defaultConfig) {
    return function (data) {
        var type = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["b" /* isCard */])(data.depositType) ? 'Card' : 'Betcash';
        var defaultAmount = data.gaEventLabel ? 'Yes' : 'No';
        var event = {
            gaEventAction: 'Selected Deposit Default',
            depositType: type,
            gaEventLabel: defaultAmount,
            amountOption: data.amountType
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'selectDefaultAmount', _merge(event));
    };
};

var _navigatedTo = function _navigatedTo(defaultConfig) {
    return function (data) {
        var event = {
            event: 'Navigation',
            gaEventCategory: 'Navigation',
            gaEventAction: 'Navigated To',
            gaEventLabel: data.name,
            microApp: 'non-microApp',
            destinationUrl: data.url
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'navigatedTo', _merge(event));
    };
};

var _attemptedDepositQuick = function _attemptedDepositQuick(defaultConfig) {
    return function (data) {
        var type = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["b" /* isCard */])(data.depositType) ? 'Card' : 'Betcash';
        var event = {
            gaEventAction: 'Deposit Attempt',
            amountOption: data.amountOption,
            cardType: data.cardType,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            netDepositFee: 5,
            depositType: type
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'attemptedDepositQuick', _merge(event));
    };
};

var _quickDepositStart = function _quickDepositStart(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            event: 'depositQuickStart',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Start',
            gaEventLabel: 'Quick Deposit Start | ' + data.gaEventLabel,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            depositType: data.depositType,
            cardType: data.cardType,
            netDepositFee: data.depositFee
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositQuickStart', _merge(gtmPropsToMerge));
    };
};

var _quickDepositSuccess = function _quickDepositSuccess(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            event: 'depositQuickSuccess',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Success',
            eventLabel: 'QuickDeposit-' + data.eventLabel,
            gaEventLabel: 'Quick Deposit Success | ' + data.gaEventLabel,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            depositType: data.depositType,
            netDepositFee: data.netDepositFee,
            isFeePaid: !!data.netDepositFee
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositQuickSuccess', _merge(gtmPropsToMerge));
    };
};

var _quickDepositError = function _quickDepositError(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            event: 'depositQuickError',
            gaEventCategory: 'Deposit',
            gaEventAction: 'Deposit Error',
            gaEventLabel: data.errorMsg,
            cardType: data.cardType,
            depositType: data.depositType,
            module: data.module
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositQuickError', _merge(gtmPropsToMerge));
    };
};

function register(events, defaultConfig) {
    events.on('AttemptToCompleteOtherAmountQuick', _attemptToCompleteOtherAmount(defaultConfig));
    events.on('selectDefaultAmount', _selectDefaultAmount(defaultConfig));
    events.on('selectAccount', _selectAccount(defaultConfig));
    events.on('navigatedTo', _navigatedTo(defaultConfig));
    events.on('attemptedDepositQuick', _attemptedDepositQuick(defaultConfig));
    events.on('QuickDepositStart', _quickDepositStart(defaultConfig));
    events.on('QuickDepositSuccess', _quickDepositSuccess(defaultConfig));
    events.on('QuickDepositError', _quickDepositError(defaultConfig));
}

/***/ }),
/* 117 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = register;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__helpers_gtm__ = __webpack_require__(10);





var defaultProps = {
    gaEventCategory: 'Deposit',
    loginStatus: 'Logged In',
    registrationStatus: 'Registered',
    depositType: 'Sightline',
    module: 'My Funds'
};

var _merge = function _merge(evt) {
    return __WEBPACK_IMPORTED_MODULE_1_lodash_fp_merge___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_fp_cloneDeep___default()(defaultProps), evt);
};

var _userRedirectedToSightline = function _userRedirectedToSightline(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: 'Deposit Redirect',
            gaEventLabel: 'Standard Deposit | Sightline',
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            netDepositFee: data.depositFee
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'depositRedirect', _merge(gtmPropsToMerge));
    };
};

var _cardDeclineRedirectClick = function _cardDeclineRedirectClick(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            gaEventAction: 'Card Declined Redirect',
            gaEventLabel: 'Card Declined Redirect | Sightline',
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            netDepositFee: data.depositFee
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'Deposit', _merge(gtmPropsToMerge));
    };
};

var _cardDeclinedRedirectModal = function _cardDeclinedRedirectModal(defaultConfig) {
    return function (data) {
        var gtmPropsToMerge = {
            event: 'deposit',
            gaEventCategory: 'Deposit',
            gaEventAction: data.isOpen ? 'Seen' : 'Close',
            gaEventLabel: 'Sightline flow pop-up',
            gaEventValue: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            module: data.module,
            depositAmount: data && data.depositAmount ? parseInt(data.depositAmount, 10) : undefined,
            microApp: 'Deposit'
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'Deposit', _merge(gtmPropsToMerge));
    };
};

var _cardDeclinedRedirectBlackListModal = function _cardDeclinedRedirectBlackListModal(defaultConfig) {
    return function (data) {
        var eventAction = data.isOpen ? 'Seen' : 'Close';
        var eventLabel;

        if (data.selection) {
            eventLabel = data.selection;
            eventAction = data.isFinished ? 'Submit' : 'Select';
        }

        var gtmPropsToMerge = {
            event: 'siteClick',
            gaEventCategory: 'Site Click',
            gaEventAction: eventAction,
            gaEventLabel: eventLabel,
            module: 'card failover modal',
            microApp: undefined,
            depositType: 'Credit/Debit card',
            tag: undefined
        };
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__helpers_gtm__["a" /* GTMEvent */])().send(defaultConfig, 'Deposit', _merge(gtmPropsToMerge));
    };
};

function register(events, defaultConfig) {
    events.on('UserSuccessfullyRedirectedToSightline', _userRedirectedToSightline(defaultConfig));
    events.on('CardDeclineRedirectClick', _cardDeclineRedirectClick(defaultConfig));
    events.on('CcpCardDeclinedRedirectSightline', _cardDeclinedRedirectModal(defaultConfig));
    events.on('CcpCardDeclinedRedirectBlackListCard', _cardDeclinedRedirectBlackListModal(defaultConfig));
}

/***/ }),
/* 118 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var EventEmitter = function () {

  // constructor :: ($rootScope) -> void
  function EventEmitter(emitter /* $rootScope*/) {
    _classCallCheck(this, EventEmitter);

    this.eventHandlers = {};
    this.emitter = emitter;
    this.namespace = '';
  }

  // emit :: (String, mixed) -> EventEmitter


  _createClass(EventEmitter, [{
    key: 'emit',
    value: function emit(eventName) {
      var _emitter;

      var identifier = this.namespace + ':' + eventName;

      for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        params[_key - 1] = arguments[_key];
      }

      (_emitter = this.emitter).$emit.apply(_emitter, [identifier].concat(params));
      return this;
    }

    // on :: (String, Function) -> EventEmitter

  }, {
    key: 'on',
    value: function on(eventName, callback) {
      var handler = function handler(evt) {
        for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
          args[_key2 - 1] = arguments[_key2];
        }

        return callback.apply(undefined, args);
      };
      var identifier = this.namespace + ':' + eventName;

      this.eventHandlers[identifier] = this.eventHandlers[identifier] || [];
      this.eventHandlers[identifier].push(this.emitter.$on(identifier, handler));

      return this;
    }

    // off :: (String) -> EventEmitter

  }, {
    key: 'off',
    value: function off(identifier) {
      [].concat(this.eventHandlers[identifier]).map(function (eventHandlerFunc) {
        return eventHandlerFunc();
      });

      this.eventHandlers[identifier] = [];

      return this;
    }
  }]);

  return EventEmitter;
}();

/* harmony default export */ __webpack_exports__["a"] = (EventEmitter);

/***/ }),
/* 119 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(module) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var _typeof2 = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

(function webpackUniversalModuleDefinition(root, factory) {
  if (( false ? 'undefined' : _typeof2(exports)) === 'object' && ( false ? 'undefined' : _typeof2(module)) === 'object') module.exports = factory(__webpack_require__(59));else if (true) !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(59)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));else {
    var a = (typeof exports === 'undefined' ? 'undefined' : _typeof2(exports)) === 'object' ? factory(require("axios")) : factory(root["axios"]);
    for (var i in a) {
      ((typeof exports === 'undefined' ? 'undefined' : _typeof2(exports)) === 'object' ? exports : root)[i] = a[i];
    }
  }
})(typeof self !== 'undefined' ? self : this, function (__WEBPACK_EXTERNAL_MODULE_14__) {
  return (/******/function (modules) {
      // webpackBootstrap
      /******/ // The module cache
      /******/var installedModules = {};
      /******/
      /******/ // The require function
      /******/function __webpack_require__(moduleId) {
        /******/
        /******/ // Check if module is in cache
        /******/if (installedModules[moduleId]) {
          /******/return installedModules[moduleId].exports;
          /******/
        }
        /******/ // Create a new module (and put it into the cache)
        /******/var module = installedModules[moduleId] = {
          /******/i: moduleId,
          /******/l: false,
          /******/exports: {}
          /******/ };
        /******/
        /******/ // Execute the module function
        /******/modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        /******/
        /******/ // Flag the module as loaded
        /******/module.l = true;
        /******/
        /******/ // Return the exports of the module
        /******/return module.exports;
        /******/
      }
      /******/
      /******/
      /******/ // expose the modules object (__webpack_modules__)
      /******/__webpack_require__.m = modules;
      /******/
      /******/ // expose the module cache
      /******/__webpack_require__.c = installedModules;
      /******/
      /******/ // define getter function for harmony exports
      /******/__webpack_require__.d = function (exports, name, getter) {
        /******/if (!__webpack_require__.o(exports, name)) {
          /******/Object.defineProperty(exports, name, {
            /******/configurable: false,
            /******/enumerable: true,
            /******/get: getter
            /******/ });
          /******/
        }
        /******/
      };
      /******/
      /******/ // getDefaultExport function for compatibility with non-harmony modules
      /******/__webpack_require__.n = function (module) {
        /******/var getter = module && module.__esModule ?
        /******/function getDefault() {
          return module['default'];
        } :
        /******/function getModuleExports() {
          return module;
        };
        /******/__webpack_require__.d(getter, 'a', getter);
        /******/return getter;
        /******/
      };
      /******/
      /******/ // Object.prototype.hasOwnProperty.call
      /******/__webpack_require__.o = function (object, property) {
        return Object.prototype.hasOwnProperty.call(object, property);
      };
      /******/
      /******/ // __webpack_public_path__
      /******/__webpack_require__.p = "";
      /******/
      /******/ // Load entry module and return exports
      /******/return __webpack_require__(__webpack_require__.s = 15);
      /******/
    }(
    /************************************************************************/
    /******/[
    /* 0 */
    /***/function (module, exports, __webpack_require__) {

      var getNative = __webpack_require__(8);

      /* Built-in method references that are verified to be native. */
      var nativeCreate = getNative(Object, 'create');

      module.exports = nativeCreate;

      /***/
    },
    /* 1 */
    /***/function (module, exports, __webpack_require__) {

      var eq = __webpack_require__(45);

      /**
       * Gets the index at which the `key` is found in `array` of key-value pairs.
       *
       * @private
       * @param {Array} array The array to inspect.
       * @param {*} key The key to search for.
       * @returns {number} Returns the index of the matched value, else `-1`.
       */
      function assocIndexOf(array, key) {
        var length = array.length;
        while (length--) {
          if (eq(array[length][0], key)) {
            return length;
          }
        }
        return -1;
      }

      module.exports = assocIndexOf;

      /***/
    },
    /* 2 */
    /***/function (module, exports, __webpack_require__) {

      var isKeyable = __webpack_require__(51);

      /**
       * Gets the data for `map`.
       *
       * @private
       * @param {Object} map The map to query.
       * @param {string} key The reference key.
       * @returns {*} Returns the map data.
       */
      function getMapData(map, key) {
        var data = map.__data__;
        return isKeyable(key) ? data[typeof key == 'string' ? 'string' : 'hash'] : data.map;
      }

      module.exports = getMapData;

      /***/
    },
    /* 3 */
    /***/function (module, exports) {

      /**
       * Checks if `value` is classified as an `Array` object.
       *
       * @static
       * @memberOf _
       * @since 0.1.0
       * @category Lang
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is an array, else `false`.
       * @example
       *
       * _.isArray([1, 2, 3]);
       * // => true
       *
       * _.isArray(document.body.children);
       * // => false
       *
       * _.isArray('abc');
       * // => false
       *
       * _.isArray(_.noop);
       * // => false
       */
      var isArray = Array.isArray;

      module.exports = isArray;

      /***/
    },
    /* 4 */
    /***/function (module, exports, __webpack_require__) {

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      var baseGetTag = __webpack_require__(7),
          isObjectLike = __webpack_require__(24);

      /** `Object#toString` result references. */
      var symbolTag = '[object Symbol]';

      /**
       * Checks if `value` is classified as a `Symbol` primitive or object.
       *
       * @static
       * @memberOf _
       * @since 4.0.0
       * @category Lang
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
       * @example
       *
       * _.isSymbol(Symbol.iterator);
       * // => true
       *
       * _.isSymbol('abc');
       * // => false
       */
      function isSymbol(value) {
        return (typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
      }

      module.exports = isSymbol;

      /***/
    },
    /* 5 */
    /***/function (module, exports, __webpack_require__) {

      var root = __webpack_require__(6);

      /** Built-in value references. */
      var _Symbol = root.Symbol;

      module.exports = _Symbol;

      /***/
    },
    /* 6 */
    /***/function (module, exports, __webpack_require__) {

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      var freeGlobal = __webpack_require__(20);

      /** Detect free variable `self`. */
      var freeSelf = (typeof self === 'undefined' ? 'undefined' : _typeof(self)) == 'object' && self && self.Object === Object && self;

      /** Used as a reference to the global object. */
      var root = freeGlobal || freeSelf || Function('return this')();

      module.exports = root;

      /***/
    },
    /* 7 */
    /***/function (module, exports, __webpack_require__) {

      var _Symbol = __webpack_require__(5),
          getRawTag = __webpack_require__(22),
          objectToString = __webpack_require__(23);

      /** `Object#toString` result references. */
      var nullTag = '[object Null]',
          undefinedTag = '[object Undefined]';

      /** Built-in value references. */
      var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;

      /**
       * The base implementation of `getTag` without fallbacks for buggy environments.
       *
       * @private
       * @param {*} value The value to query.
       * @returns {string} Returns the `toStringTag`.
       */
      function baseGetTag(value) {
        if (value == null) {
          return value === undefined ? undefinedTag : nullTag;
        }
        return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
      }

      module.exports = baseGetTag;

      /***/
    },
    /* 8 */
    /***/function (module, exports, __webpack_require__) {

      var baseIsNative = __webpack_require__(32),
          getValue = __webpack_require__(37);

      /**
       * Gets the native function at `key` of `object`.
       *
       * @private
       * @param {Object} object The object to query.
       * @param {string} key The key of the method to get.
       * @returns {*} Returns the function if it's native, else `undefined`.
       */
      function getNative(object, key) {
        var value = getValue(object, key);
        return baseIsNative(value) ? value : undefined;
      }

      module.exports = getNative;

      /***/
    },
    /* 9 */
    /***/function (module, exports) {

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      /**
       * Checks if `value` is the
       * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
       * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
       *
       * @static
       * @memberOf _
       * @since 0.1.0
       * @category Lang
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is an object, else `false`.
       * @example
       *
       * _.isObject({});
       * // => true
       *
       * _.isObject([1, 2, 3]);
       * // => true
       *
       * _.isObject(_.noop);
       * // => true
       *
       * _.isObject(null);
       * // => false
       */
      function isObject(value) {
        var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
        return value != null && (type == 'object' || type == 'function');
      }

      module.exports = isObject;

      /***/
    },
    /* 10 */
    /***/function (module, exports) {

      module.exports = {
        service_host: 'service.tvg.com',
        service: {
          graph: '/graph/v2/query',
          wtx: '/wtx/v1/wagers',
          pay: '/pay/v1',
          capi: '/capi/v1',
          log: '/uel/v1/log-event',
          usa: '/usa/v2',
          usa_v1: '/usa/v1',
          uam: '/uam/v1',
          prf: '/prf/v1',
          upr: '/upr/v1/preferences',
          geo: '/geo/v1',
          uwt: '/uwt/v1',
          wro: '/wro/v1',
          uas: '/uas/v1',
          nav: '/nav/v1',
          slp: '/slp/v1',
          ufc: '/ufc/v1',
          deposit: '/deposit/api'
        },
        google: {
          gtmId: 'KTDSBG',
          gaId: 'UA-8156856-2'
        }
      };

      /***/
    },
    /* 11 */
    /***/function (module, exports) {

      module.exports = {
        service_host: 'service.tvg.com',
        google: {
          gtmId: 'KTDSBG',
          gaId: 'UA-8156856-2'
        }
      };

      /***/
    },
    /* 12 */
    /***/function (module, exports) {

      module.exports = {
        service_host: 'service-qa.tvg.com',
        google: {
          gtmId: 'N86C6P',
          gaId: 'UA-8156856-12'
        }
      };

      /***/
    },
    /* 13 */
    /***/function (module, exports) {

      module.exports = {
        service_host: 'service-staging.tvg.com',
        google: {
          gtmId: 'NC8JMM',
          gaId: 'UA-8156856-11'
        }
      };

      /***/
    },
    /* 14 */
    /***/function (module, exports) {

      module.exports = __WEBPACK_EXTERNAL_MODULE_14__;

      /***/
    },
    /* 15 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";

      Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_0_lodash_get__ = __webpack_require__(16);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_0_lodash_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_get__);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_1__brand__ = __webpack_require__(59);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_2__environment__ = __webpack_require__(60);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_2__environment___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__environment__);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_3__content__ = __webpack_require__(62);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_4__device__ = __webpack_require__(78);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_5__product__ = __webpack_require__(79);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_6__mediator_actions__ = __webpack_require__(80);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_7__features__ = __webpack_require__(81);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_8__messages__ = __webpack_require__(82);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_9__metadata__ = __webpack_require__(83);

      /* harmony default export */__webpack_exports__["default"] = function (hostname) {
        if (!hostname && typeof window !== 'undefined' && window.location) {
          hostname = window.location.hostname;
        }

        var brand = Object(__WEBPACK_IMPORTED_MODULE_1__brand__["a" /* default */])(hostname);
        var environment = __WEBPACK_IMPORTED_MODULE_2__environment___default()(hostname);
        var device = Object(__WEBPACK_IMPORTED_MODULE_4__device__["a" /* default */])();
        var product = Object(__WEBPACK_IMPORTED_MODULE_5__product__["a" /* default */])();
        var features = __WEBPACK_IMPORTED_MODULE_7__features__["a" /* default */].readFeatures();
        var messages = __WEBPACK_IMPORTED_MODULE_8__messages__["a" /* default */].readMessages();
        var metadata = Object(__WEBPACK_IMPORTED_MODULE_9__metadata__["a" /* default */])();
        var configs = Object(__WEBPACK_IMPORTED_MODULE_3__content__["a" /* default */])(environment)[brand];

        return {
          brand: brand,
          device: device,
          environment: environment,
          product: product,
          features: features,
          messages: messages,
          metadata: metadata,
          context: function context() {
            var productContext = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : product;
            return productContext + '-' + brand;
          },
          config: function config(configPath) {
            return configPath ? __WEBPACK_IMPORTED_MODULE_0_lodash_get___default()(configs, configPath) : configs;
          },
          getFeatures: function getFeatures() {
            var device = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'desktop';
            var serverSide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

            return __WEBPACK_IMPORTED_MODULE_7__features__["a" /* default */].getFeatures(configs.service, product, device, brand, serverSide);
          },
          getMessages: function getMessages(namespaces) {
            var serverSide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

            return __WEBPACK_IMPORTED_MODULE_8__messages__["a" /* default */].getMessages(namespaces, configs.service, product, device, brand, serverSide);
          },
          mediatorActions: __WEBPACK_IMPORTED_MODULE_6__mediator_actions__["a" /* default */]
        };
      };

      /***/
    },
    /* 16 */
    /***/function (module, exports, __webpack_require__) {

      var baseGet = __webpack_require__(17);

      /**
       * Gets the value at `path` of `object`. If the resolved value is
       * `undefined`, the `defaultValue` is returned in its place.
       *
       * @static
       * @memberOf _
       * @since 3.7.0
       * @category Object
       * @param {Object} object The object to query.
       * @param {Array|string} path The path of the property to get.
       * @param {*} [defaultValue] The value returned for `undefined` resolved values.
       * @returns {*} Returns the resolved value.
       * @example
       *
       * var object = { 'a': [{ 'b': { 'c': 3 } }] };
       *
       * _.get(object, 'a[0].b.c');
       * // => 3
       *
       * _.get(object, ['a', '0', 'b', 'c']);
       * // => 3
       *
       * _.get(object, 'a.b.c', 'default');
       * // => 'default'
       */
      function get(object, path, defaultValue) {
        var result = object == null ? undefined : baseGet(object, path);
        return result === undefined ? defaultValue : result;
      }

      module.exports = get;

      /***/
    },
    /* 17 */
    /***/function (module, exports, __webpack_require__) {

      var castPath = __webpack_require__(18),
          toKey = __webpack_require__(58);

      /**
       * The base implementation of `_.get` without support for default values.
       *
       * @private
       * @param {Object} object The object to query.
       * @param {Array|string} path The path of the property to get.
       * @returns {*} Returns the resolved value.
       */
      function baseGet(object, path) {
        path = castPath(path, object);

        var index = 0,
            length = path.length;

        while (object != null && index < length) {
          object = object[toKey(path[index++])];
        }
        return index && index == length ? object : undefined;
      }

      module.exports = baseGet;

      /***/
    },
    /* 18 */
    /***/function (module, exports, __webpack_require__) {

      var isArray = __webpack_require__(3),
          isKey = __webpack_require__(19),
          stringToPath = __webpack_require__(25),
          toString = __webpack_require__(55);

      /**
       * Casts `value` to a path array if it's not one.
       *
       * @private
       * @param {*} value The value to inspect.
       * @param {Object} [object] The object to query keys on.
       * @returns {Array} Returns the cast property path array.
       */
      function castPath(value, object) {
        if (isArray(value)) {
          return value;
        }
        return isKey(value, object) ? [value] : stringToPath(toString(value));
      }

      module.exports = castPath;

      /***/
    },
    /* 19 */
    /***/function (module, exports, __webpack_require__) {

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      var isArray = __webpack_require__(3),
          isSymbol = __webpack_require__(4);

      /** Used to match property names within property paths. */
      var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
          reIsPlainProp = /^\w*$/;

      /**
       * Checks if `value` is a property name and not a property path.
       *
       * @private
       * @param {*} value The value to check.
       * @param {Object} [object] The object to query keys on.
       * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
       */
      function isKey(value, object) {
        if (isArray(value)) {
          return false;
        }
        var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
        if (type == 'number' || type == 'symbol' || type == 'boolean' || value == null || isSymbol(value)) {
          return true;
        }
        return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
      }

      module.exports = isKey;

      /***/
    },
    /* 20 */
    /***/function (module, exports, __webpack_require__) {

      /* WEBPACK VAR INJECTION */(function (global) {
        var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
          return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
        } : function (obj) {
          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
        };

        /** Detect free variable `global` from Node.js. */
        var freeGlobal = (typeof global === 'undefined' ? 'undefined' : _typeof(global)) == 'object' && global && global.Object === Object && global;

        module.exports = freeGlobal;
        /* WEBPACK VAR INJECTION */
      }).call(exports, __webpack_require__(21));

      /***/
    },
    /* 21 */
    /***/function (module, exports) {

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      var g;

      // This works in non-strict mode
      g = function () {
        return this;
      }();

      try {
        // This works if eval is allowed (see CSP)
        g = g || Function("return this")() || (1, eval)("this");
      } catch (e) {
        // This works if the window reference is available
        if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === "object") g = window;
      }

      // g can still be undefined, but nothing to do about it...
      // We return undefined, instead of nothing here, so it's
      // easier to handle this case. if(!global) { ...}

      module.exports = g;

      /***/
    },
    /* 22 */
    /***/function (module, exports, __webpack_require__) {

      var _Symbol = __webpack_require__(5);

      /** Used for built-in method references. */
      var objectProto = Object.prototype;

      /** Used to check objects for own properties. */
      var hasOwnProperty = objectProto.hasOwnProperty;

      /**
       * Used to resolve the
       * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
       * of values.
       */
      var nativeObjectToString = objectProto.toString;

      /** Built-in value references. */
      var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;

      /**
       * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
       *
       * @private
       * @param {*} value The value to query.
       * @returns {string} Returns the raw `toStringTag`.
       */
      function getRawTag(value) {
        var isOwn = hasOwnProperty.call(value, symToStringTag),
            tag = value[symToStringTag];

        try {
          value[symToStringTag] = undefined;
          var unmasked = true;
        } catch (e) {}

        var result = nativeObjectToString.call(value);
        if (unmasked) {
          if (isOwn) {
            value[symToStringTag] = tag;
          } else {
            delete value[symToStringTag];
          }
        }
        return result;
      }

      module.exports = getRawTag;

      /***/
    },
    /* 23 */
    /***/function (module, exports) {

      /** Used for built-in method references. */
      var objectProto = Object.prototype;

      /**
       * Used to resolve the
       * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
       * of values.
       */
      var nativeObjectToString = objectProto.toString;

      /**
       * Converts `value` to a string using `Object.prototype.toString`.
       *
       * @private
       * @param {*} value The value to convert.
       * @returns {string} Returns the converted string.
       */
      function objectToString(value) {
        return nativeObjectToString.call(value);
      }

      module.exports = objectToString;

      /***/
    },
    /* 24 */
    /***/function (module, exports) {

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      /**
       * Checks if `value` is object-like. A value is object-like if it's not `null`
       * and has a `typeof` result of "object".
       *
       * @static
       * @memberOf _
       * @since 4.0.0
       * @category Lang
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
       * @example
       *
       * _.isObjectLike({});
       * // => true
       *
       * _.isObjectLike([1, 2, 3]);
       * // => true
       *
       * _.isObjectLike(_.noop);
       * // => false
       *
       * _.isObjectLike(null);
       * // => false
       */
      function isObjectLike(value) {
        return value != null && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'object';
      }

      module.exports = isObjectLike;

      /***/
    },
    /* 25 */
    /***/function (module, exports, __webpack_require__) {

      var memoizeCapped = __webpack_require__(26);

      /** Used to match property names within property paths. */
      var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

      /** Used to match backslashes in property paths. */
      var reEscapeChar = /\\(\\)?/g;

      /**
       * Converts `string` to a property path array.
       *
       * @private
       * @param {string} string The string to convert.
       * @returns {Array} Returns the property path array.
       */
      var stringToPath = memoizeCapped(function (string) {
        var result = [];
        if (string.charCodeAt(0) === 46 /* . */) {
            result.push('');
          }
        string.replace(rePropName, function (match, number, quote, subString) {
          result.push(quote ? subString.replace(reEscapeChar, '$1') : number || match);
        });
        return result;
      });

      module.exports = stringToPath;

      /***/
    },
    /* 26 */
    /***/function (module, exports, __webpack_require__) {

      var memoize = __webpack_require__(27);

      /** Used as the maximum memoize cache size. */
      var MAX_MEMOIZE_SIZE = 500;

      /**
       * A specialized version of `_.memoize` which clears the memoized function's
       * cache when it exceeds `MAX_MEMOIZE_SIZE`.
       *
       * @private
       * @param {Function} func The function to have its output memoized.
       * @returns {Function} Returns the new memoized function.
       */
      function memoizeCapped(func) {
        var result = memoize(func, function (key) {
          if (cache.size === MAX_MEMOIZE_SIZE) {
            cache.clear();
          }
          return key;
        });

        var cache = result.cache;
        return result;
      }

      module.exports = memoizeCapped;

      /***/
    },
    /* 27 */
    /***/function (module, exports, __webpack_require__) {

      var MapCache = __webpack_require__(28);

      /** Error message constants. */
      var FUNC_ERROR_TEXT = 'Expected a function';

      /**
       * Creates a function that memoizes the result of `func`. If `resolver` is
       * provided, it determines the cache key for storing the result based on the
       * arguments provided to the memoized function. By default, the first argument
       * provided to the memoized function is used as the map cache key. The `func`
       * is invoked with the `this` binding of the memoized function.
       *
       * **Note:** The cache is exposed as the `cache` property on the memoized
       * function. Its creation may be customized by replacing the `_.memoize.Cache`
       * constructor with one whose instances implement the
       * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
       * method interface of `clear`, `delete`, `get`, `has`, and `set`.
       *
       * @static
       * @memberOf _
       * @since 0.1.0
       * @category Function
       * @param {Function} func The function to have its output memoized.
       * @param {Function} [resolver] The function to resolve the cache key.
       * @returns {Function} Returns the new memoized function.
       * @example
       *
       * var object = { 'a': 1, 'b': 2 };
       * var other = { 'c': 3, 'd': 4 };
       *
       * var values = _.memoize(_.values);
       * values(object);
       * // => [1, 2]
       *
       * values(other);
       * // => [3, 4]
       *
       * object.a = 2;
       * values(object);
       * // => [1, 2]
       *
       * // Modify the result cache.
       * values.cache.set(object, ['a', 'b']);
       * values(object);
       * // => ['a', 'b']
       *
       * // Replace `_.memoize.Cache`.
       * _.memoize.Cache = WeakMap;
       */
      function memoize(func, resolver) {
        if (typeof func != 'function' || resolver != null && typeof resolver != 'function') {
          throw new TypeError(FUNC_ERROR_TEXT);
        }
        var memoized = function memoized() {
          var args = arguments,
              key = resolver ? resolver.apply(this, args) : args[0],
              cache = memoized.cache;

          if (cache.has(key)) {
            return cache.get(key);
          }
          var result = func.apply(this, args);
          memoized.cache = cache.set(key, result) || cache;
          return result;
        };
        memoized.cache = new (memoize.Cache || MapCache)();
        return memoized;
      }

      // Expose `MapCache`.
      memoize.Cache = MapCache;

      module.exports = memoize;

      /***/
    },
    /* 28 */
    /***/function (module, exports, __webpack_require__) {

      var mapCacheClear = __webpack_require__(29),
          mapCacheDelete = __webpack_require__(50),
          mapCacheGet = __webpack_require__(52),
          mapCacheHas = __webpack_require__(53),
          mapCacheSet = __webpack_require__(54);

      /**
       * Creates a map cache object to store key-value pairs.
       *
       * @private
       * @constructor
       * @param {Array} [entries] The key-value pairs to cache.
       */
      function MapCache(entries) {
        var index = -1,
            length = entries == null ? 0 : entries.length;

        this.clear();
        while (++index < length) {
          var entry = entries[index];
          this.set(entry[0], entry[1]);
        }
      }

      // Add methods to `MapCache`.
      MapCache.prototype.clear = mapCacheClear;
      MapCache.prototype['delete'] = mapCacheDelete;
      MapCache.prototype.get = mapCacheGet;
      MapCache.prototype.has = mapCacheHas;
      MapCache.prototype.set = mapCacheSet;

      module.exports = MapCache;

      /***/
    },
    /* 29 */
    /***/function (module, exports, __webpack_require__) {

      var Hash = __webpack_require__(30),
          ListCache = __webpack_require__(42),
          Map = __webpack_require__(49);

      /**
       * Removes all key-value entries from the map.
       *
       * @private
       * @name clear
       * @memberOf MapCache
       */
      function mapCacheClear() {
        this.size = 0;
        this.__data__ = {
          'hash': new Hash(),
          'map': new (Map || ListCache)(),
          'string': new Hash()
        };
      }

      module.exports = mapCacheClear;

      /***/
    },
    /* 30 */
    /***/function (module, exports, __webpack_require__) {

      var hashClear = __webpack_require__(31),
          hashDelete = __webpack_require__(38),
          hashGet = __webpack_require__(39),
          hashHas = __webpack_require__(40),
          hashSet = __webpack_require__(41);

      /**
       * Creates a hash object.
       *
       * @private
       * @constructor
       * @param {Array} [entries] The key-value pairs to cache.
       */
      function Hash(entries) {
        var index = -1,
            length = entries == null ? 0 : entries.length;

        this.clear();
        while (++index < length) {
          var entry = entries[index];
          this.set(entry[0], entry[1]);
        }
      }

      // Add methods to `Hash`.
      Hash.prototype.clear = hashClear;
      Hash.prototype['delete'] = hashDelete;
      Hash.prototype.get = hashGet;
      Hash.prototype.has = hashHas;
      Hash.prototype.set = hashSet;

      module.exports = Hash;

      /***/
    },
    /* 31 */
    /***/function (module, exports, __webpack_require__) {

      var nativeCreate = __webpack_require__(0);

      /**
       * Removes all key-value entries from the hash.
       *
       * @private
       * @name clear
       * @memberOf Hash
       */
      function hashClear() {
        this.__data__ = nativeCreate ? nativeCreate(null) : {};
        this.size = 0;
      }

      module.exports = hashClear;

      /***/
    },
    /* 32 */
    /***/function (module, exports, __webpack_require__) {

      var isFunction = __webpack_require__(33),
          isMasked = __webpack_require__(34),
          isObject = __webpack_require__(9),
          toSource = __webpack_require__(36);

      /**
       * Used to match `RegExp`
       * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
       */
      var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

      /** Used to detect host constructors (Safari). */
      var reIsHostCtor = /^\[object .+?Constructor\]$/;

      /** Used for built-in method references. */
      var funcProto = Function.prototype,
          objectProto = Object.prototype;

      /** Used to resolve the decompiled source of functions. */
      var funcToString = funcProto.toString;

      /** Used to check objects for own properties. */
      var hasOwnProperty = objectProto.hasOwnProperty;

      /** Used to detect if a method is native. */
      var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');

      /**
       * The base implementation of `_.isNative` without bad shim checks.
       *
       * @private
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is a native function,
       *  else `false`.
       */
      function baseIsNative(value) {
        if (!isObject(value) || isMasked(value)) {
          return false;
        }
        var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
        return pattern.test(toSource(value));
      }

      module.exports = baseIsNative;

      /***/
    },
    /* 33 */
    /***/function (module, exports, __webpack_require__) {

      var baseGetTag = __webpack_require__(7),
          isObject = __webpack_require__(9);

      /** `Object#toString` result references. */
      var asyncTag = '[object AsyncFunction]',
          funcTag = '[object Function]',
          genTag = '[object GeneratorFunction]',
          proxyTag = '[object Proxy]';

      /**
       * Checks if `value` is classified as a `Function` object.
       *
       * @static
       * @memberOf _
       * @since 0.1.0
       * @category Lang
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is a function, else `false`.
       * @example
       *
       * _.isFunction(_);
       * // => true
       *
       * _.isFunction(/abc/);
       * // => false
       */
      function isFunction(value) {
        if (!isObject(value)) {
          return false;
        }
        // The use of `Object#toString` avoids issues with the `typeof` operator
        // in Safari 9 which returns 'object' for typed arrays and other constructors.
        var tag = baseGetTag(value);
        return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
      }

      module.exports = isFunction;

      /***/
    },
    /* 34 */
    /***/function (module, exports, __webpack_require__) {

      var coreJsData = __webpack_require__(35);

      /** Used to detect methods masquerading as native. */
      var maskSrcKey = function () {
        var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
        return uid ? 'Symbol(src)_1.' + uid : '';
      }();

      /**
       * Checks if `func` has its source masked.
       *
       * @private
       * @param {Function} func The function to check.
       * @returns {boolean} Returns `true` if `func` is masked, else `false`.
       */
      function isMasked(func) {
        return !!maskSrcKey && maskSrcKey in func;
      }

      module.exports = isMasked;

      /***/
    },
    /* 35 */
    /***/function (module, exports, __webpack_require__) {

      var root = __webpack_require__(6);

      /** Used to detect overreaching core-js shims. */
      var coreJsData = root['__core-js_shared__'];

      module.exports = coreJsData;

      /***/
    },
    /* 36 */
    /***/function (module, exports) {

      /** Used for built-in method references. */
      var funcProto = Function.prototype;

      /** Used to resolve the decompiled source of functions. */
      var funcToString = funcProto.toString;

      /**
       * Converts `func` to its source code.
       *
       * @private
       * @param {Function} func The function to convert.
       * @returns {string} Returns the source code.
       */
      function toSource(func) {
        if (func != null) {
          try {
            return funcToString.call(func);
          } catch (e) {}
          try {
            return func + '';
          } catch (e) {}
        }
        return '';
      }

      module.exports = toSource;

      /***/
    },
    /* 37 */
    /***/function (module, exports) {

      /**
       * Gets the value at `key` of `object`.
       *
       * @private
       * @param {Object} [object] The object to query.
       * @param {string} key The key of the property to get.
       * @returns {*} Returns the property value.
       */
      function getValue(object, key) {
        return object == null ? undefined : object[key];
      }

      module.exports = getValue;

      /***/
    },
    /* 38 */
    /***/function (module, exports) {

      /**
       * Removes `key` and its value from the hash.
       *
       * @private
       * @name delete
       * @memberOf Hash
       * @param {Object} hash The hash to modify.
       * @param {string} key The key of the value to remove.
       * @returns {boolean} Returns `true` if the entry was removed, else `false`.
       */
      function hashDelete(key) {
        var result = this.has(key) && delete this.__data__[key];
        this.size -= result ? 1 : 0;
        return result;
      }

      module.exports = hashDelete;

      /***/
    },
    /* 39 */
    /***/function (module, exports, __webpack_require__) {

      var nativeCreate = __webpack_require__(0);

      /** Used to stand-in for `undefined` hash values. */
      var HASH_UNDEFINED = '__lodash_hash_undefined__';

      /** Used for built-in method references. */
      var objectProto = Object.prototype;

      /** Used to check objects for own properties. */
      var hasOwnProperty = objectProto.hasOwnProperty;

      /**
       * Gets the hash value for `key`.
       *
       * @private
       * @name get
       * @memberOf Hash
       * @param {string} key The key of the value to get.
       * @returns {*} Returns the entry value.
       */
      function hashGet(key) {
        var data = this.__data__;
        if (nativeCreate) {
          var result = data[key];
          return result === HASH_UNDEFINED ? undefined : result;
        }
        return hasOwnProperty.call(data, key) ? data[key] : undefined;
      }

      module.exports = hashGet;

      /***/
    },
    /* 40 */
    /***/function (module, exports, __webpack_require__) {

      var nativeCreate = __webpack_require__(0);

      /** Used for built-in method references. */
      var objectProto = Object.prototype;

      /** Used to check objects for own properties. */
      var hasOwnProperty = objectProto.hasOwnProperty;

      /**
       * Checks if a hash value for `key` exists.
       *
       * @private
       * @name has
       * @memberOf Hash
       * @param {string} key The key of the entry to check.
       * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
       */
      function hashHas(key) {
        var data = this.__data__;
        return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
      }

      module.exports = hashHas;

      /***/
    },
    /* 41 */
    /***/function (module, exports, __webpack_require__) {

      var nativeCreate = __webpack_require__(0);

      /** Used to stand-in for `undefined` hash values. */
      var HASH_UNDEFINED = '__lodash_hash_undefined__';

      /**
       * Sets the hash `key` to `value`.
       *
       * @private
       * @name set
       * @memberOf Hash
       * @param {string} key The key of the value to set.
       * @param {*} value The value to set.
       * @returns {Object} Returns the hash instance.
       */
      function hashSet(key, value) {
        var data = this.__data__;
        this.size += this.has(key) ? 0 : 1;
        data[key] = nativeCreate && value === undefined ? HASH_UNDEFINED : value;
        return this;
      }

      module.exports = hashSet;

      /***/
    },
    /* 42 */
    /***/function (module, exports, __webpack_require__) {

      var listCacheClear = __webpack_require__(43),
          listCacheDelete = __webpack_require__(44),
          listCacheGet = __webpack_require__(46),
          listCacheHas = __webpack_require__(47),
          listCacheSet = __webpack_require__(48);

      /**
       * Creates an list cache object.
       *
       * @private
       * @constructor
       * @param {Array} [entries] The key-value pairs to cache.
       */
      function ListCache(entries) {
        var index = -1,
            length = entries == null ? 0 : entries.length;

        this.clear();
        while (++index < length) {
          var entry = entries[index];
          this.set(entry[0], entry[1]);
        }
      }

      // Add methods to `ListCache`.
      ListCache.prototype.clear = listCacheClear;
      ListCache.prototype['delete'] = listCacheDelete;
      ListCache.prototype.get = listCacheGet;
      ListCache.prototype.has = listCacheHas;
      ListCache.prototype.set = listCacheSet;

      module.exports = ListCache;

      /***/
    },
    /* 43 */
    /***/function (module, exports) {

      /**
       * Removes all key-value entries from the list cache.
       *
       * @private
       * @name clear
       * @memberOf ListCache
       */
      function listCacheClear() {
        this.__data__ = [];
        this.size = 0;
      }

      module.exports = listCacheClear;

      /***/
    },
    /* 44 */
    /***/function (module, exports, __webpack_require__) {

      var assocIndexOf = __webpack_require__(1);

      /** Used for built-in method references. */
      var arrayProto = Array.prototype;

      /** Built-in value references. */
      var splice = arrayProto.splice;

      /**
       * Removes `key` and its value from the list cache.
       *
       * @private
       * @name delete
       * @memberOf ListCache
       * @param {string} key The key of the value to remove.
       * @returns {boolean} Returns `true` if the entry was removed, else `false`.
       */
      function listCacheDelete(key) {
        var data = this.__data__,
            index = assocIndexOf(data, key);

        if (index < 0) {
          return false;
        }
        var lastIndex = data.length - 1;
        if (index == lastIndex) {
          data.pop();
        } else {
          splice.call(data, index, 1);
        }
        --this.size;
        return true;
      }

      module.exports = listCacheDelete;

      /***/
    },
    /* 45 */
    /***/function (module, exports) {

      /**
       * Performs a
       * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
       * comparison between two values to determine if they are equivalent.
       *
       * @static
       * @memberOf _
       * @since 4.0.0
       * @category Lang
       * @param {*} value The value to compare.
       * @param {*} other The other value to compare.
       * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
       * @example
       *
       * var object = { 'a': 1 };
       * var other = { 'a': 1 };
       *
       * _.eq(object, object);
       * // => true
       *
       * _.eq(object, other);
       * // => false
       *
       * _.eq('a', 'a');
       * // => true
       *
       * _.eq('a', Object('a'));
       * // => false
       *
       * _.eq(NaN, NaN);
       * // => true
       */
      function eq(value, other) {
        return value === other || value !== value && other !== other;
      }

      module.exports = eq;

      /***/
    },
    /* 46 */
    /***/function (module, exports, __webpack_require__) {

      var assocIndexOf = __webpack_require__(1);

      /**
       * Gets the list cache value for `key`.
       *
       * @private
       * @name get
       * @memberOf ListCache
       * @param {string} key The key of the value to get.
       * @returns {*} Returns the entry value.
       */
      function listCacheGet(key) {
        var data = this.__data__,
            index = assocIndexOf(data, key);

        return index < 0 ? undefined : data[index][1];
      }

      module.exports = listCacheGet;

      /***/
    },
    /* 47 */
    /***/function (module, exports, __webpack_require__) {

      var assocIndexOf = __webpack_require__(1);

      /**
       * Checks if a list cache value for `key` exists.
       *
       * @private
       * @name has
       * @memberOf ListCache
       * @param {string} key The key of the entry to check.
       * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
       */
      function listCacheHas(key) {
        return assocIndexOf(this.__data__, key) > -1;
      }

      module.exports = listCacheHas;

      /***/
    },
    /* 48 */
    /***/function (module, exports, __webpack_require__) {

      var assocIndexOf = __webpack_require__(1);

      /**
       * Sets the list cache `key` to `value`.
       *
       * @private
       * @name set
       * @memberOf ListCache
       * @param {string} key The key of the value to set.
       * @param {*} value The value to set.
       * @returns {Object} Returns the list cache instance.
       */
      function listCacheSet(key, value) {
        var data = this.__data__,
            index = assocIndexOf(data, key);

        if (index < 0) {
          ++this.size;
          data.push([key, value]);
        } else {
          data[index][1] = value;
        }
        return this;
      }

      module.exports = listCacheSet;

      /***/
    },
    /* 49 */
    /***/function (module, exports, __webpack_require__) {

      var getNative = __webpack_require__(8),
          root = __webpack_require__(6);

      /* Built-in method references that are verified to be native. */
      var Map = getNative(root, 'Map');

      module.exports = Map;

      /***/
    },
    /* 50 */
    /***/function (module, exports, __webpack_require__) {

      var getMapData = __webpack_require__(2);

      /**
       * Removes `key` and its value from the map.
       *
       * @private
       * @name delete
       * @memberOf MapCache
       * @param {string} key The key of the value to remove.
       * @returns {boolean} Returns `true` if the entry was removed, else `false`.
       */
      function mapCacheDelete(key) {
        var result = getMapData(this, key)['delete'](key);
        this.size -= result ? 1 : 0;
        return result;
      }

      module.exports = mapCacheDelete;

      /***/
    },
    /* 51 */
    /***/function (module, exports) {

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      /**
       * Checks if `value` is suitable for use as unique object key.
       *
       * @private
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
       */
      function isKeyable(value) {
        var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
        return type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean' ? value !== '__proto__' : value === null;
      }

      module.exports = isKeyable;

      /***/
    },
    /* 52 */
    /***/function (module, exports, __webpack_require__) {

      var getMapData = __webpack_require__(2);

      /**
       * Gets the map value for `key`.
       *
       * @private
       * @name get
       * @memberOf MapCache
       * @param {string} key The key of the value to get.
       * @returns {*} Returns the entry value.
       */
      function mapCacheGet(key) {
        return getMapData(this, key).get(key);
      }

      module.exports = mapCacheGet;

      /***/
    },
    /* 53 */
    /***/function (module, exports, __webpack_require__) {

      var getMapData = __webpack_require__(2);

      /**
       * Checks if a map value for `key` exists.
       *
       * @private
       * @name has
       * @memberOf MapCache
       * @param {string} key The key of the entry to check.
       * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
       */
      function mapCacheHas(key) {
        return getMapData(this, key).has(key);
      }

      module.exports = mapCacheHas;

      /***/
    },
    /* 54 */
    /***/function (module, exports, __webpack_require__) {

      var getMapData = __webpack_require__(2);

      /**
       * Sets the map `key` to `value`.
       *
       * @private
       * @name set
       * @memberOf MapCache
       * @param {string} key The key of the value to set.
       * @param {*} value The value to set.
       * @returns {Object} Returns the map cache instance.
       */
      function mapCacheSet(key, value) {
        var data = getMapData(this, key),
            size = data.size;

        data.set(key, value);
        this.size += data.size == size ? 0 : 1;
        return this;
      }

      module.exports = mapCacheSet;

      /***/
    },
    /* 55 */
    /***/function (module, exports, __webpack_require__) {

      var baseToString = __webpack_require__(56);

      /**
       * Converts `value` to a string. An empty string is returned for `null`
       * and `undefined` values. The sign of `-0` is preserved.
       *
       * @static
       * @memberOf _
       * @since 4.0.0
       * @category Lang
       * @param {*} value The value to convert.
       * @returns {string} Returns the converted string.
       * @example
       *
       * _.toString(null);
       * // => ''
       *
       * _.toString(-0);
       * // => '-0'
       *
       * _.toString([1, 2, 3]);
       * // => '1,2,3'
       */
      function toString(value) {
        return value == null ? '' : baseToString(value);
      }

      module.exports = toString;

      /***/
    },
    /* 56 */
    /***/function (module, exports, __webpack_require__) {

      var _Symbol = __webpack_require__(5),
          arrayMap = __webpack_require__(57),
          isArray = __webpack_require__(3),
          isSymbol = __webpack_require__(4);

      /** Used as references for various `Number` constants. */
      var INFINITY = 1 / 0;

      /** Used to convert symbols to primitives and strings. */
      var symbolProto = _Symbol ? _Symbol.prototype : undefined,
          symbolToString = symbolProto ? symbolProto.toString : undefined;

      /**
       * The base implementation of `_.toString` which doesn't convert nullish
       * values to empty strings.
       *
       * @private
       * @param {*} value The value to process.
       * @returns {string} Returns the string.
       */
      function baseToString(value) {
        // Exit early for strings to avoid a performance hit in some environments.
        if (typeof value == 'string') {
          return value;
        }
        if (isArray(value)) {
          // Recursively convert values (susceptible to call stack limits).
          return arrayMap(value, baseToString) + '';
        }
        if (isSymbol(value)) {
          return symbolToString ? symbolToString.call(value) : '';
        }
        var result = value + '';
        return result == '0' && 1 / value == -INFINITY ? '-0' : result;
      }

      module.exports = baseToString;

      /***/
    },
    /* 57 */
    /***/function (module, exports) {

      /**
       * A specialized version of `_.map` for arrays without support for iteratee
       * shorthands.
       *
       * @private
       * @param {Array} [array] The array to iterate over.
       * @param {Function} iteratee The function invoked per iteration.
       * @returns {Array} Returns the new mapped array.
       */
      function arrayMap(array, iteratee) {
        var index = -1,
            length = array == null ? 0 : array.length,
            result = Array(length);

        while (++index < length) {
          result[index] = iteratee(array[index], index, array);
        }
        return result;
      }

      module.exports = arrayMap;

      /***/
    },
    /* 58 */
    /***/function (module, exports, __webpack_require__) {

      var isSymbol = __webpack_require__(4);

      /** Used as references for various `Number` constants. */
      var INFINITY = 1 / 0;

      /**
       * Converts `value` to a string key if it's not a string or symbol.
       *
       * @private
       * @param {*} value The value to inspect.
       * @returns {string|symbol} Returns the key.
       */
      function toKey(value) {
        if (typeof value == 'string' || isSymbol(value)) {
          return value;
        }
        var result = value + '';
        return result == '0' && 1 / value == -INFINITY ? '-0' : result;
      }

      module.exports = toKey;

      /***/
    },
    /* 59 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";

      /* harmony default export */
      __webpack_exports__["a"] = function (hostname) {
        if (hostname) {
          if (/(nj|4njbets)(\.|-)/gi.test(hostname)) {
            return '4njbets';
          }
          if (/(pa|pabets)(\.|-)/gi.test(hostname)) {
            return 'pabets';
          }
          if (/ia(\.|-)/gi.test(hostname)) {
            return 'iowa';
          }
        }
        return 'tvg';
      };

      /***/
    },
    /* 60 */
    /***/function (module, exports, __webpack_require__) {

      /* WEBPACK VAR INJECTION */(function (process) {

        var isBrowser = function isBrowser() {
          return typeof window !== 'undefined' && !!window.__TVG_GLOBALS__;
        };

        var getEnvironmentByHostname = function getEnvironmentByHostname(hostname) {
          var defaultEnv = 'production';

          if (!hostname) {
            return defaultEnv;
          }

          if (/(stage\.|staging\.)/gi.test(hostname)) {
            return 'staging';
          }

          if (/qa\.|dev\./gi.test(hostname)) {
            return 'qa';
          }

          return defaultEnv;
        };

        var getEnvironmentInBrowser = function getEnvironmentInBrowser() {
          return typeof window !== 'undefined' && !!window.__TVG_GLOBALS__ && !!window.__TVG_GLOBALS__.ENVIRONMENT && window.__TVG_GLOBALS__.ENVIRONMENT;
        };

        var getEnvironmentInServer = function getEnvironmentInServer() {
          return typeof process.env.ENVIRONMENT === 'string' && process.env.ENVIRONMENT;
        };

        /**
         * When fetching an environment two variables have priority:
         *  - in the browser, node-grid should inject a global variable `__TVG_GLOBALS__.ENVIRONMENT`
         *  - in the server, the container has the variable ENVIRONMENT
         * These two variables allows to be deterministic about the environment, and only
         * if by some unknown reason they fail, then we check the hostname as a last resourt
         */
        module.exports = function (hostname) {
          return (isBrowser() ? getEnvironmentInBrowser() : getEnvironmentInServer()) || getEnvironmentByHostname(hostname);
        };
        /* WEBPACK VAR INJECTION */
      }).call(exports, __webpack_require__(61));

      /***/
    },
    /* 61 */
    /***/function (module, exports) {

      // shim for using process in browser
      var process = module.exports = {};

      // cached from whatever global is present so that test runners that stub it
      // don't break things.  But we need to wrap it in a try catch in case it is
      // wrapped in strict mode code which doesn't define any globals.  It's inside a
      // function because try/catches deoptimize in certain engines.

      var cachedSetTimeout;
      var cachedClearTimeout;

      function defaultSetTimout() {
        throw new Error('setTimeout has not been defined');
      }
      function defaultClearTimeout() {
        throw new Error('clearTimeout has not been defined');
      }
      (function () {
        try {
          if (typeof setTimeout === 'function') {
            cachedSetTimeout = setTimeout;
          } else {
            cachedSetTimeout = defaultSetTimout;
          }
        } catch (e) {
          cachedSetTimeout = defaultSetTimout;
        }
        try {
          if (typeof clearTimeout === 'function') {
            cachedClearTimeout = clearTimeout;
          } else {
            cachedClearTimeout = defaultClearTimeout;
          }
        } catch (e) {
          cachedClearTimeout = defaultClearTimeout;
        }
      })();
      function runTimeout(fun) {
        if (cachedSetTimeout === setTimeout) {
          //normal enviroments in sane situations
          return setTimeout(fun, 0);
        }
        // if setTimeout wasn't available but was latter defined
        if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
          cachedSetTimeout = setTimeout;
          return setTimeout(fun, 0);
        }
        try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedSetTimeout(fun, 0);
        } catch (e) {
          try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
            return cachedSetTimeout.call(null, fun, 0);
          } catch (e) {
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
            return cachedSetTimeout.call(this, fun, 0);
          }
        }
      }
      function runClearTimeout(marker) {
        if (cachedClearTimeout === clearTimeout) {
          //normal enviroments in sane situations
          return clearTimeout(marker);
        }
        // if clearTimeout wasn't available but was latter defined
        if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
          cachedClearTimeout = clearTimeout;
          return clearTimeout(marker);
        }
        try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedClearTimeout(marker);
        } catch (e) {
          try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
            return cachedClearTimeout.call(null, marker);
          } catch (e) {
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
            return cachedClearTimeout.call(this, marker);
          }
        }
      }
      var queue = [];
      var draining = false;
      var currentQueue;
      var queueIndex = -1;

      function cleanUpNextTick() {
        if (!draining || !currentQueue) {
          return;
        }
        draining = false;
        if (currentQueue.length) {
          queue = currentQueue.concat(queue);
        } else {
          queueIndex = -1;
        }
        if (queue.length) {
          drainQueue();
        }
      }

      function drainQueue() {
        if (draining) {
          return;
        }
        var timeout = runTimeout(cleanUpNextTick);
        draining = true;

        var len = queue.length;
        while (len) {
          currentQueue = queue;
          queue = [];
          while (++queueIndex < len) {
            if (currentQueue) {
              currentQueue[queueIndex].run();
            }
          }
          queueIndex = -1;
          len = queue.length;
        }
        currentQueue = null;
        draining = false;
        runClearTimeout(timeout);
      }

      process.nextTick = function (fun) {
        var args = new Array(arguments.length - 1);
        if (arguments.length > 1) {
          for (var i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i];
          }
        }
        queue.push(new Item(fun, args));
        if (queue.length === 1 && !draining) {
          runTimeout(drainQueue);
        }
      };

      // v8 likes predictible objects
      function Item(fun, array) {
        this.fun = fun;
        this.array = array;
      }
      Item.prototype.run = function () {
        this.fun.apply(null, this.array);
      };
      process.title = 'browser';
      process.browser = true;
      process.env = {};
      process.argv = [];
      process.version = ''; // empty string to avoid regexp issues
      process.versions = {};

      function noop() {}

      process.on = noop;
      process.addListener = noop;
      process.once = noop;
      process.off = noop;
      process.removeListener = noop;
      process.removeAllListeners = noop;
      process.emit = noop;
      process.prependListener = noop;
      process.prependOnceListener = noop;

      process.listeners = function (name) {
        return [];
      };

      process.binding = function (name) {
        throw new Error('process.binding is not supported');
      };

      process.cwd = function () {
        return '/';
      };
      process.chdir = function (dir) {
        throw new Error('process.chdir is not supported');
      };
      process.umask = function () {
        return 0;
      };

      /***/
    },
    /* 62 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";
      /* harmony import */
      var __WEBPACK_IMPORTED_MODULE_0__base_js__ = __webpack_require__(63);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_0__base_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__base_js__);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_1__content_default_js__ = __webpack_require__(10);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_1__content_default_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__content_default_js__);

      /* harmony default export */__webpack_exports__["a"] = function (env) {
        var brands = ['tvg', 'pabets', '4njbets', 'iowa'];

        var confDefault = {
          tvg: __WEBPACK_IMPORTED_MODULE_1__content_default_js___default.a,
          pabets: __WEBPACK_IMPORTED_MODULE_1__content_default_js___default.a,
          iowa: __WEBPACK_IMPORTED_MODULE_1__content_default_js___default.a,
          '4njbets': __WEBPACK_IMPORTED_MODULE_1__content_default_js___default.a
        };
        var content = {
          production: Object.assign({}, confDefault),
          staging: Object.assign({}, confDefault),
          qa: Object.assign({}, confDefault)
        };

        var _loop = function _loop(envName) {
          if (content.hasOwnProperty(envName)) {
            brands.forEach(function (brand) {
              var baseConf = __webpack_require__(64)("./" + envName + '/base.js');
              var brandConf = __webpack_require__(65)("./" + envName + '/' + brand + '.js');
              content[envName][brand] = Object.assign({}, content[envName][brand], baseConf, brandConf);
            });
          }
        };

        for (var envName in content) {
          _loop(envName);
        }

        var config = brands.reduce(function (accumulator, brand) {
          accumulator[brand] = __WEBPACK_IMPORTED_MODULE_0__base_js__["config"](content[env][brand]);
          return accumulator;
        }, {});

        return config;
      };

      /***/
    },
    /* 63 */
    /***/function (module, exports) {

      module.exports = {
        config: function config(envConfig) {
          var serviceHost = typeof window !== 'undefined' ? '//' + envConfig.service_host : 'http://' + envConfig.service_host;
          return {
            service_host: serviceHost,
            service: {
              graph: serviceHost + envConfig.service.graph,
              capi: serviceHost + envConfig.service.capi,
              wtx: serviceHost + envConfig.service.wtx,
              pay: serviceHost + envConfig.service.pay,
              log: serviceHost + envConfig.service.log,
              usa: serviceHost + envConfig.service.usa,
              usa_v1: serviceHost + envConfig.service.usa_v1,
              uam: serviceHost + envConfig.service.uam,
              prf: serviceHost + envConfig.service.prf,
              upr: serviceHost + envConfig.service.upr,
              geo: serviceHost + envConfig.service.geo,
              uwt: serviceHost + envConfig.service.uwt,
              wro: serviceHost + envConfig.service.wro,
              uas: serviceHost + envConfig.service.uas,
              nav: serviceHost + envConfig.service.nav,
              slp: serviceHost + envConfig.service.slp,
              deposit: serviceHost + envConfig.service.deposit,
              ufc: serviceHost + envConfig.service.ufc
            },
            google: {
              gtmId: envConfig.google.gtmId,
              gaId: envConfig.google.gaId
            }
          };
        }
      };

      /***/
    },
    /* 64 */
    /***/function (module, exports, __webpack_require__) {

      var map = {
        "./production/base.js": 11,
        "./qa/base.js": 12,
        "./staging/base.js": 13
      };
      function webpackContext(req) {
        return __webpack_require__(webpackContextResolve(req));
      };
      function webpackContextResolve(req) {
        var id = map[req];
        if (!(id + 1)) // check for number or string
          throw new Error("Cannot find module '" + req + "'.");
        return id;
      };
      webpackContext.keys = function webpackContextKeys() {
        return Object.keys(map);
      };
      webpackContext.resolve = webpackContextResolve;
      module.exports = webpackContext;
      webpackContext.id = 64;

      /***/
    },
    /* 65 */
    /***/function (module, exports, __webpack_require__) {

      var map = {
        "./default.js": 10,
        "./production/4njbets.js": 66,
        "./production/base.js": 11,
        "./production/iowa.js": 67,
        "./production/pabets.js": 68,
        "./production/tvg.js": 69,
        "./qa/4njbets.js": 70,
        "./qa/base.js": 12,
        "./qa/iowa.js": 71,
        "./qa/pabets.js": 72,
        "./qa/tvg.js": 73,
        "./staging/4njbets.js": 74,
        "./staging/base.js": 13,
        "./staging/iowa.js": 75,
        "./staging/pabets.js": 76,
        "./staging/tvg.js": 77
      };
      function webpackContext(req) {
        return __webpack_require__(webpackContextResolve(req));
      };
      function webpackContextResolve(req) {
        var id = map[req];
        if (!(id + 1)) // check for number or string
          throw new Error("Cannot find module '" + req + "'.");
        return id;
      };
      webpackContext.keys = function webpackContextKeys() {
        return Object.keys(map);
      };
      webpackContext.resolve = webpackContextResolve;
      module.exports = webpackContext;
      webpackContext.id = 65;

      /***/
    },
    /* 66 */
    /***/function (module, exports) {

      module.exports = {
        service_host: 'service.us.betfair.com'
      };

      /***/
    },
    /* 67 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 68 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 69 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 70 */
    /***/function (module, exports) {

      module.exports = {
        service_host: 'service-qa.us.betfair.com'
      };

      /***/
    },
    /* 71 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 72 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 73 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 74 */
    /***/function (module, exports) {

      module.exports = {
        service_host: 'service-staging.us.betfair.com'
      };

      /***/
    },
    /* 75 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 76 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 77 */
    /***/function (module, exports) {

      module.exports = {};

      /***/
    },
    /* 78 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";
      /* harmony default export */
      __webpack_exports__["a"] = function () {
        if (typeof window !== 'undefined' && window.__TVG_GLOBALS__ && window.__TVG_GLOBALS__.DEVICE) {
          return window.__TVG_GLOBALS__.DEVICE;
        }
        return 'desktop';
      };

      /***/
    },
    /* 79 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";

      /* harmony default export */
      __webpack_exports__["a"] = function () {
        if (typeof window !== 'undefined' && window.__TVG_GLOBALS__ && window.__TVG_GLOBALS__.PRODUCT) {
          return window.__TVG_GLOBALS__.PRODUCT;
        }
        return 'tvg4';
      };

      /***/
    },
    /* 80 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";

      // TODO: remove this

      /* harmony default export */
      __webpack_exports__["a"] = {
        TVG4: {
          NAV: 'TVG4_NAVIGATION',
          OPEN_QUICK_DEPOSIT: 'OPEN_QUICK_DEPOSIT',
          SEND_FEEDBACK: 'TVG4_SEND_FEEDBACK',
          UPDATE_ROUTER: 'UPDATE_ROUTER',
          SESSION_TIMEOUT: 'TVG4_SESSION_TIMEOUT',
          UPDATE_SESSION: 'UPDATE_SESSION'
        },
        TOUCH: {
          NAV: 'TOUCH_NAVIGATION',
          OPEN_LOGIN_VIEW: 'OPEN_LOGIN_VIEW',
          OPEN_QUICK_DEPOSIT: 'OPEN_QUICK_DEPOSIT',
          OPEN_MY_BETS: 'OPEN_MY_BETS',
          UPDATE_SESSION: 'UPDATE_SESSION',
          UPDATE_PREFERENCES: 'UPDATE_PREFERENCES',
          UPDATE_ROUTER: 'UPDATE_ROUTER'
        },
        LOGINOUT: {
          LOGIN: 'APP_LOGIN',
          LOGOUT: 'APP_LOGOUT',
          REDIRECT: 'APP_REDIRECT'
        },
        USER_ACTION: {
          SEND: 'USER_ACTION'
        }
      };

      /***/
    },
    /* 81 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";
      /* harmony import */
      var __WEBPACK_IMPORTED_MODULE_0_axios__ = __webpack_require__(14);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_0_axios___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_axios__);
      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      var parseFeatures = function parseFeatures(featuresData) {
        var features = false;
        try {
          var data = JSON.parse(decodeURIComponent(featuresData));
          if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') {
            features = data.response;
          }
        } catch (e) {}

        return features;
      };

      var readFeatures = function readFeatures() {
        var featuresObject = false;
        if (typeof window !== 'undefined' && window.__TVG_GLOBALS__ && window.__TVG_GLOBALS__.FEATURE_TOGGLES) {
          featuresObject = parseFeatures(window.__TVG_GLOBALS__.FEATURE_TOGGLES);
        }
        return featuresObject;
      };

      var getFeatures = function getFeatures(service, product, device, brand, serverSide) {
        var features = readFeatures();
        if (features || typeof window === 'undefined' && !serverSide) {
          return Promise.resolve().then(function () {
            return features;
          });
        } else {
          var requestOptions = {
            url: service.capi + '/featureToggles/' + product + '/' + device + '/' + brand,
            method: 'GET',
            withCredentials: true
          };
          return __WEBPACK_IMPORTED_MODULE_0_axios___default()(requestOptions).then(function (result) {
            return result.data ? result.data : Promise.reject(new Error('No feature toggles returned'));
          });
        }
      };

      /* harmony default export */__webpack_exports__["a"] = { readFeatures: readFeatures, getFeatures: getFeatures };

      /***/
    },
    /* 82 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";
      /* harmony import */
      var __WEBPACK_IMPORTED_MODULE_0_axios__ = __webpack_require__(14);
      /* harmony import */var __WEBPACK_IMPORTED_MODULE_0_axios___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_axios__);
      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      var parseMessages = function parseMessages(messagesData) {
        var messages = false;
        try {
          var data = JSON.parse(decodeURIComponent(messagesData));
          if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') {
            messages = data.response.reduce(function (values, obj) {
              return Object.assign(values, obj);
            }, {});
          }
        } catch (e) {}

        return messages;
      };

      var readMessages = function readMessages() {
        var messagesObject = false;
        if (typeof window !== 'undefined' && window.__TVG_GLOBALS__ && window.__TVG_GLOBALS__.MESSAGES) {
          messagesObject = parseMessages(window.__TVG_GLOBALS__.MESSAGES);
        }
        return messagesObject;
      };

      var getMessages = function getMessages(namespaces, service, product, device, brand, serverSide) {
        var messages = readMessages();
        if (messages || typeof window === 'undefined' && !serverSide) {
          return Promise.resolve().then(function () {
            return messages;
          });
        } else {
          var requestOptions = {
            url: service.capi + '/messages?product=' + product + '&device=' + device + '&brand=' + brand + '&namespace=' + namespaces,
            method: 'GET',
            withCredentials: true
          };
          return __WEBPACK_IMPORTED_MODULE_0_axios___default()(requestOptions).then(function (result) {
            return result.data ? result.data : Promise.reject(new Error('No messages returned'));
          });
        }
      };

      /* harmony default export */__webpack_exports__["a"] = { readMessages: readMessages, getMessages: getMessages };

      /***/
    },
    /* 83 */
    /***/function (module, __webpack_exports__, __webpack_require__) {

      "use strict";

      var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
        return typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === 'undefined' ? 'undefined' : _typeof2(obj);
      };

      /* harmony default export */__webpack_exports__["a"] = function () {
        var metadata = false;
        if (typeof window !== 'undefined' && window.__TVG_GLOBALS__ && window.__TVG_GLOBALS__.metadata) {
          try {
            var data = JSON.parse(decodeURIComponent(window.__TVG_GLOBALS__.METADATA));
            if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') {
              metadata = data;
            }
          } catch (e) {}
        }
        return metadata;
      };

      /***/
    }]
    /******/)
  );
});
//# sourceMappingURL=tvg-conf.umd.js.map

;

var _temp = function () {
  if (typeof __REACT_HOT_LOADER__ === 'undefined') {
    return;
  }
}();

;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(37)(module)))

/***/ }),
/* 120 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);
var bind = __webpack_require__(64);
var Axios = __webpack_require__(122);
var defaults = __webpack_require__(38);

/**
 * Create an instance of Axios
 *
 * @param {Object} defaultConfig The default config for the instance
 * @return {Axios} A new instance of Axios
 */
function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);
  var instance = bind(Axios.prototype.request, context);

  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context);

  // Copy context to instance
  utils.extend(instance, context);

  return instance;
}

// Create the default instance to be exported
var axios = createInstance(defaults);

// Expose Axios class to allow class inheritance
axios.Axios = Axios;

// Factory for creating new instances
axios.create = function create(instanceConfig) {
  return createInstance(utils.merge(defaults, instanceConfig));
};

// Expose Cancel & CancelToken
axios.Cancel = __webpack_require__(61);
axios.CancelToken = __webpack_require__(121);
axios.isCancel = __webpack_require__(62);

// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};
axios.spread = __webpack_require__(136);

module.exports = axios;

// Allow use of default import syntax in TypeScript
module.exports.default = axios;

/***/ }),
/* 121 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var Cancel = __webpack_require__(61);

/**
 * A `CancelToken` is an object that can be used to request cancellation of an operation.
 *
 * @class
 * @param {Function} executor The executor function.
 */
function CancelToken(executor) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor must be a function.');
  }

  var resolvePromise;
  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });

  var token = this;
  executor(function cancel(message) {
    if (token.reason) {
      // Cancellation has already been requested
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason);
  });
}

/**
 * Throws a `Cancel` if cancellation has been requested.
 */
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
  if (this.reason) {
    throw this.reason;
  }
};

/**
 * Returns an object that contains a new `CancelToken` and a function that, when called,
 * cancels the `CancelToken`.
 */
CancelToken.source = function source() {
  var cancel;
  var token = new CancelToken(function executor(c) {
    cancel = c;
  });
  return {
    token: token,
    cancel: cancel
  };
};

module.exports = CancelToken;

/***/ }),
/* 122 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var defaults = __webpack_require__(38);
var utils = __webpack_require__(3);
var InterceptorManager = __webpack_require__(123);
var dispatchRequest = __webpack_require__(124);
var isAbsoluteURL = __webpack_require__(132);
var combineURLs = __webpack_require__(130);

/**
 * Create a new instance of Axios
 *
 * @param {Object} instanceConfig The default config for the instance
 */
function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  };
}

/**
 * Dispatch a request
 *
 * @param {Object} config The config specific for this request (merged with this.defaults)
 */
Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = utils.merge({
      url: arguments[0]
    }, arguments[1]);
  }

  config = utils.merge(defaults, this.defaults, { method: 'get' }, config);
  config.method = config.method.toLowerCase();

  // Support baseURL config
  if (config.baseURL && !isAbsoluteURL(config.url)) {
    config.url = combineURLs(config.baseURL, config.url);
  }

  // Hook up interceptors middleware
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
};

// Provide aliases for supported request methods
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function (url, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url
    }));
  };
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function (url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

module.exports = Axios;

/***/ }),
/* 123 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);

function InterceptorManager() {
  this.handlers = [];
}

/**
 * Add a new interceptor to the stack
 *
 * @param {Function} fulfilled The function to handle `then` for a `Promise`
 * @param {Function} rejected The function to handle `reject` for a `Promise`
 *
 * @return {Number} An ID used to remove interceptor later
 */
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected
  });
  return this.handlers.length - 1;
};

/**
 * Remove an interceptor from the stack
 *
 * @param {Number} id The ID that was returned by `use`
 */
InterceptorManager.prototype.eject = function eject(id) {
  if (this.handlers[id]) {
    this.handlers[id] = null;
  }
};

/**
 * Iterate over all the registered interceptors
 *
 * This method is particularly useful for skipping over any
 * interceptors that may have become `null` calling `eject`.
 *
 * @param {Function} fn The function to call for each interceptor
 */
InterceptorManager.prototype.forEach = function forEach(fn) {
  utils.forEach(this.handlers, function forEachHandler(h) {
    if (h !== null) {
      fn(h);
    }
  });
};

module.exports = InterceptorManager;

/***/ }),
/* 124 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);
var transformData = __webpack_require__(127);
var isCancel = __webpack_require__(62);
var defaults = __webpack_require__(38);

/**
 * Throws a `Cancel` if cancellation has been requested.
 */
function throwIfCancellationRequested(config) {
  if (config.cancelToken) {
    config.cancelToken.throwIfRequested();
  }
}

/**
 * Dispatch a request to the server using the configured adapter.
 *
 * @param {object} config The config that is to be used for the request
 * @returns {Promise} The Promise to be fulfilled
 */
module.exports = function dispatchRequest(config) {
  throwIfCancellationRequested(config);

  // Ensure headers exist
  config.headers = config.headers || {};

  // Transform request data
  config.data = transformData(config.data, config.headers, config.transformRequest);

  // Flatten headers
  config.headers = utils.merge(config.headers.common || {}, config.headers[config.method] || {}, config.headers || {});

  utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], function cleanHeaderConfig(method) {
    delete config.headers[method];
  });

  var adapter = config.adapter || defaults.adapter;

  return adapter(config).then(function onAdapterResolution(response) {
    throwIfCancellationRequested(config);

    // Transform response data
    response.data = transformData(response.data, response.headers, config.transformResponse);

    return response;
  }, function onAdapterRejection(reason) {
    if (!isCancel(reason)) {
      throwIfCancellationRequested(config);

      // Transform response data
      if (reason && reason.response) {
        reason.response.data = transformData(reason.response.data, reason.response.headers, config.transformResponse);
      }
    }

    return Promise.reject(reason);
  });
};

/***/ }),
/* 125 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * Update an Error with the specified config, error code, and response.
 *
 * @param {Error} error The error to update.
 * @param {Object} config The config.
 * @param {string} [code] The error code (for example, 'ECONNABORTED').
 * @param {Object} [request] The request.
 * @param {Object} [response] The response.
 * @returns {Error} The error.
 */

module.exports = function enhanceError(error, config, code, request, response) {
  error.config = config;
  if (code) {
    error.code = code;
  }
  error.request = request;
  error.response = response;
  return error;
};

/***/ }),
/* 126 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var createError = __webpack_require__(63);

/**
 * Resolve or reject a Promise based on response status.
 *
 * @param {Function} resolve A function that resolves the promise.
 * @param {Function} reject A function that rejects the promise.
 * @param {object} response The response.
 */
module.exports = function settle(resolve, reject, response) {
  var validateStatus = response.config.validateStatus;
  // Note: status is not exposed by XDomainRequest
  if (!response.status || !validateStatus || validateStatus(response.status)) {
    resolve(response);
  } else {
    reject(createError('Request failed with status code ' + response.status, response.config, null, response.request, response));
  }
};

/***/ }),
/* 127 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);

/**
 * Transform the data for a request or a response
 *
 * @param {Object|String} data The data to be transformed
 * @param {Array} headers The headers for the request or response
 * @param {Array|Function} fns A single function or Array of functions
 * @returns {*} The resulting transformed data
 */
module.exports = function transformData(data, headers, fns) {
  /*eslint no-param-reassign:0*/
  utils.forEach(fns, function transform(fn) {
    data = fn(data, headers);
  });

  return data;
};

/***/ }),
/* 128 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


// btoa polyfill for IE<10 courtesy https://github.com/davidchambers/Base64.js

var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';

function E() {
  this.message = 'String contains an invalid character';
}
E.prototype = new Error();
E.prototype.code = 5;
E.prototype.name = 'InvalidCharacterError';

function btoa(input) {
  var str = String(input);
  var output = '';
  for (
  // initialize result and counter
  var block, charCode, idx = 0, map = chars;
  // if the next str index does not exist:
  //   change the mapping table to "="
  //   check if d has no fractional digits
  str.charAt(idx | 0) || (map = '=', idx % 1);
  // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
  output += map.charAt(63 & block >> 8 - idx % 1 * 8)) {
    charCode = str.charCodeAt(idx += 3 / 4);
    if (charCode > 0xFF) {
      throw new E();
    }
    block = block << 8 | charCode;
  }
  return output;
}

module.exports = btoa;

/***/ }),
/* 129 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);

function encode(val) {
  return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']');
}

/**
 * Build a URL by appending params to the end
 *
 * @param {string} url The base of the url (e.g., http://www.google.com)
 * @param {object} [params] The params to be appended
 * @returns {string} The formatted url
 */
module.exports = function buildURL(url, params, paramsSerializer) {
  /*eslint no-param-reassign:0*/
  if (!params) {
    return url;
  }

  var serializedParams;
  if (paramsSerializer) {
    serializedParams = paramsSerializer(params);
  } else if (utils.isURLSearchParams(params)) {
    serializedParams = params.toString();
  } else {
    var parts = [];

    utils.forEach(params, function serialize(val, key) {
      if (val === null || typeof val === 'undefined') {
        return;
      }

      if (utils.isArray(val)) {
        key = key + '[]';
      }

      if (!utils.isArray(val)) {
        val = [val];
      }

      utils.forEach(val, function parseValue(v) {
        if (utils.isDate(v)) {
          v = v.toISOString();
        } else if (utils.isObject(v)) {
          v = JSON.stringify(v);
        }
        parts.push(encode(key) + '=' + encode(v));
      });
    });

    serializedParams = parts.join('&');
  }

  if (serializedParams) {
    url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
  }

  return url;
};

/***/ }),
/* 130 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * Creates a new URL by combining the specified URLs
 *
 * @param {string} baseURL The base URL
 * @param {string} relativeURL The relative URL
 * @returns {string} The combined URL
 */

module.exports = function combineURLs(baseURL, relativeURL) {
  return relativeURL ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL;
};

/***/ }),
/* 131 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);

module.exports = utils.isStandardBrowserEnv() ?

// Standard browser envs support document.cookie
function standardBrowserEnv() {
  return {
    write: function write(name, value, expires, path, domain, secure) {
      var cookie = [];
      cookie.push(name + '=' + encodeURIComponent(value));

      if (utils.isNumber(expires)) {
        cookie.push('expires=' + new Date(expires).toGMTString());
      }

      if (utils.isString(path)) {
        cookie.push('path=' + path);
      }

      if (utils.isString(domain)) {
        cookie.push('domain=' + domain);
      }

      if (secure === true) {
        cookie.push('secure');
      }

      document.cookie = cookie.join('; ');
    },

    read: function read(name) {
      var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
      return match ? decodeURIComponent(match[3]) : null;
    },

    remove: function remove(name) {
      this.write(name, '', Date.now() - 86400000);
    }
  };
}() :

// Non standard browser env (web workers, react-native) lack needed support.
function nonStandardBrowserEnv() {
  return {
    write: function write() {},
    read: function read() {
      return null;
    },
    remove: function remove() {}
  };
}();

/***/ }),
/* 132 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * Determines whether the specified URL is absolute
 *
 * @param {string} url The URL to test
 * @returns {boolean} True if the specified URL is absolute, otherwise false
 */

module.exports = function isAbsoluteURL(url) {
  // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
  // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
  // by any combination of letters, digits, plus, period, or hyphen.
  return (/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url)
  );
};

/***/ }),
/* 133 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);

module.exports = utils.isStandardBrowserEnv() ?

// Standard browser envs have full support of the APIs needed to test
// whether the request URL is of the same origin as current location.
function standardBrowserEnv() {
  var msie = /(msie|trident)/i.test(navigator.userAgent);
  var urlParsingNode = document.createElement('a');
  var originURL;

  /**
  * Parse a URL to discover it's components
  *
  * @param {String} url The URL to be parsed
  * @returns {Object}
  */
  function resolveURL(url) {
    var href = url;

    if (msie) {
      // IE needs attribute set twice to normalize properties
      urlParsingNode.setAttribute('href', href);
      href = urlParsingNode.href;
    }

    urlParsingNode.setAttribute('href', href);

    // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
    return {
      href: urlParsingNode.href,
      protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
      host: urlParsingNode.host,
      search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
      hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
      hostname: urlParsingNode.hostname,
      port: urlParsingNode.port,
      pathname: urlParsingNode.pathname.charAt(0) === '/' ? urlParsingNode.pathname : '/' + urlParsingNode.pathname
    };
  }

  originURL = resolveURL(window.location.href);

  /**
  * Determine if a URL shares the same origin as the current location
  *
  * @param {String} requestURL The URL to test
  * @returns {boolean} True if URL shares the same origin, otherwise false
  */
  return function isURLSameOrigin(requestURL) {
    var parsed = utils.isString(requestURL) ? resolveURL(requestURL) : requestURL;
    return parsed.protocol === originURL.protocol && parsed.host === originURL.host;
  };
}() :

// Non standard browser envs (web workers, react-native) lack needed support.
function nonStandardBrowserEnv() {
  return function isURLSameOrigin() {
    return true;
  };
}();

/***/ }),
/* 134 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);

module.exports = function normalizeHeaderName(headers, normalizedName) {
  utils.forEach(headers, function processHeader(value, name) {
    if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
      headers[normalizedName] = value;
      delete headers[name];
    }
  });
};

/***/ }),
/* 135 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


var utils = __webpack_require__(3);

/**
 * Parse headers into an object
 *
 * ```
 * Date: Wed, 27 Aug 2014 08:58:49 GMT
 * Content-Type: application/json
 * Connection: keep-alive
 * Transfer-Encoding: chunked
 * ```
 *
 * @param {String} headers Headers needing to be parsed
 * @returns {Object} Headers parsed into an object
 */
module.exports = function parseHeaders(headers) {
  var parsed = {};
  var key;
  var val;
  var i;

  if (!headers) {
    return parsed;
  }

  utils.forEach(headers.split('\n'), function parser(line) {
    i = line.indexOf(':');
    key = utils.trim(line.substr(0, i)).toLowerCase();
    val = utils.trim(line.substr(i + 1));

    if (key) {
      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
    }
  });

  return parsed;
};

/***/ }),
/* 136 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


/**
 * Syntactic sugar for invoking a function and expanding an array for arguments.
 *
 * Common use case would be to use `Function.prototype.apply`.
 *
 *  ```js
 *  function f(x, y, z) {}
 *  var args = [1, 2, 3];
 *  f.apply(null, args);
 *  ```
 *
 * With `spread` this example can be re-written.
 *
 *  ```js
 *  spread(function(x, y, z) {})([1, 2, 3]);
 *  ```
 *
 * @param {Function} callback
 * @returns {Function}
 */

module.exports = function spread(callback) {
  return function wrap(arr) {
    return callback.apply(null, arr);
  };
};

/***/ }),
/* 137 */
/***/ (function(module, exports) {

/*!
 * Determine if an object is a Buffer
 *
 * @author   Feross Aboukhadijeh <https://feross.org>
 * @license  MIT
 */

// The _isBuffer check is for Safari 5-7 support, because it's missing
// Object.prototype.constructor. Remove this eventually
module.exports = function (obj) {
  return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer);
};

function isBuffer(obj) {
  return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj);
}

// For Node v0.10 support. Remove this eventually.
function isSlowBuffer(obj) {
  return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0));
}

/***/ }),
/* 138 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/** `Object#toString` result references. */
var funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    symbolTag = '[object Symbol]';

/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
    reIsPlainProp = /^\w*$/,
    reLeadingDot = /^\./,
    rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Detect free variable `global` from Node.js. */
var freeGlobal = (typeof global === 'undefined' ? 'undefined' : _typeof(global)) == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = (typeof self === 'undefined' ? 'undefined' : _typeof(self)) == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Checks if `value` is a host object in IE < 9.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
 */
function isHostObject(value) {
  // Many host objects are `Object` objects that can coerce to strings
  // despite having improperly defined `toString` methods.
  var result = false;
  if (value != null && typeof value.toString != 'function') {
    try {
      result = !!(value + '');
    } catch (e) {}
  }
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to detect methods masquerading as native. */
var maskSrcKey = function () {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? 'Symbol(src)_1.' + uid : '';
}();

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');

/** Built-in value references. */
var _Symbol = root.Symbol,
    splice = arrayProto.splice;

/* Built-in method references that are verified to be native. */
var Map = getNative(root, 'Map'),
    nativeCreate = getNative(Object, 'create');

/** Used to convert symbols to primitives and strings. */
var symbolProto = _Symbol ? _Symbol.prototype : undefined,
    symbolToString = symbolProto ? symbolProto.toString : undefined;

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  return this.has(key) && delete this.__data__[key];
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  data[key] = nativeCreate && value === undefined ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.__data__ = {
    'hash': new Hash(),
    'map': new (Map || ListCache)(),
    'string': new Hash()
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  return getMapData(this, key)['delete'](key);
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  getMapData(this, key).set(key, value);
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * The base implementation of `_.get` without support for default values.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @returns {*} Returns the resolved value.
 */
function baseGet(object, path) {
  path = isKey(path, object) ? [path] : castPath(path);

  var index = 0,
      length = path.length;

  while (object != null && index < length) {
    object = object[toKey(path[index++])];
  }
  return index && index == length ? object : undefined;
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = isFunction(value) || isHostObject(value) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value;
  }
  if (isSymbol(value)) {
    return symbolToString ? symbolToString.call(value) : '';
  }
  var result = value + '';
  return result == '0' && 1 / value == -INFINITY ? '-0' : result;
}

/**
 * Casts `value` to a path array if it's not one.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {Array} Returns the cast property path array.
 */
function castPath(value) {
  return isArray(value) ? value : stringToPath(value);
}

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key) ? data[typeof key == 'string' ? 'string' : 'hash'] : data.map;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * Checks if `value` is a property name and not a property path.
 *
 * @private
 * @param {*} value The value to check.
 * @param {Object} [object] The object to query keys on.
 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 */
function isKey(value, object) {
  if (isArray(value)) {
    return false;
  }
  var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
  if (type == 'number' || type == 'symbol' || type == 'boolean' || value == null || isSymbol(value)) {
    return true;
  }
  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
  return type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean' ? value !== '__proto__' : value === null;
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && maskSrcKey in func;
}

/**
 * Converts `string` to a property path array.
 *
 * @private
 * @param {string} string The string to convert.
 * @returns {Array} Returns the property path array.
 */
var stringToPath = memoize(function (string) {
  string = toString(string);

  var result = [];
  if (reLeadingDot.test(string)) {
    result.push('');
  }
  string.replace(rePropName, function (match, number, quote, string) {
    result.push(quote ? string.replace(reEscapeChar, '$1') : number || match);
  });
  return result;
});

/**
 * Converts `value` to a string key if it's not a string or symbol.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {string|symbol} Returns the key.
 */
function toKey(value) {
  if (typeof value == 'string' || isSymbol(value)) {
    return value;
  }
  var result = value + '';
  return result == '0' && 1 / value == -INFINITY ? '-0' : result;
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to process.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return func + '';
    } catch (e) {}
  }
  return '';
}

/**
 * Creates a function that memoizes the result of `func`. If `resolver` is
 * provided, it determines the cache key for storing the result based on the
 * arguments provided to the memoized function. By default, the first argument
 * provided to the memoized function is used as the map cache key. The `func`
 * is invoked with the `this` binding of the memoized function.
 *
 * **Note:** The cache is exposed as the `cache` property on the memoized
 * function. Its creation may be customized by replacing the `_.memoize.Cache`
 * constructor with one whose instances implement the
 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
 * method interface of `delete`, `get`, `has`, and `set`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to have its output memoized.
 * @param {Function} [resolver] The function to resolve the cache key.
 * @returns {Function} Returns the new memoized function.
 * @example
 *
 * var object = { 'a': 1, 'b': 2 };
 * var other = { 'c': 3, 'd': 4 };
 *
 * var values = _.memoize(_.values);
 * values(object);
 * // => [1, 2]
 *
 * values(other);
 * // => [3, 4]
 *
 * object.a = 2;
 * values(object);
 * // => [1, 2]
 *
 * // Modify the result cache.
 * values.cache.set(object, ['a', 'b']);
 * values(object);
 * // => ['a', 'b']
 *
 * // Replace `_.memoize.Cache`.
 * _.memoize.Cache = WeakMap;
 */
function memoize(func, resolver) {
  if (typeof func != 'function' || resolver && typeof resolver != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  var memoized = function memoized() {
    var args = arguments,
        key = resolver ? resolver.apply(this, args) : args[0],
        cache = memoized.cache;

    if (cache.has(key)) {
      return cache.get(key);
    }
    var result = func.apply(this, args);
    memoized.cache = cache.set(key, result);
    return result;
  };
  memoized.cache = new (memoize.Cache || MapCache)();
  return memoized;
}

// Assign cache to `_.memoize`.
memoize.Cache = MapCache;

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || value !== value && other !== other;
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'object';
}

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return (typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'symbol' || isObjectLike(value) && objectToString.call(value) == symbolTag;
}

/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 * @example
 *
 * _.toString(null);
 * // => ''
 *
 * _.toString(-0);
 * // => '-0'
 *
 * _.toString([1, 2, 3]);
 * // => '1,2,3'
 */
function toString(value) {
  return value == null ? '' : baseToString(value);
}

/**
 * Gets the value at `path` of `object`. If the resolved value is
 * `undefined`, the `defaultValue` is returned in its place.
 *
 * @static
 * @memberOf _
 * @since 3.7.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
 * @returns {*} Returns the resolved value.
 * @example
 *
 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
 *
 * _.get(object, 'a[0].b.c');
 * // => 3
 *
 * _.get(object, ['a', '0', 'b', 'c']);
 * // => 3
 *
 * _.get(object, 'a.b.c', 'default');
 * // => 'default'
 */
function get(object, path, defaultValue) {
  var result = object == null ? undefined : baseGet(object, path);
  return result === undefined ? defaultValue : result;
}

module.exports = get;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(109)))

/***/ }),
/* 139 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(6),
    root = __webpack_require__(1);

/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView');

module.exports = DataView;

/***/ }),
/* 140 */
/***/ (function(module, exports, __webpack_require__) {

var hashClear = __webpack_require__(195),
    hashDelete = __webpack_require__(196),
    hashGet = __webpack_require__(197),
    hashHas = __webpack_require__(198),
    hashSet = __webpack_require__(199);

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;

    this.clear();
    while (++index < length) {
        var entry = entries[index];
        this.set(entry[0], entry[1]);
    }
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

module.exports = Hash;

/***/ }),
/* 141 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(6),
    root = __webpack_require__(1);

/* Built-in method references that are verified to be native. */
var Promise = getNative(root, 'Promise');

module.exports = Promise;

/***/ }),
/* 142 */
/***/ (function(module, exports, __webpack_require__) {

var getNative = __webpack_require__(6),
    root = __webpack_require__(1);

/* Built-in method references that are verified to be native. */
var Set = getNative(root, 'Set');

module.exports = Set;

/***/ }),
/* 143 */
/***/ (function(module, exports, __webpack_require__) {

var MapCache = __webpack_require__(41),
    setCacheAdd = __webpack_require__(226),
    setCacheHas = __webpack_require__(227);

/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
    var index = -1,
        length = values == null ? 0 : values.length;

    this.__data__ = new MapCache();
    while (++index < length) {
        this.add(values[index]);
    }
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;

module.exports = SetCache;

/***/ }),
/* 144 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.filter` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length,
      resIndex = 0,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[resIndex++] = value;
    }
  }
  return result;
}

module.exports = arrayFilter;

/***/ }),
/* 145 */
/***/ (function(module, exports, __webpack_require__) {

var baseIndexOf = __webpack_require__(152);

/**
 * A specialized version of `_.includes` for arrays without support for
 * specifying an index to search from.
 *
 * @private
 * @param {Array} [array] The array to inspect.
 * @param {*} target The value to search for.
 * @returns {boolean} Returns `true` if `target` is found, else `false`.
 */
function arrayIncludes(array, value) {
  var length = array == null ? 0 : array.length;
  return !!length && baseIndexOf(array, value, 0) > -1;
}

module.exports = arrayIncludes;

/***/ }),
/* 146 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.some` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

module.exports = arraySome;

/***/ }),
/* 147 */
/***/ (function(module, exports, __webpack_require__) {

var copyObject = __webpack_require__(12),
    keysIn = __webpack_require__(22);

/**
 * The base implementation of `_.assignIn` without support for multiple sources
 * or `customizer` functions.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @returns {Object} Returns `object`.
 */
function baseAssignIn(object, source) {
  return object && copyObject(source, keysIn(source), object);
}

module.exports = baseAssignIn;

/***/ }),
/* 148 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.findIndex` and `_.findLastIndex` without
 * support for iteratee shorthands.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {Function} predicate The function invoked per iteration.
 * @param {number} fromIndex The index to search from.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function baseFindIndex(array, predicate, fromIndex, fromRight) {
  var length = array.length,
      index = fromIndex + (fromRight ? 1 : -1);

  while (fromRight ? index-- : ++index < length) {
    if (predicate(array[index], index, array)) {
      return index;
    }
  }
  return -1;
}

module.exports = baseFindIndex;

/***/ }),
/* 149 */
/***/ (function(module, exports, __webpack_require__) {

var arrayPush = __webpack_require__(44),
    isFlattenable = __webpack_require__(203);

/**
 * The base implementation of `_.flatten` with support for restricting flattening.
 *
 * @private
 * @param {Array} array The array to flatten.
 * @param {number} depth The maximum recursion depth.
 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
 * @param {Array} [result=[]] The initial result value.
 * @returns {Array} Returns the new flattened array.
 */
function baseFlatten(array, depth, predicate, isStrict, result) {
  var index = -1,
      length = array.length;

  predicate || (predicate = isFlattenable);
  result || (result = []);

  while (++index < length) {
    var value = array[index];
    if (depth > 0 && predicate(value)) {
      if (depth > 1) {
        // Recursively flatten arrays (susceptible to call stack limits).
        baseFlatten(value, depth - 1, predicate, isStrict, result);
      } else {
        arrayPush(result, value);
      }
    } else if (!isStrict) {
      result[result.length] = value;
    }
  }
  return result;
}

module.exports = baseFlatten;

/***/ }),
/* 150 */
/***/ (function(module, exports, __webpack_require__) {

var createBaseFor = __webpack_require__(181);

/**
 * The base implementation of `baseForOwn` which iterates over `object`
 * properties returned by `keysFunc` and invokes `iteratee` for each property.
 * Iteratee functions may exit iteration early by explicitly returning `false`.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @returns {Object} Returns `object`.
 */
var baseFor = createBaseFor();

module.exports = baseFor;

/***/ }),
/* 151 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.hasIn` without support for deep paths.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {Array|string} key The key to check.
 * @returns {boolean} Returns `true` if `key` exists, else `false`.
 */
function baseHasIn(object, key) {
  return object != null && key in Object(object);
}

module.exports = baseHasIn;

/***/ }),
/* 152 */
/***/ (function(module, exports, __webpack_require__) {

var baseFindIndex = __webpack_require__(148),
    baseIsNaN = __webpack_require__(157),
    strictIndexOf = __webpack_require__(234);

/**
 * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} value The value to search for.
 * @param {number} fromIndex The index to search from.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function baseIndexOf(array, value, fromIndex) {
    return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
}

module.exports = baseIndexOf;

/***/ }),
/* 153 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetTag = __webpack_require__(5),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var argsTag = '[object Arguments]';

/**
 * The base implementation of `_.isArguments`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 */
function baseIsArguments(value) {
  return isObjectLike(value) && baseGetTag(value) == argsTag;
}

module.exports = baseIsArguments;

/***/ }),
/* 154 */
/***/ (function(module, exports, __webpack_require__) {

var Stack = __webpack_require__(24),
    equalArrays = __webpack_require__(86),
    equalByTag = __webpack_require__(185),
    equalObjects = __webpack_require__(186),
    getTag = __webpack_require__(13),
    isArray = __webpack_require__(0),
    isBuffer = __webpack_require__(20),
    isTypedArray = __webpack_require__(35);

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    objectTag = '[object Object]';

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
  var objIsArr = isArray(object),
      othIsArr = isArray(other),
      objTag = objIsArr ? arrayTag : getTag(object),
      othTag = othIsArr ? arrayTag : getTag(other);

  objTag = objTag == argsTag ? objectTag : objTag;
  othTag = othTag == argsTag ? objectTag : othTag;

  var objIsObj = objTag == objectTag,
      othIsObj = othTag == objectTag,
      isSameTag = objTag == othTag;

  if (isSameTag && isBuffer(object)) {
    if (!isBuffer(other)) {
      return false;
    }
    objIsArr = true;
    objIsObj = false;
  }
  if (isSameTag && !objIsObj) {
    stack || (stack = new Stack());
    return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
  }
  if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      var objUnwrapped = objIsWrapped ? object.value() : object,
          othUnwrapped = othIsWrapped ? other.value() : other;

      stack || (stack = new Stack());
      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
    }
  }
  if (!isSameTag) {
    return false;
  }
  stack || (stack = new Stack());
  return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
}

module.exports = baseIsEqualDeep;

/***/ }),
/* 155 */
/***/ (function(module, exports, __webpack_require__) {

var getTag = __webpack_require__(13),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var mapTag = '[object Map]';

/**
 * The base implementation of `_.isMap` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
 */
function baseIsMap(value) {
  return isObjectLike(value) && getTag(value) == mapTag;
}

module.exports = baseIsMap;

/***/ }),
/* 156 */
/***/ (function(module, exports, __webpack_require__) {

var Stack = __webpack_require__(24),
    baseIsEqual = __webpack_require__(75);

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/**
 * The base implementation of `_.isMatch` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to inspect.
 * @param {Object} source The object of property values to match.
 * @param {Array} matchData The property names, values, and compare flags to match.
 * @param {Function} [customizer] The function to customize comparisons.
 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
 */
function baseIsMatch(object, source, matchData, customizer) {
  var index = matchData.length,
      length = index,
      noCustomizer = !customizer;

  if (object == null) {
    return !length;
  }
  object = Object(object);
  while (index--) {
    var data = matchData[index];
    if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
      return false;
    }
  }
  while (++index < length) {
    data = matchData[index];
    var key = data[0],
        objValue = object[key],
        srcValue = data[1];

    if (noCustomizer && data[2]) {
      if (objValue === undefined && !(key in object)) {
        return false;
      }
    } else {
      var stack = new Stack();
      if (customizer) {
        var result = customizer(objValue, srcValue, key, object, source, stack);
      }
      if (!(result === undefined ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result)) {
        return false;
      }
    }
  }
  return true;
}

module.exports = baseIsMatch;

/***/ }),
/* 157 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.isNaN` without support for number objects.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
 */
function baseIsNaN(value) {
  return value !== value;
}

module.exports = baseIsNaN;

/***/ }),
/* 158 */
/***/ (function(module, exports, __webpack_require__) {

var isFunction = __webpack_require__(34),
    isMasked = __webpack_require__(207),
    isObject = __webpack_require__(4),
    toSource = __webpack_require__(103);

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used for built-in method references. */
var funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

module.exports = baseIsNative;

/***/ }),
/* 159 */
/***/ (function(module, exports, __webpack_require__) {

var getTag = __webpack_require__(13),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var setTag = '[object Set]';

/**
 * The base implementation of `_.isSet` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
 */
function baseIsSet(value) {
  return isObjectLike(value) && getTag(value) == setTag;
}

module.exports = baseIsSet;

/***/ }),
/* 160 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetTag = __webpack_require__(5),
    isLength = __webpack_require__(58),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    objectTag = '[object Object]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;

/**
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 */
function baseIsTypedArray(value) {
    return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}

module.exports = baseIsTypedArray;

/***/ }),
/* 161 */
/***/ (function(module, exports, __webpack_require__) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var baseMatches = __webpack_require__(163),
    baseMatchesProperty = __webpack_require__(164),
    identity = __webpack_require__(33),
    isArray = __webpack_require__(0),
    property = __webpack_require__(266);

/**
 * The base implementation of `_.iteratee`.
 *
 * @private
 * @param {*} [value=_.identity] The value to convert to an iteratee.
 * @returns {Function} Returns the iteratee.
 */
function baseIteratee(value) {
  // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
  // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
  if (typeof value == 'function') {
    return value;
  }
  if (value == null) {
    return identity;
  }
  if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) == 'object') {
    return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
  }
  return property(value);
}

module.exports = baseIteratee;

/***/ }),
/* 162 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(4),
    isPrototype = __webpack_require__(30),
    nativeKeysIn = __webpack_require__(222);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeysIn(object) {
  if (!isObject(object)) {
    return nativeKeysIn(object);
  }
  var isProto = isPrototype(object),
      result = [];

  for (var key in object) {
    if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
      result.push(key);
    }
  }
  return result;
}

module.exports = baseKeysIn;

/***/ }),
/* 163 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsMatch = __webpack_require__(156),
    getMatchData = __webpack_require__(190),
    matchesStrictComparable = __webpack_require__(94);

/**
 * The base implementation of `_.matches` which doesn't clone `source`.
 *
 * @private
 * @param {Object} source The object of property values to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatches(source) {
  var matchData = getMatchData(source);
  if (matchData.length == 1 && matchData[0][2]) {
    return matchesStrictComparable(matchData[0][0], matchData[0][1]);
  }
  return function (object) {
    return object === source || baseIsMatch(object, source, matchData);
  };
}

module.exports = baseMatches;

/***/ }),
/* 164 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsEqual = __webpack_require__(75),
    get = __webpack_require__(252),
    hasIn = __webpack_require__(253),
    isKey = __webpack_require__(54),
    isStrictComparable = __webpack_require__(93),
    matchesStrictComparable = __webpack_require__(94),
    toKey = __webpack_require__(16);

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/**
 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
 *
 * @private
 * @param {string} path The path of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatchesProperty(path, srcValue) {
  if (isKey(path) && isStrictComparable(srcValue)) {
    return matchesStrictComparable(toKey(path), srcValue);
  }
  return function (object) {
    var objValue = get(object, path);
    return objValue === undefined && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
  };
}

module.exports = baseMatchesProperty;

/***/ }),
/* 165 */
/***/ (function(module, exports, __webpack_require__) {

var Stack = __webpack_require__(24),
    assignMergeValue = __webpack_require__(70),
    baseFor = __webpack_require__(150),
    baseMergeDeep = __webpack_require__(166),
    isObject = __webpack_require__(4),
    keysIn = __webpack_require__(22),
    safeGet = __webpack_require__(98);

/**
 * The base implementation of `_.merge` without support for multiple sources.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {number} srcIndex The index of `source`.
 * @param {Function} [customizer] The function to customize merged values.
 * @param {Object} [stack] Tracks traversed source values and their merged
 *  counterparts.
 */
function baseMerge(object, source, srcIndex, customizer, stack) {
  if (object === source) {
    return;
  }
  baseFor(source, function (srcValue, key) {
    if (isObject(srcValue)) {
      stack || (stack = new Stack());
      baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
    } else {
      var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + '', object, source, stack) : undefined;

      if (newValue === undefined) {
        newValue = srcValue;
      }
      assignMergeValue(object, key, newValue);
    }
  }, keysIn);
}

module.exports = baseMerge;

/***/ }),
/* 166 */
/***/ (function(module, exports, __webpack_require__) {

var assignMergeValue = __webpack_require__(70),
    cloneBuffer = __webpack_require__(78),
    cloneTypedArray = __webpack_require__(79),
    copyArray = __webpack_require__(15),
    initCloneObject = __webpack_require__(92),
    isArguments = __webpack_require__(18),
    isArray = __webpack_require__(0),
    isArrayLikeObject = __webpack_require__(254),
    isBuffer = __webpack_require__(20),
    isFunction = __webpack_require__(34),
    isObject = __webpack_require__(4),
    isPlainObject = __webpack_require__(104),
    isTypedArray = __webpack_require__(35),
    safeGet = __webpack_require__(98),
    toPlainObject = __webpack_require__(272);

/**
 * A specialized version of `baseMerge` for arrays and objects which performs
 * deep merges and tracks traversed objects enabling objects with circular
 * references to be merged.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {string} key The key of the value to merge.
 * @param {number} srcIndex The index of `source`.
 * @param {Function} mergeFunc The function to merge values.
 * @param {Function} [customizer] The function to customize assigned values.
 * @param {Object} [stack] Tracks traversed source values and their merged
 *  counterparts.
 */
function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
  var objValue = safeGet(object, key),
      srcValue = safeGet(source, key),
      stacked = stack.get(srcValue);

  if (stacked) {
    assignMergeValue(object, key, stacked);
    return;
  }
  var newValue = customizer ? customizer(objValue, srcValue, key + '', object, source, stack) : undefined;

  var isCommon = newValue === undefined;

  if (isCommon) {
    var isArr = isArray(srcValue),
        isBuff = !isArr && isBuffer(srcValue),
        isTyped = !isArr && !isBuff && isTypedArray(srcValue);

    newValue = srcValue;
    if (isArr || isBuff || isTyped) {
      if (isArray(objValue)) {
        newValue = objValue;
      } else if (isArrayLikeObject(objValue)) {
        newValue = copyArray(objValue);
      } else if (isBuff) {
        isCommon = false;
        newValue = cloneBuffer(srcValue, true);
      } else if (isTyped) {
        isCommon = false;
        newValue = cloneTypedArray(srcValue, true);
      } else {
        newValue = [];
      }
    } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
      newValue = objValue;
      if (isArguments(objValue)) {
        newValue = toPlainObject(objValue);
      } else if (!isObject(objValue) || srcIndex && isFunction(objValue)) {
        newValue = initCloneObject(srcValue);
      }
    } else {
      isCommon = false;
    }
  }
  if (isCommon) {
    // Recursively merge objects and arrays (susceptible to call stack limits).
    stack.set(srcValue, newValue);
    mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
    stack['delete'](srcValue);
  }
  assignMergeValue(object, key, newValue);
}

module.exports = baseMergeDeep;

/***/ }),
/* 167 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.property` without support for deep paths.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function baseProperty(key) {
  return function (object) {
    return object == null ? undefined : object[key];
  };
}

module.exports = baseProperty;

/***/ }),
/* 168 */
/***/ (function(module, exports, __webpack_require__) {

var baseGet = __webpack_require__(73);

/**
 * A specialized version of `baseProperty` which supports deep paths.
 *
 * @private
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function basePropertyDeep(path) {
  return function (object) {
    return baseGet(object, path);
  };
}

module.exports = basePropertyDeep;

/***/ }),
/* 169 */
/***/ (function(module, exports, __webpack_require__) {

var identity = __webpack_require__(33),
    overRest = __webpack_require__(97),
    setToString = __webpack_require__(57);

/**
 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @returns {Function} Returns the new function.
 */
function baseRest(func, start) {
  return setToString(overRest(func, start, identity), func + '');
}

module.exports = baseRest;

/***/ }),
/* 170 */
/***/ (function(module, exports, __webpack_require__) {

var constant = __webpack_require__(241),
    defineProperty = __webpack_require__(85),
    identity = __webpack_require__(33);

/**
 * The base implementation of `setToString` without support for hot loop shorting.
 *
 * @private
 * @param {Function} func The function to modify.
 * @param {Function} string The `toString` result.
 * @returns {Function} Returns `func`.
 */
var baseSetToString = !defineProperty ? identity : function (func, string) {
  return defineProperty(func, 'toString', {
    'configurable': true,
    'enumerable': false,
    'value': constant(string),
    'writable': true
  });
};

module.exports = baseSetToString;

/***/ }),
/* 171 */
/***/ (function(module, exports) {

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

module.exports = baseTimes;

/***/ }),
/* 172 */
/***/ (function(module, exports, __webpack_require__) {

var _Symbol = __webpack_require__(11),
    arrayMap = __webpack_require__(69),
    isArray = __webpack_require__(0),
    isSymbol = __webpack_require__(21);

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/** Used to convert symbols to primitives and strings. */
var symbolProto = _Symbol ? _Symbol.prototype : undefined,
    symbolToString = symbolProto ? symbolProto.toString : undefined;

/**
 * The base implementation of `_.toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value;
  }
  if (isArray(value)) {
    // Recursively convert values (susceptible to call stack limits).
    return arrayMap(value, baseToString) + '';
  }
  if (isSymbol(value)) {
    return symbolToString ? symbolToString.call(value) : '';
  }
  var result = value + '';
  return result == '0' && 1 / value == -INFINITY ? '-0' : result;
}

module.exports = baseToString;

/***/ }),
/* 173 */
/***/ (function(module, exports) {

/**
 * Checks if a `cache` value for `key` exists.
 *
 * @private
 * @param {Object} cache The cache to query.
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function cacheHas(cache, key) {
  return cache.has(key);
}

module.exports = cacheHas;

/***/ }),
/* 174 */
/***/ (function(module, exports, __webpack_require__) {

var cloneArrayBuffer = __webpack_require__(50);

/**
 * Creates a clone of `dataView`.
 *
 * @private
 * @param {Object} dataView The data view to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned data view.
 */
function cloneDataView(dataView, isDeep) {
  var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
  return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
}

module.exports = cloneDataView;

/***/ }),
/* 175 */
/***/ (function(module, exports) {

/** Used to match `RegExp` flags from their coerced string values. */
var reFlags = /\w*$/;

/**
 * Creates a clone of `regexp`.
 *
 * @private
 * @param {Object} regexp The regexp to clone.
 * @returns {Object} Returns the cloned regexp.
 */
function cloneRegExp(regexp) {
  var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
  result.lastIndex = regexp.lastIndex;
  return result;
}

module.exports = cloneRegExp;

/***/ }),
/* 176 */
/***/ (function(module, exports, __webpack_require__) {

var _Symbol = __webpack_require__(11);

/** Used to convert symbols to primitives and strings. */
var symbolProto = _Symbol ? _Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

/**
 * Creates a clone of the `symbol` object.
 *
 * @private
 * @param {Object} symbol The symbol object to clone.
 * @returns {Object} Returns the cloned symbol object.
 */
function cloneSymbol(symbol) {
  return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
}

module.exports = cloneSymbol;

/***/ }),
/* 177 */
/***/ (function(module, exports, __webpack_require__) {

var copyObject = __webpack_require__(12),
    getSymbols = __webpack_require__(53);

/**
 * Copies own symbols of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy symbols from.
 * @param {Object} [object={}] The object to copy symbols to.
 * @returns {Object} Returns `object`.
 */
function copySymbols(source, object) {
  return copyObject(source, getSymbols(source), object);
}

module.exports = copySymbols;

/***/ }),
/* 178 */
/***/ (function(module, exports, __webpack_require__) {

var copyObject = __webpack_require__(12),
    getSymbolsIn = __webpack_require__(91);

/**
 * Copies own and inherited symbols of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy symbols from.
 * @param {Object} [object={}] The object to copy symbols to.
 * @returns {Object} Returns `object`.
 */
function copySymbolsIn(source, object) {
  return copyObject(source, getSymbolsIn(source), object);
}

module.exports = copySymbolsIn;

/***/ }),
/* 179 */
/***/ (function(module, exports, __webpack_require__) {

var root = __webpack_require__(1);

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

module.exports = coreJsData;

/***/ }),
/* 180 */
/***/ (function(module, exports) {

/**
 * Gets the number of `placeholder` occurrences in `array`.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} placeholder The placeholder to search for.
 * @returns {number} Returns the placeholder count.
 */
function countHolders(array, placeholder) {
  var length = array.length,
      result = 0;

  while (length--) {
    if (array[length] === placeholder) {
      ++result;
    }
  }
  return result;
}

module.exports = countHolders;

/***/ }),
/* 181 */
/***/ (function(module, exports) {

/**
 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
 *
 * @private
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseFor(fromRight) {
  return function (object, iteratee, keysFunc) {
    var index = -1,
        iterable = Object(object),
        props = keysFunc(object),
        length = props.length;

    while (length--) {
      var key = props[fromRight ? length : ++index];
      if (iteratee(iterable[key], key, iterable) === false) {
        break;
      }
    }
    return object;
  };
}

module.exports = createBaseFor;

/***/ }),
/* 182 */
/***/ (function(module, exports, __webpack_require__) {

var createCtor = __webpack_require__(27),
    root = __webpack_require__(1);

/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1;

/**
 * Creates a function that wraps `func` to invoke it with the optional `this`
 * binding of `thisArg`.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
 * @param {*} [thisArg] The `this` binding of `func`.
 * @returns {Function} Returns the new wrapped function.
 */
function createBind(func, bitmask, thisArg) {
  var isBind = bitmask & WRAP_BIND_FLAG,
      Ctor = createCtor(func);

  function wrapper() {
    var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
    return fn.apply(isBind ? thisArg : this, arguments);
  }
  return wrapper;
}

module.exports = createBind;

/***/ }),
/* 183 */
/***/ (function(module, exports, __webpack_require__) {

var apply = __webpack_require__(42),
    createCtor = __webpack_require__(27),
    createHybrid = __webpack_require__(83),
    createRecurry = __webpack_require__(84),
    getHolder = __webpack_require__(90),
    replaceHolders = __webpack_require__(56),
    root = __webpack_require__(1);

/**
 * Creates a function that wraps `func` to enable currying.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
 * @param {number} arity The arity of `func`.
 * @returns {Function} Returns the new wrapped function.
 */
function createCurry(func, bitmask, arity) {
  var Ctor = createCtor(func);

  function wrapper() {
    var length = arguments.length,
        args = Array(length),
        index = length,
        placeholder = getHolder(wrapper);

    while (index--) {
      args[index] = arguments[index];
    }
    var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder);

    length -= holders.length;
    if (length < arity) {
      return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, undefined, args, holders, undefined, undefined, arity - length);
    }
    var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
    return apply(fn, this, args);
  }
  return wrapper;
}

module.exports = createCurry;

/***/ }),
/* 184 */
/***/ (function(module, exports, __webpack_require__) {

var apply = __webpack_require__(42),
    createCtor = __webpack_require__(27),
    root = __webpack_require__(1);

/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1;

/**
 * Creates a function that wraps `func` to invoke it with the `this` binding
 * of `thisArg` and `partials` prepended to the arguments it receives.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
 * @param {*} thisArg The `this` binding of `func`.
 * @param {Array} partials The arguments to prepend to those provided to
 *  the new function.
 * @returns {Function} Returns the new wrapped function.
 */
function createPartial(func, bitmask, thisArg, partials) {
  var isBind = bitmask & WRAP_BIND_FLAG,
      Ctor = createCtor(func);

  function wrapper() {
    var argsIndex = -1,
        argsLength = arguments.length,
        leftIndex = -1,
        leftLength = partials.length,
        args = Array(leftLength + argsLength),
        fn = this && this !== root && this instanceof wrapper ? Ctor : func;

    while (++leftIndex < leftLength) {
      args[leftIndex] = partials[leftIndex];
    }
    while (argsLength--) {
      args[leftIndex++] = arguments[++argsIndex];
    }
    return apply(fn, isBind ? thisArg : this, args);
  }
  return wrapper;
}

module.exports = createPartial;

/***/ }),
/* 185 */
/***/ (function(module, exports, __webpack_require__) {

var _Symbol = __webpack_require__(11),
    Uint8Array = __webpack_require__(66),
    eq = __webpack_require__(17),
    equalArrays = __webpack_require__(86),
    mapToArray = __webpack_require__(218),
    setToArray = __webpack_require__(228);

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/** `Object#toString` result references. */
var boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]';

/** Used to convert symbols to primitives and strings. */
var symbolProto = _Symbol ? _Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
  switch (tag) {
    case dataViewTag:
      if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
        return false;
      }
      object = object.buffer;
      other = other.buffer;

    case arrayBufferTag:
      if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
        return false;
      }
      return true;

    case boolTag:
    case dateTag:
    case numberTag:
      // Coerce booleans to `1` or `0` and dates to milliseconds.
      // Invalid dates are coerced to `NaN`.
      return eq(+object, +other);

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings, primitives and objects,
      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
      // for more details.
      return object == other + '';

    case mapTag:
      var convert = mapToArray;

    case setTag:
      var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
      convert || (convert = setToArray);

      if (object.size != other.size && !isPartial) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked) {
        return stacked == other;
      }
      bitmask |= COMPARE_UNORDERED_FLAG;

      // Recursively compare objects (susceptible to call stack limits).
      stack.set(object, other);
      var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
      stack['delete'](object);
      return result;

    case symbolTag:
      if (symbolValueOf) {
        return symbolValueOf.call(object) == symbolValueOf.call(other);
      }
  }
  return false;
}

module.exports = equalByTag;

/***/ }),
/* 186 */
/***/ (function(module, exports, __webpack_require__) {

var getAllKeys = __webpack_require__(88);

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1;

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      objProps = getAllKeys(object),
      objLength = objProps.length,
      othProps = getAllKeys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isPartial) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(object);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var result = true;
  stack.set(object, other);
  stack.set(other, object);

  var skipCtor = isPartial;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key];

    if (customizer) {
      var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
    }
    // Recursively compare objects (susceptible to call stack limits).
    if (!(compared === undefined ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
      result = false;
      break;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (result && !skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor && 'constructor' in object && 'constructor' in other && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      result = false;
    }
  }
  stack['delete'](object);
  stack['delete'](other);
  return result;
}

module.exports = equalObjects;

/***/ }),
/* 187 */
/***/ (function(module, exports, __webpack_require__) {

var flatten = __webpack_require__(243),
    overRest = __webpack_require__(97),
    setToString = __webpack_require__(57);

/**
 * A specialized version of `baseRest` which flattens the rest array.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @returns {Function} Returns the new function.
 */
function flatRest(func) {
  return setToString(overRest(func, undefined, flatten), func + '');
}

module.exports = flatRest;

/***/ }),
/* 188 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetAllKeys = __webpack_require__(74),
    getSymbolsIn = __webpack_require__(91),
    keysIn = __webpack_require__(22);

/**
 * Creates an array of own and inherited enumerable property names and
 * symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names and symbols.
 */
function getAllKeysIn(object) {
  return baseGetAllKeys(object, keysIn, getSymbolsIn);
}

module.exports = getAllKeysIn;

/***/ }),
/* 189 */
/***/ (function(module, exports, __webpack_require__) {

var realNames = __webpack_require__(224);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Gets the name of `func`.
 *
 * @private
 * @param {Function} func The function to query.
 * @returns {string} Returns the function name.
 */
function getFuncName(func) {
  var result = func.name + '',
      array = realNames[result],
      length = hasOwnProperty.call(realNames, result) ? array.length : 0;

  while (length--) {
    var data = array[length],
        otherFunc = data.func;
    if (otherFunc == null || otherFunc == func) {
      return data.name;
    }
  }
  return result;
}

module.exports = getFuncName;

/***/ }),
/* 190 */
/***/ (function(module, exports, __webpack_require__) {

var isStrictComparable = __webpack_require__(93),
    keys = __webpack_require__(36);

/**
 * Gets the property names, values, and compare flags of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the match data of `object`.
 */
function getMatchData(object) {
    var result = keys(object),
        length = result.length;

    while (length--) {
        var key = result[length],
            value = object[key];

        result[length] = [key, value, isStrictComparable(value)];
    }
    return result;
}

module.exports = getMatchData;

/***/ }),
/* 191 */
/***/ (function(module, exports, __webpack_require__) {

var _Symbol = __webpack_require__(11);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/** Built-in value references. */
var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;

/**
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the raw `toStringTag`.
 */
function getRawTag(value) {
  var isOwn = hasOwnProperty.call(value, symToStringTag),
      tag = value[symToStringTag];

  try {
    value[symToStringTag] = undefined;
    var unmasked = true;
  } catch (e) {}

  var result = nativeObjectToString.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag;
    } else {
      delete value[symToStringTag];
    }
  }
  return result;
}

module.exports = getRawTag;

/***/ }),
/* 192 */
/***/ (function(module, exports) {

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

module.exports = getValue;

/***/ }),
/* 193 */
/***/ (function(module, exports) {

/** Used to match wrap detail comments. */
var reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
    reSplitDetails = /,? & /;

/**
 * Extracts wrapper details from the `source` body comment.
 *
 * @private
 * @param {string} source The source to inspect.
 * @returns {Array} Returns the wrapper details.
 */
function getWrapDetails(source) {
  var match = source.match(reWrapDetails);
  return match ? match[1].split(reSplitDetails) : [];
}

module.exports = getWrapDetails;

/***/ }),
/* 194 */
/***/ (function(module, exports, __webpack_require__) {

var castPath = __webpack_require__(77),
    isArguments = __webpack_require__(18),
    isArray = __webpack_require__(0),
    isIndex = __webpack_require__(29),
    isLength = __webpack_require__(58),
    toKey = __webpack_require__(16);

/**
 * Checks if `path` exists on `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @param {Function} hasFunc The function to check properties.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 */
function hasPath(object, path, hasFunc) {
  path = castPath(path, object);

  var index = -1,
      length = path.length,
      result = false;

  while (++index < length) {
    var key = toKey(path[index]);
    if (!(result = object != null && hasFunc(object, key))) {
      break;
    }
    object = object[key];
  }
  if (result || ++index != length) {
    return result;
  }
  length = object == null ? 0 : object.length;
  return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
}

module.exports = hasPath;

/***/ }),
/* 195 */
/***/ (function(module, exports, __webpack_require__) {

var nativeCreate = __webpack_require__(31);

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
  this.size = 0;
}

module.exports = hashClear;

/***/ }),
/* 196 */
/***/ (function(module, exports) {

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  var result = this.has(key) && delete this.__data__[key];
  this.size -= result ? 1 : 0;
  return result;
}

module.exports = hashDelete;

/***/ }),
/* 197 */
/***/ (function(module, exports, __webpack_require__) {

var nativeCreate = __webpack_require__(31);

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

module.exports = hashGet;

/***/ }),
/* 198 */
/***/ (function(module, exports, __webpack_require__) {

var nativeCreate = __webpack_require__(31);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
}

module.exports = hashHas;

/***/ }),
/* 199 */
/***/ (function(module, exports, __webpack_require__) {

var nativeCreate = __webpack_require__(31);

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  this.size += this.has(key) ? 0 : 1;
  data[key] = nativeCreate && value === undefined ? HASH_UNDEFINED : value;
  return this;
}

module.exports = hashSet;

/***/ }),
/* 200 */
/***/ (function(module, exports) {

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Initializes an array clone.
 *
 * @private
 * @param {Array} array The array to clone.
 * @returns {Array} Returns the initialized clone.
 */
function initCloneArray(array) {
  var length = array.length,
      result = new array.constructor(length);

  // Add properties assigned by `RegExp#exec`.
  if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
    result.index = array.index;
    result.input = array.input;
  }
  return result;
}

module.exports = initCloneArray;

/***/ }),
/* 201 */
/***/ (function(module, exports, __webpack_require__) {

var cloneArrayBuffer = __webpack_require__(50),
    cloneDataView = __webpack_require__(174),
    cloneRegExp = __webpack_require__(175),
    cloneSymbol = __webpack_require__(176),
    cloneTypedArray = __webpack_require__(79);

/** `Object#toString` result references. */
var boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/**
 * Initializes an object clone based on its `toStringTag`.
 *
 * **Note:** This function only supports cloning values with tags of
 * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
 *
 * @private
 * @param {Object} object The object to clone.
 * @param {string} tag The `toStringTag` of the object to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the initialized clone.
 */
function initCloneByTag(object, tag, isDeep) {
  var Ctor = object.constructor;
  switch (tag) {
    case arrayBufferTag:
      return cloneArrayBuffer(object);

    case boolTag:
    case dateTag:
      return new Ctor(+object);

    case dataViewTag:
      return cloneDataView(object, isDeep);

    case float32Tag:case float64Tag:
    case int8Tag:case int16Tag:case int32Tag:
    case uint8Tag:case uint8ClampedTag:case uint16Tag:case uint32Tag:
      return cloneTypedArray(object, isDeep);

    case mapTag:
      return new Ctor();

    case numberTag:
    case stringTag:
      return new Ctor(object);

    case regexpTag:
      return cloneRegExp(object);

    case setTag:
      return new Ctor();

    case symbolTag:
      return cloneSymbol(object);
  }
}

module.exports = initCloneByTag;

/***/ }),
/* 202 */
/***/ (function(module, exports) {

/** Used to match wrap detail comments. */
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/;

/**
 * Inserts wrapper `details` in a comment at the top of the `source` body.
 *
 * @private
 * @param {string} source The source to modify.
 * @returns {Array} details The details to insert.
 * @returns {string} Returns the modified source.
 */
function insertWrapDetails(source, details) {
  var length = details.length;
  if (!length) {
    return source;
  }
  var lastIndex = length - 1;
  details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
  details = details.join(length > 2 ? ', ' : ' ');
  return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
}

module.exports = insertWrapDetails;

/***/ }),
/* 203 */
/***/ (function(module, exports, __webpack_require__) {

var _Symbol = __webpack_require__(11),
    isArguments = __webpack_require__(18),
    isArray = __webpack_require__(0);

/** Built-in value references. */
var spreadableSymbol = _Symbol ? _Symbol.isConcatSpreadable : undefined;

/**
 * Checks if `value` is a flattenable `arguments` object or array.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
 */
function isFlattenable(value) {
    return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
}

module.exports = isFlattenable;

/***/ }),
/* 204 */
/***/ (function(module, exports, __webpack_require__) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var eq = __webpack_require__(17),
    isArrayLike = __webpack_require__(19),
    isIndex = __webpack_require__(29),
    isObject = __webpack_require__(4);

/**
 * Checks if the given arguments are from an iteratee call.
 *
 * @private
 * @param {*} value The potential iteratee value argument.
 * @param {*} index The potential iteratee index or key argument.
 * @param {*} object The potential iteratee object argument.
 * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
 *  else `false`.
 */
function isIterateeCall(value, index, object) {
  if (!isObject(object)) {
    return false;
  }
  var type = typeof index === 'undefined' ? 'undefined' : _typeof(index);
  if (type == 'number' ? isArrayLike(object) && isIndex(index, object.length) : type == 'string' && index in object) {
    return eq(object[index], value);
  }
  return false;
}

module.exports = isIterateeCall;

/***/ }),
/* 205 */
/***/ (function(module, exports) {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
  return type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean' ? value !== '__proto__' : value === null;
}

module.exports = isKeyable;

/***/ }),
/* 206 */
/***/ (function(module, exports, __webpack_require__) {

var LazyWrapper = __webpack_require__(39),
    getData = __webpack_require__(89),
    getFuncName = __webpack_require__(189),
    lodash = __webpack_require__(273);

/**
 * Checks if `func` has a lazy counterpart.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
 *  else `false`.
 */
function isLaziable(func) {
  var funcName = getFuncName(func),
      other = lodash[funcName];

  if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
    return false;
  }
  if (func === other) {
    return true;
  }
  var data = getData(other);
  return !!data && func === data[0];
}

module.exports = isLaziable;

/***/ }),
/* 207 */
/***/ (function(module, exports, __webpack_require__) {

var coreJsData = __webpack_require__(179);

/** Used to detect methods masquerading as native. */
var maskSrcKey = function () {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? 'Symbol(src)_1.' + uid : '';
}();

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && maskSrcKey in func;
}

module.exports = isMasked;

/***/ }),
/* 208 */
/***/ (function(module, exports) {

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
  this.size = 0;
}

module.exports = listCacheClear;

/***/ }),
/* 209 */
/***/ (function(module, exports, __webpack_require__) {

var assocIndexOf = __webpack_require__(25);

/** Used for built-in method references. */
var arrayProto = Array.prototype;

/** Built-in value references. */
var splice = arrayProto.splice;

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  --this.size;
  return true;
}

module.exports = listCacheDelete;

/***/ }),
/* 210 */
/***/ (function(module, exports, __webpack_require__) {

var assocIndexOf = __webpack_require__(25);

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

module.exports = listCacheGet;

/***/ }),
/* 211 */
/***/ (function(module, exports, __webpack_require__) {

var assocIndexOf = __webpack_require__(25);

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

module.exports = listCacheHas;

/***/ }),
/* 212 */
/***/ (function(module, exports, __webpack_require__) {

var assocIndexOf = __webpack_require__(25);

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    ++this.size;
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

module.exports = listCacheSet;

/***/ }),
/* 213 */
/***/ (function(module, exports, __webpack_require__) {

var Hash = __webpack_require__(140),
    ListCache = __webpack_require__(23),
    Map = __webpack_require__(40);

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.size = 0;
  this.__data__ = {
    'hash': new Hash(),
    'map': new (Map || ListCache)(),
    'string': new Hash()
  };
}

module.exports = mapCacheClear;

/***/ }),
/* 214 */
/***/ (function(module, exports, __webpack_require__) {

var getMapData = __webpack_require__(28);

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  var result = getMapData(this, key)['delete'](key);
  this.size -= result ? 1 : 0;
  return result;
}

module.exports = mapCacheDelete;

/***/ }),
/* 215 */
/***/ (function(module, exports, __webpack_require__) {

var getMapData = __webpack_require__(28);

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

module.exports = mapCacheGet;

/***/ }),
/* 216 */
/***/ (function(module, exports, __webpack_require__) {

var getMapData = __webpack_require__(28);

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

module.exports = mapCacheHas;

/***/ }),
/* 217 */
/***/ (function(module, exports, __webpack_require__) {

var getMapData = __webpack_require__(28);

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  var data = getMapData(this, key),
      size = data.size;

  data.set(key, value);
  this.size += data.size == size ? 0 : 1;
  return this;
}

module.exports = mapCacheSet;

/***/ }),
/* 218 */
/***/ (function(module, exports) {

/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function (value, key) {
    result[++index] = [key, value];
  });
  return result;
}

module.exports = mapToArray;

/***/ }),
/* 219 */
/***/ (function(module, exports, __webpack_require__) {

var memoize = __webpack_require__(263);

/** Used as the maximum memoize cache size. */
var MAX_MEMOIZE_SIZE = 500;

/**
 * A specialized version of `_.memoize` which clears the memoized function's
 * cache when it exceeds `MAX_MEMOIZE_SIZE`.
 *
 * @private
 * @param {Function} func The function to have its output memoized.
 * @returns {Function} Returns the new memoized function.
 */
function memoizeCapped(func) {
  var result = memoize(func, function (key) {
    if (cache.size === MAX_MEMOIZE_SIZE) {
      cache.clear();
    }
    return key;
  });

  var cache = result.cache;
  return result;
}

module.exports = memoizeCapped;

/***/ }),
/* 220 */
/***/ (function(module, exports, __webpack_require__) {

var composeArgs = __webpack_require__(80),
    composeArgsRight = __webpack_require__(81),
    replaceHolders = __webpack_require__(56);

/** Used as the internal argument placeholder. */
var PLACEHOLDER = '__lodash_placeholder__';

/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1,
    WRAP_BIND_KEY_FLAG = 2,
    WRAP_CURRY_BOUND_FLAG = 4,
    WRAP_CURRY_FLAG = 8,
    WRAP_ARY_FLAG = 128,
    WRAP_REARG_FLAG = 256;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMin = Math.min;

/**
 * Merges the function metadata of `source` into `data`.
 *
 * Merging metadata reduces the number of wrappers used to invoke a function.
 * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
 * may be applied regardless of execution order. Methods like `_.ary` and
 * `_.rearg` modify function arguments, making the order in which they are
 * executed important, preventing the merging of metadata. However, we make
 * an exception for a safe combined case where curried functions have `_.ary`
 * and or `_.rearg` applied.
 *
 * @private
 * @param {Array} data The destination metadata.
 * @param {Array} source The source metadata.
 * @returns {Array} Returns `data`.
 */
function mergeData(data, source) {
  var bitmask = data[1],
      srcBitmask = source[1],
      newBitmask = bitmask | srcBitmask,
      isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);

  var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG;

  // Exit early if metadata can't be merged.
  if (!(isCommon || isCombo)) {
    return data;
  }
  // Use source `thisArg` if available.
  if (srcBitmask & WRAP_BIND_FLAG) {
    data[2] = source[2];
    // Set when currying a bound function.
    newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
  }
  // Compose partial arguments.
  var value = source[3];
  if (value) {
    var partials = data[3];
    data[3] = partials ? composeArgs(partials, value, source[4]) : value;
    data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
  }
  // Compose partial right arguments.
  value = source[5];
  if (value) {
    partials = data[5];
    data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
    data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
  }
  // Use source `argPos` if available.
  value = source[7];
  if (value) {
    data[7] = value;
  }
  // Use source `ary` if it's smaller.
  if (srcBitmask & WRAP_ARY_FLAG) {
    data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
  }
  // Use source `arity` if one is not provided.
  if (data[9] == null) {
    data[9] = source[9];
  }
  // Use source `func` and merge bitmasks.
  data[0] = source[0];
  data[1] = newBitmask;

  return data;
}

module.exports = mergeData;

/***/ }),
/* 221 */
/***/ (function(module, exports, __webpack_require__) {

var overArg = __webpack_require__(96);

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeKeys = overArg(Object.keys, Object);

module.exports = nativeKeys;

/***/ }),
/* 222 */
/***/ (function(module, exports) {

/**
 * This function is like
 * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * except that it includes inherited enumerable properties.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function nativeKeysIn(object) {
  var result = [];
  if (object != null) {
    for (var key in Object(object)) {
      result.push(key);
    }
  }
  return result;
}

module.exports = nativeKeysIn;

/***/ }),
/* 223 */
/***/ (function(module, exports) {

/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/**
 * Converts `value` to a string using `Object.prototype.toString`.
 *
 * @private
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 */
function objectToString(value) {
  return nativeObjectToString.call(value);
}

module.exports = objectToString;

/***/ }),
/* 224 */
/***/ (function(module, exports) {

/** Used to lookup unminified function names. */
var realNames = {};

module.exports = realNames;

/***/ }),
/* 225 */
/***/ (function(module, exports, __webpack_require__) {

var copyArray = __webpack_require__(15),
    isIndex = __webpack_require__(29);

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMin = Math.min;

/**
 * Reorder `array` according to the specified indexes where the element at
 * the first index is assigned as the first element, the element at
 * the second index is assigned as the second element, and so on.
 *
 * @private
 * @param {Array} array The array to reorder.
 * @param {Array} indexes The arranged array indexes.
 * @returns {Array} Returns `array`.
 */
function reorder(array, indexes) {
  var arrLength = array.length,
      length = nativeMin(indexes.length, arrLength),
      oldArray = copyArray(array);

  while (length--) {
    var index = indexes[length];
    array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
  }
  return array;
}

module.exports = reorder;

/***/ }),
/* 226 */
/***/ (function(module, exports) {

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

module.exports = setCacheAdd;

/***/ }),
/* 227 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

module.exports = setCacheHas;

/***/ }),
/* 228 */
/***/ (function(module, exports) {

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function (value) {
    result[++index] = value;
  });
  return result;
}

module.exports = setToArray;

/***/ }),
/* 229 */
/***/ (function(module, exports, __webpack_require__) {

var ListCache = __webpack_require__(23);

/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new ListCache();
  this.size = 0;
}

module.exports = stackClear;

/***/ }),
/* 230 */
/***/ (function(module, exports) {

/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  var data = this.__data__,
      result = data['delete'](key);

  this.size = data.size;
  return result;
}

module.exports = stackDelete;

/***/ }),
/* 231 */
/***/ (function(module, exports) {

/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

module.exports = stackGet;

/***/ }),
/* 232 */
/***/ (function(module, exports) {

/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

module.exports = stackHas;

/***/ }),
/* 233 */
/***/ (function(module, exports, __webpack_require__) {

var ListCache = __webpack_require__(23),
    Map = __webpack_require__(40),
    MapCache = __webpack_require__(41);

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var data = this.__data__;
  if (data instanceof ListCache) {
    var pairs = data.__data__;
    if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) {
      pairs.push([key, value]);
      this.size = ++data.size;
      return this;
    }
    data = this.__data__ = new MapCache(pairs);
  }
  data.set(key, value);
  this.size = data.size;
  return this;
}

module.exports = stackSet;

/***/ }),
/* 234 */
/***/ (function(module, exports) {

/**
 * A specialized version of `_.indexOf` which performs strict equality
 * comparisons of values, i.e. `===`.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} value The value to search for.
 * @param {number} fromIndex The index to search from.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function strictIndexOf(array, value, fromIndex) {
  var index = fromIndex - 1,
      length = array.length;

  while (++index < length) {
    if (array[index] === value) {
      return index;
    }
  }
  return -1;
}

module.exports = strictIndexOf;

/***/ }),
/* 235 */
/***/ (function(module, exports, __webpack_require__) {

var arrayEach = __webpack_require__(43),
    arrayIncludes = __webpack_require__(145);

/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1,
    WRAP_BIND_KEY_FLAG = 2,
    WRAP_CURRY_FLAG = 8,
    WRAP_CURRY_RIGHT_FLAG = 16,
    WRAP_PARTIAL_FLAG = 32,
    WRAP_PARTIAL_RIGHT_FLAG = 64,
    WRAP_ARY_FLAG = 128,
    WRAP_REARG_FLAG = 256,
    WRAP_FLIP_FLAG = 512;

/** Used to associate wrap methods with their bit flags. */
var wrapFlags = [['ary', WRAP_ARY_FLAG], ['bind', WRAP_BIND_FLAG], ['bindKey', WRAP_BIND_KEY_FLAG], ['curry', WRAP_CURRY_FLAG], ['curryRight', WRAP_CURRY_RIGHT_FLAG], ['flip', WRAP_FLIP_FLAG], ['partial', WRAP_PARTIAL_FLAG], ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], ['rearg', WRAP_REARG_FLAG]];

/**
 * Updates wrapper `details` based on `bitmask` flags.
 *
 * @private
 * @returns {Array} details The details to modify.
 * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
 * @returns {Array} Returns `details`.
 */
function updateWrapDetails(details, bitmask) {
  arrayEach(wrapFlags, function (pair) {
    var value = '_.' + pair[0];
    if (bitmask & pair[1] && !arrayIncludes(details, value)) {
      details.push(value);
    }
  });
  return details.sort();
}

module.exports = updateWrapDetails;

/***/ }),
/* 236 */
/***/ (function(module, exports, __webpack_require__) {

var LazyWrapper = __webpack_require__(39),
    LodashWrapper = __webpack_require__(65),
    copyArray = __webpack_require__(15);

/**
 * Creates a clone of `wrapper`.
 *
 * @private
 * @param {Object} wrapper The wrapper to clone.
 * @returns {Object} Returns the cloned wrapper.
 */
function wrapperClone(wrapper) {
  if (wrapper instanceof LazyWrapper) {
    return wrapper.clone();
  }
  var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
  result.__actions__ = copyArray(wrapper.__actions__);
  result.__index__ = wrapper.__index__;
  result.__values__ = wrapper.__values__;
  return result;
}

module.exports = wrapperClone;

/***/ }),
/* 237 */
/***/ (function(module, exports, __webpack_require__) {

var createWrap = __webpack_require__(51);

/** Used to compose bitmasks for function metadata. */
var WRAP_ARY_FLAG = 128;

/**
 * Creates a function that invokes `func`, with up to `n` arguments,
 * ignoring any additional arguments.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Function
 * @param {Function} func The function to cap arguments for.
 * @param {number} [n=func.length] The arity cap.
 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
 * @returns {Function} Returns the new capped function.
 * @example
 *
 * _.map(['6', '8', '10'], _.ary(parseInt, 1));
 * // => [6, 8, 10]
 */
function ary(func, n, guard) {
  n = guard ? undefined : n;
  n = func && n == null ? func.length : n;
  return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
}

module.exports = ary;

/***/ }),
/* 238 */
/***/ (function(module, exports, __webpack_require__) {

var copyObject = __webpack_require__(12),
    createAssigner = __webpack_require__(82),
    keysIn = __webpack_require__(22);

/**
 * This method is like `_.assign` except that it iterates over own and
 * inherited source properties.
 *
 * **Note:** This method mutates `object`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @alias extend
 * @category Object
 * @param {Object} object The destination object.
 * @param {...Object} [sources] The source objects.
 * @returns {Object} Returns `object`.
 * @see _.assign
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 * }
 *
 * function Bar() {
 *   this.c = 3;
 * }
 *
 * Foo.prototype.b = 2;
 * Bar.prototype.d = 4;
 *
 * _.assignIn({ 'a': 0 }, new Foo, new Bar);
 * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
 */
var assignIn = createAssigner(function (object, source) {
  copyObject(source, keysIn(source), object);
});

module.exports = assignIn;

/***/ }),
/* 239 */
/***/ (function(module, exports, __webpack_require__) {

var baseClone = __webpack_require__(46);

/** Used to compose bitmasks for cloning. */
var CLONE_SYMBOLS_FLAG = 4;

/**
 * Creates a shallow clone of `value`.
 *
 * **Note:** This method is loosely based on the
 * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
 * and supports cloning arrays, array buffers, booleans, date objects, maps,
 * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
 * arrays. The own enumerable properties of `arguments` objects are cloned
 * as plain objects. An empty object is returned for uncloneable values such
 * as error objects, functions, DOM nodes, and WeakMaps.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to clone.
 * @returns {*} Returns the cloned value.
 * @see _.cloneDeep
 * @example
 *
 * var objects = [{ 'a': 1 }, { 'b': 2 }];
 *
 * var shallow = _.clone(objects);
 * console.log(shallow[0] === objects[0]);
 * // => true
 */
function clone(value) {
  return baseClone(value, CLONE_SYMBOLS_FLAG);
}

module.exports = clone;

/***/ }),
/* 240 */
/***/ (function(module, exports, __webpack_require__) {

var baseClone = __webpack_require__(46);

/** Used to compose bitmasks for cloning. */
var CLONE_DEEP_FLAG = 1,
    CLONE_SYMBOLS_FLAG = 4;

/**
 * This method is like `_.clone` except that it recursively clones `value`.
 *
 * @static
 * @memberOf _
 * @since 1.0.0
 * @category Lang
 * @param {*} value The value to recursively clone.
 * @returns {*} Returns the deep cloned value.
 * @see _.clone
 * @example
 *
 * var objects = [{ 'a': 1 }, { 'b': 2 }];
 *
 * var deep = _.cloneDeep(objects);
 * console.log(deep[0] === objects[0]);
 * // => false
 */
function cloneDeep(value) {
  return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
}

module.exports = cloneDeep;

/***/ }),
/* 241 */
/***/ (function(module, exports) {

/**
 * Creates a function that returns `value`.
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Util
 * @param {*} value The value to return from the new function.
 * @returns {Function} Returns the new constant function.
 * @example
 *
 * var objects = _.times(2, _.constant({ 'a': 1 }));
 *
 * console.log(objects);
 * // => [{ 'a': 1 }, { 'a': 1 }]
 *
 * console.log(objects[0] === objects[1]);
 * // => true
 */
function constant(value) {
  return function () {
    return value;
  };
}

module.exports = constant;

/***/ }),
/* 242 */
/***/ (function(module, exports, __webpack_require__) {

var createWrap = __webpack_require__(51);

/** Used to compose bitmasks for function metadata. */
var WRAP_CURRY_FLAG = 8;

/**
 * Creates a function that accepts arguments of `func` and either invokes
 * `func` returning its result, if at least `arity` number of arguments have
 * been provided, or returns a function that accepts the remaining `func`
 * arguments, and so on. The arity of `func` may be specified if `func.length`
 * is not sufficient.
 *
 * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
 * may be used as a placeholder for provided arguments.
 *
 * **Note:** This method doesn't set the "length" property of curried functions.
 *
 * @static
 * @memberOf _
 * @since 2.0.0
 * @category Function
 * @param {Function} func The function to curry.
 * @param {number} [arity=func.length] The arity of `func`.
 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
 * @returns {Function} Returns the new curried function.
 * @example
 *
 * var abc = function(a, b, c) {
 *   return [a, b, c];
 * };
 *
 * var curried = _.curry(abc);
 *
 * curried(1)(2)(3);
 * // => [1, 2, 3]
 *
 * curried(1, 2)(3);
 * // => [1, 2, 3]
 *
 * curried(1, 2, 3);
 * // => [1, 2, 3]
 *
 * // Curried with placeholders.
 * curried(1)(_, 3)(2);
 * // => [1, 2, 3]
 */
function curry(func, arity, guard) {
  arity = guard ? undefined : arity;
  var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
  result.placeholder = curry.placeholder;
  return result;
}

// Assign default placeholders.
curry.placeholder = {};

module.exports = curry;

/***/ }),
/* 243 */
/***/ (function(module, exports, __webpack_require__) {

var baseFlatten = __webpack_require__(149);

/**
 * Flattens `array` a single level deep.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Array
 * @param {Array} array The array to flatten.
 * @returns {Array} Returns the new flattened array.
 * @example
 *
 * _.flatten([1, [2, [3, [4]], 5]]);
 * // => [1, 2, [3, [4]], 5]
 */
function flatten(array) {
  var length = array == null ? 0 : array.length;
  return length ? baseFlatten(array, 1) : [];
}

module.exports = flatten;

/***/ }),
/* 244 */
/***/ (function(module, exports, __webpack_require__) {

var mapping = __webpack_require__(245),
    fallbackHolder = __webpack_require__(9);

/** Built-in value reference. */
var push = Array.prototype.push;

/**
 * Creates a function, with an arity of `n`, that invokes `func` with the
 * arguments it receives.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {number} n The arity of the new function.
 * @returns {Function} Returns the new function.
 */
function baseArity(func, n) {
  return n == 2 ? function (a, b) {
    return func.apply(undefined, arguments);
  } : function (a) {
    return func.apply(undefined, arguments);
  };
}

/**
 * Creates a function that invokes `func`, with up to `n` arguments, ignoring
 * any additional arguments.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @param {number} n The arity cap.
 * @returns {Function} Returns the new function.
 */
function baseAry(func, n) {
  return n == 2 ? function (a, b) {
    return func(a, b);
  } : function (a) {
    return func(a);
  };
}

/**
 * Creates a clone of `array`.
 *
 * @private
 * @param {Array} array The array to clone.
 * @returns {Array} Returns the cloned array.
 */
function cloneArray(array) {
  var length = array ? array.length : 0,
      result = Array(length);

  while (length--) {
    result[length] = array[length];
  }
  return result;
}

/**
 * Creates a function that clones a given object using the assignment `func`.
 *
 * @private
 * @param {Function} func The assignment function.
 * @returns {Function} Returns the new cloner function.
 */
function createCloner(func) {
  return function (object) {
    return func({}, object);
  };
}

/**
 * A specialized version of `_.spread` which flattens the spread array into
 * the arguments of the invoked `func`.
 *
 * @private
 * @param {Function} func The function to spread arguments over.
 * @param {number} start The start position of the spread.
 * @returns {Function} Returns the new function.
 */
function flatSpread(func, start) {
  return function () {
    var length = arguments.length,
        lastIndex = length - 1,
        args = Array(length);

    while (length--) {
      args[length] = arguments[length];
    }
    var array = args[start],
        otherArgs = args.slice(0, start);

    if (array) {
      push.apply(otherArgs, array);
    }
    if (start != lastIndex) {
      push.apply(otherArgs, args.slice(start + 1));
    }
    return func.apply(this, otherArgs);
  };
}

/**
 * Creates a function that wraps `func` and uses `cloner` to clone the first
 * argument it receives.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} cloner The function to clone arguments.
 * @returns {Function} Returns the new immutable function.
 */
function wrapImmutable(func, cloner) {
  return function () {
    var length = arguments.length;
    if (!length) {
      return;
    }
    var args = Array(length);
    while (length--) {
      args[length] = arguments[length];
    }
    var result = args[0] = cloner.apply(undefined, args);
    func.apply(undefined, args);
    return result;
  };
}

/**
 * The base implementation of `convert` which accepts a `util` object of methods
 * required to perform conversions.
 *
 * @param {Object} util The util object.
 * @param {string} name The name of the function to convert.
 * @param {Function} func The function to convert.
 * @param {Object} [options] The options object.
 * @param {boolean} [options.cap=true] Specify capping iteratee arguments.
 * @param {boolean} [options.curry=true] Specify currying.
 * @param {boolean} [options.fixed=true] Specify fixed arity.
 * @param {boolean} [options.immutable=true] Specify immutable operations.
 * @param {boolean} [options.rearg=true] Specify rearranging arguments.
 * @returns {Function|Object} Returns the converted function or object.
 */
function baseConvert(util, name, func, options) {
  var setPlaceholder,
      isLib = typeof name == 'function',
      isObj = name === Object(name);

  if (isObj) {
    options = func;
    func = name;
    name = undefined;
  }
  if (func == null) {
    throw new TypeError();
  }
  options || (options = {});

  var config = {
    'cap': 'cap' in options ? options.cap : true,
    'curry': 'curry' in options ? options.curry : true,
    'fixed': 'fixed' in options ? options.fixed : true,
    'immutable': 'immutable' in options ? options.immutable : true,
    'rearg': 'rearg' in options ? options.rearg : true
  };

  var forceCurry = 'curry' in options && options.curry,
      forceFixed = 'fixed' in options && options.fixed,
      forceRearg = 'rearg' in options && options.rearg,
      placeholder = isLib ? func : fallbackHolder,
      pristine = isLib ? func.runInContext() : undefined;

  var helpers = isLib ? func : {
    'ary': util.ary,
    'assign': util.assign,
    'clone': util.clone,
    'curry': util.curry,
    'forEach': util.forEach,
    'isArray': util.isArray,
    'isError': util.isError,
    'isFunction': util.isFunction,
    'isWeakMap': util.isWeakMap,
    'iteratee': util.iteratee,
    'keys': util.keys,
    'rearg': util.rearg,
    'toInteger': util.toInteger,
    'toPath': util.toPath
  };

  var ary = helpers.ary,
      assign = helpers.assign,
      clone = helpers.clone,
      curry = helpers.curry,
      each = helpers.forEach,
      isArray = helpers.isArray,
      isError = helpers.isError,
      isFunction = helpers.isFunction,
      isWeakMap = helpers.isWeakMap,
      keys = helpers.keys,
      rearg = helpers.rearg,
      toInteger = helpers.toInteger,
      toPath = helpers.toPath;

  var aryMethodKeys = keys(mapping.aryMethod);

  var wrappers = {
    'castArray': function castArray(_castArray) {
      return function () {
        var value = arguments[0];
        return isArray(value) ? _castArray(cloneArray(value)) : _castArray.apply(undefined, arguments);
      };
    },
    'iteratee': function iteratee(_iteratee) {
      return function () {
        var func = arguments[0],
            arity = arguments[1],
            result = _iteratee(func, arity),
            length = result.length;

        if (config.cap && typeof arity == 'number') {
          arity = arity > 2 ? arity - 2 : 1;
          return length && length <= arity ? result : baseAry(result, arity);
        }
        return result;
      };
    },
    'mixin': function mixin(_mixin) {
      return function (source) {
        var func = this;
        if (!isFunction(func)) {
          return _mixin(func, Object(source));
        }
        var pairs = [];
        each(keys(source), function (key) {
          if (isFunction(source[key])) {
            pairs.push([key, func.prototype[key]]);
          }
        });

        _mixin(func, Object(source));

        each(pairs, function (pair) {
          var value = pair[1];
          if (isFunction(value)) {
            func.prototype[pair[0]] = value;
          } else {
            delete func.prototype[pair[0]];
          }
        });
        return func;
      };
    },
    'nthArg': function nthArg(_nthArg) {
      return function (n) {
        var arity = n < 0 ? 1 : toInteger(n) + 1;
        return curry(_nthArg(n), arity);
      };
    },
    'rearg': function rearg(_rearg) {
      return function (func, indexes) {
        var arity = indexes ? indexes.length : 0;
        return curry(_rearg(func, indexes), arity);
      };
    },
    'runInContext': function runInContext(_runInContext) {
      return function (context) {
        return baseConvert(util, _runInContext(context), options);
      };
    }
  };

  /*--------------------------------------------------------------------------*/

  /**
   * Casts `func` to a function with an arity capped iteratee if needed.
   *
   * @private
   * @param {string} name The name of the function to inspect.
   * @param {Function} func The function to inspect.
   * @returns {Function} Returns the cast function.
   */
  function castCap(name, func) {
    if (config.cap) {
      var indexes = mapping.iterateeRearg[name];
      if (indexes) {
        return iterateeRearg(func, indexes);
      }
      var n = !isLib && mapping.iterateeAry[name];
      if (n) {
        return iterateeAry(func, n);
      }
    }
    return func;
  }

  /**
   * Casts `func` to a curried function if needed.
   *
   * @private
   * @param {string} name The name of the function to inspect.
   * @param {Function} func The function to inspect.
   * @param {number} n The arity of `func`.
   * @returns {Function} Returns the cast function.
   */
  function castCurry(name, func, n) {
    return forceCurry || config.curry && n > 1 ? curry(func, n) : func;
  }

  /**
   * Casts `func` to a fixed arity function if needed.
   *
   * @private
   * @param {string} name The name of the function to inspect.
   * @param {Function} func The function to inspect.
   * @param {number} n The arity cap.
   * @returns {Function} Returns the cast function.
   */
  function castFixed(name, func, n) {
    if (config.fixed && (forceFixed || !mapping.skipFixed[name])) {
      var data = mapping.methodSpread[name],
          start = data && data.start;

      return start === undefined ? ary(func, n) : flatSpread(func, start);
    }
    return func;
  }

  /**
   * Casts `func` to an rearged function if needed.
   *
   * @private
   * @param {string} name The name of the function to inspect.
   * @param {Function} func The function to inspect.
   * @param {number} n The arity of `func`.
   * @returns {Function} Returns the cast function.
   */
  function castRearg(name, func, n) {
    return config.rearg && n > 1 && (forceRearg || !mapping.skipRearg[name]) ? rearg(func, mapping.methodRearg[name] || mapping.aryRearg[n]) : func;
  }

  /**
   * Creates a clone of `object` by `path`.
   *
   * @private
   * @param {Object} object The object to clone.
   * @param {Array|string} path The path to clone by.
   * @returns {Object} Returns the cloned object.
   */
  function cloneByPath(object, path) {
    path = toPath(path);

    var index = -1,
        length = path.length,
        lastIndex = length - 1,
        result = clone(Object(object)),
        nested = result;

    while (nested != null && ++index < length) {
      var key = path[index],
          value = nested[key];

      if (value != null && !(isFunction(value) || isError(value) || isWeakMap(value))) {
        nested[key] = clone(index == lastIndex ? value : Object(value));
      }
      nested = nested[key];
    }
    return result;
  }

  /**
   * Converts `lodash` to an immutable auto-curried iteratee-first data-last
   * version with conversion `options` applied.
   *
   * @param {Object} [options] The options object. See `baseConvert` for more details.
   * @returns {Function} Returns the converted `lodash`.
   */
  function convertLib(options) {
    return _.runInContext.convert(options)(undefined);
  }

  /**
   * Create a converter function for `func` of `name`.
   *
   * @param {string} name The name of the function to convert.
   * @param {Function} func The function to convert.
   * @returns {Function} Returns the new converter function.
   */
  function createConverter(name, func) {
    var realName = mapping.aliasToReal[name] || name,
        methodName = mapping.remap[realName] || realName,
        oldOptions = options;

    return function (options) {
      var newUtil = isLib ? pristine : helpers,
          newFunc = isLib ? pristine[methodName] : func,
          newOptions = assign(assign({}, oldOptions), options);

      return baseConvert(newUtil, realName, newFunc, newOptions);
    };
  }

  /**
   * Creates a function that wraps `func` to invoke its iteratee, with up to `n`
   * arguments, ignoring any additional arguments.
   *
   * @private
   * @param {Function} func The function to cap iteratee arguments for.
   * @param {number} n The arity cap.
   * @returns {Function} Returns the new function.
   */
  function iterateeAry(func, n) {
    return overArg(func, function (func) {
      return typeof func == 'function' ? baseAry(func, n) : func;
    });
  }

  /**
   * Creates a function that wraps `func` to invoke its iteratee with arguments
   * arranged according to the specified `indexes` where the argument value at
   * the first index is provided as the first argument, the argument value at
   * the second index is provided as the second argument, and so on.
   *
   * @private
   * @param {Function} func The function to rearrange iteratee arguments for.
   * @param {number[]} indexes The arranged argument indexes.
   * @returns {Function} Returns the new function.
   */
  function iterateeRearg(func, indexes) {
    return overArg(func, function (func) {
      var n = indexes.length;
      return baseArity(rearg(baseAry(func, n), indexes), n);
    });
  }

  /**
   * Creates a function that invokes `func` with its first argument transformed.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {Function} transform The argument transform.
   * @returns {Function} Returns the new function.
   */
  function overArg(func, transform) {
    return function () {
      var length = arguments.length;
      if (!length) {
        return func();
      }
      var args = Array(length);
      while (length--) {
        args[length] = arguments[length];
      }
      var index = config.rearg ? 0 : length - 1;
      args[index] = transform(args[index]);
      return func.apply(undefined, args);
    };
  }

  /**
   * Creates a function that wraps `func` and applys the conversions
   * rules by `name`.
   *
   * @private
   * @param {string} name The name of the function to wrap.
   * @param {Function} func The function to wrap.
   * @returns {Function} Returns the converted function.
   */
  function wrap(name, func) {
    var result,
        realName = mapping.aliasToReal[name] || name,
        wrapped = func,
        wrapper = wrappers[realName];

    if (wrapper) {
      wrapped = wrapper(func);
    } else if (config.immutable) {
      if (mapping.mutate.array[realName]) {
        wrapped = wrapImmutable(func, cloneArray);
      } else if (mapping.mutate.object[realName]) {
        wrapped = wrapImmutable(func, createCloner(func));
      } else if (mapping.mutate.set[realName]) {
        wrapped = wrapImmutable(func, cloneByPath);
      }
    }
    each(aryMethodKeys, function (aryKey) {
      each(mapping.aryMethod[aryKey], function (otherName) {
        if (realName == otherName) {
          var data = mapping.methodSpread[realName],
              afterRearg = data && data.afterRearg;

          result = afterRearg ? castFixed(realName, castRearg(realName, wrapped, aryKey), aryKey) : castRearg(realName, castFixed(realName, wrapped, aryKey), aryKey);

          result = castCap(realName, result);
          result = castCurry(realName, result, aryKey);
          return false;
        }
      });
      return !result;
    });

    result || (result = wrapped);
    if (result == func) {
      result = forceCurry ? curry(result, 1) : function () {
        return func.apply(this, arguments);
      };
    }
    result.convert = createConverter(realName, func);
    if (mapping.placeholder[realName]) {
      setPlaceholder = true;
      result.placeholder = func.placeholder = placeholder;
    }
    return result;
  }

  /*--------------------------------------------------------------------------*/

  if (!isObj) {
    return wrap(name, func);
  }
  var _ = func;

  // Convert methods by ary cap.
  var pairs = [];
  each(aryMethodKeys, function (aryKey) {
    each(mapping.aryMethod[aryKey], function (key) {
      var func = _[mapping.remap[key] || key];
      if (func) {
        pairs.push([key, wrap(key, func)]);
      }
    });
  });

  // Convert remaining methods.
  each(keys(_), function (key) {
    var func = _[key];
    if (typeof func == 'function') {
      var length = pairs.length;
      while (length--) {
        if (pairs[length][0] == key) {
          return;
        }
      }
      func.convert = createConverter(key, func);
      pairs.push([key, func]);
    }
  });

  // Assign to `_` leaving `_.prototype` unchanged to allow chaining.
  each(pairs, function (pair) {
    _[pair[0]] = pair[1];
  });

  _.convert = convertLib;
  if (setPlaceholder) {
    _.placeholder = placeholder;
  }
  // Assign aliases.
  each(keys(_), function (key) {
    each(mapping.realToAlias[key] || [], function (alias) {
      _[alias] = _[key];
    });
  });

  return _;
}

module.exports = baseConvert;

/***/ }),
/* 245 */
/***/ (function(module, exports) {

/** Used to map aliases to their real names. */
exports.aliasToReal = {

  // Lodash aliases.
  'each': 'forEach',
  'eachRight': 'forEachRight',
  'entries': 'toPairs',
  'entriesIn': 'toPairsIn',
  'extend': 'assignIn',
  'extendAll': 'assignInAll',
  'extendAllWith': 'assignInAllWith',
  'extendWith': 'assignInWith',
  'first': 'head',

  // Methods that are curried variants of others.
  'conforms': 'conformsTo',
  'matches': 'isMatch',
  'property': 'get',

  // Ramda aliases.
  '__': 'placeholder',
  'F': 'stubFalse',
  'T': 'stubTrue',
  'all': 'every',
  'allPass': 'overEvery',
  'always': 'constant',
  'any': 'some',
  'anyPass': 'overSome',
  'apply': 'spread',
  'assoc': 'set',
  'assocPath': 'set',
  'complement': 'negate',
  'compose': 'flowRight',
  'contains': 'includes',
  'dissoc': 'unset',
  'dissocPath': 'unset',
  'dropLast': 'dropRight',
  'dropLastWhile': 'dropRightWhile',
  'equals': 'isEqual',
  'identical': 'eq',
  'indexBy': 'keyBy',
  'init': 'initial',
  'invertObj': 'invert',
  'juxt': 'over',
  'omitAll': 'omit',
  'nAry': 'ary',
  'path': 'get',
  'pathEq': 'matchesProperty',
  'pathOr': 'getOr',
  'paths': 'at',
  'pickAll': 'pick',
  'pipe': 'flow',
  'pluck': 'map',
  'prop': 'get',
  'propEq': 'matchesProperty',
  'propOr': 'getOr',
  'props': 'at',
  'symmetricDifference': 'xor',
  'symmetricDifferenceBy': 'xorBy',
  'symmetricDifferenceWith': 'xorWith',
  'takeLast': 'takeRight',
  'takeLastWhile': 'takeRightWhile',
  'unapply': 'rest',
  'unnest': 'flatten',
  'useWith': 'overArgs',
  'where': 'conformsTo',
  'whereEq': 'isMatch',
  'zipObj': 'zipObject'
};

/** Used to map ary to method names. */
exports.aryMethod = {
  '1': ['assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create', 'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow', 'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll', 'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome', 'rest', 'reverse', 'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart', 'uniqueId', 'words', 'zipAll'],
  '2': ['add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith', 'at', 'before', 'bind', 'bindAll', 'bindKey', 'chunk', 'cloneDeepWith', 'cloneWith', 'concat', 'conformsTo', 'countBy', 'curryN', 'curryRightN', 'debounce', 'defaults', 'defaultsDeep', 'defaultTo', 'delay', 'difference', 'divide', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq', 'every', 'filter', 'find', 'findIndex', 'findKey', 'findLast', 'findLastIndex', 'findLastKey', 'flatMap', 'flatMapDeep', 'flattenDepth', 'forEach', 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get', 'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection', 'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy', 'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty', 'maxBy', 'meanBy', 'merge', 'mergeAllWith', 'minBy', 'multiply', 'nth', 'omit', 'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial', 'partialRight', 'partition', 'pick', 'pickBy', 'propertyOf', 'pull', 'pullAll', 'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', 'repeat', 'restFrom', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex', 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy', 'split', 'spreadFrom', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight', 'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars', 'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith', 'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject', 'zipObjectDeep'],
  '3': ['assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith', 'findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom', 'getOr', 'includesFrom', 'indexOfFrom', 'inRange', 'intersectionBy', 'intersectionWith', 'invokeArgs', 'invokeArgsMap', 'isEqualWith', 'isMatchWith', 'flatMapDepth', 'lastIndexOfFrom', 'mergeWith', 'orderBy', 'padChars', 'padCharsEnd', 'padCharsStart', 'pullAllBy', 'pullAllWith', 'rangeStep', 'rangeStepRight', 'reduce', 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy', 'sortedLastIndexBy', 'transform', 'unionBy', 'unionWith', 'update', 'xorBy', 'xorWith', 'zipWith'],
  '4': ['fill', 'setWith', 'updateWith']
};

/** Used to map ary to rearg configs. */
exports.aryRearg = {
  '2': [1, 0],
  '3': [2, 0, 1],
  '4': [3, 2, 0, 1]
};

/** Used to map method names to their iteratee ary. */
exports.iterateeAry = {
  'dropRightWhile': 1,
  'dropWhile': 1,
  'every': 1,
  'filter': 1,
  'find': 1,
  'findFrom': 1,
  'findIndex': 1,
  'findIndexFrom': 1,
  'findKey': 1,
  'findLast': 1,
  'findLastFrom': 1,
  'findLastIndex': 1,
  'findLastIndexFrom': 1,
  'findLastKey': 1,
  'flatMap': 1,
  'flatMapDeep': 1,
  'flatMapDepth': 1,
  'forEach': 1,
  'forEachRight': 1,
  'forIn': 1,
  'forInRight': 1,
  'forOwn': 1,
  'forOwnRight': 1,
  'map': 1,
  'mapKeys': 1,
  'mapValues': 1,
  'partition': 1,
  'reduce': 2,
  'reduceRight': 2,
  'reject': 1,
  'remove': 1,
  'some': 1,
  'takeRightWhile': 1,
  'takeWhile': 1,
  'times': 1,
  'transform': 2
};

/** Used to map method names to iteratee rearg configs. */
exports.iterateeRearg = {
  'mapKeys': [1],
  'reduceRight': [1, 0]
};

/** Used to map method names to rearg configs. */
exports.methodRearg = {
  'assignInAllWith': [1, 0],
  'assignInWith': [1, 2, 0],
  'assignAllWith': [1, 0],
  'assignWith': [1, 2, 0],
  'differenceBy': [1, 2, 0],
  'differenceWith': [1, 2, 0],
  'getOr': [2, 1, 0],
  'intersectionBy': [1, 2, 0],
  'intersectionWith': [1, 2, 0],
  'isEqualWith': [1, 2, 0],
  'isMatchWith': [2, 1, 0],
  'mergeAllWith': [1, 0],
  'mergeWith': [1, 2, 0],
  'padChars': [2, 1, 0],
  'padCharsEnd': [2, 1, 0],
  'padCharsStart': [2, 1, 0],
  'pullAllBy': [2, 1, 0],
  'pullAllWith': [2, 1, 0],
  'rangeStep': [1, 2, 0],
  'rangeStepRight': [1, 2, 0],
  'setWith': [3, 1, 2, 0],
  'sortedIndexBy': [2, 1, 0],
  'sortedLastIndexBy': [2, 1, 0],
  'unionBy': [1, 2, 0],
  'unionWith': [1, 2, 0],
  'updateWith': [3, 1, 2, 0],
  'xorBy': [1, 2, 0],
  'xorWith': [1, 2, 0],
  'zipWith': [1, 2, 0]
};

/** Used to map method names to spread configs. */
exports.methodSpread = {
  'assignAll': { 'start': 0 },
  'assignAllWith': { 'start': 0 },
  'assignInAll': { 'start': 0 },
  'assignInAllWith': { 'start': 0 },
  'defaultsAll': { 'start': 0 },
  'defaultsDeepAll': { 'start': 0 },
  'invokeArgs': { 'start': 2 },
  'invokeArgsMap': { 'start': 2 },
  'mergeAll': { 'start': 0 },
  'mergeAllWith': { 'start': 0 },
  'partial': { 'start': 1 },
  'partialRight': { 'start': 1 },
  'without': { 'start': 1 },
  'zipAll': { 'start': 0 }
};

/** Used to identify methods which mutate arrays or objects. */
exports.mutate = {
  'array': {
    'fill': true,
    'pull': true,
    'pullAll': true,
    'pullAllBy': true,
    'pullAllWith': true,
    'pullAt': true,
    'remove': true,
    'reverse': true
  },
  'object': {
    'assign': true,
    'assignAll': true,
    'assignAllWith': true,
    'assignIn': true,
    'assignInAll': true,
    'assignInAllWith': true,
    'assignInWith': true,
    'assignWith': true,
    'defaults': true,
    'defaultsAll': true,
    'defaultsDeep': true,
    'defaultsDeepAll': true,
    'merge': true,
    'mergeAll': true,
    'mergeAllWith': true,
    'mergeWith': true
  },
  'set': {
    'set': true,
    'setWith': true,
    'unset': true,
    'update': true,
    'updateWith': true
  }
};

/** Used to track methods with placeholder support */
exports.placeholder = {
  'bind': true,
  'bindKey': true,
  'curry': true,
  'curryRight': true,
  'partial': true,
  'partialRight': true
};

/** Used to map real names to their aliases. */
exports.realToAlias = function () {
  var hasOwnProperty = Object.prototype.hasOwnProperty,
      object = exports.aliasToReal,
      result = {};

  for (var key in object) {
    var value = object[key];
    if (hasOwnProperty.call(result, value)) {
      result[value].push(key);
    } else {
      result[value] = [key];
    }
  }
  return result;
}();

/** Used to map method names to other names. */
exports.remap = {
  'assignAll': 'assign',
  'assignAllWith': 'assignWith',
  'assignInAll': 'assignIn',
  'assignInAllWith': 'assignInWith',
  'curryN': 'curry',
  'curryRightN': 'curryRight',
  'defaultsAll': 'defaults',
  'defaultsDeepAll': 'defaultsDeep',
  'findFrom': 'find',
  'findIndexFrom': 'findIndex',
  'findLastFrom': 'findLast',
  'findLastIndexFrom': 'findLastIndex',
  'getOr': 'get',
  'includesFrom': 'includes',
  'indexOfFrom': 'indexOf',
  'invokeArgs': 'invoke',
  'invokeArgsMap': 'invokeMap',
  'lastIndexOfFrom': 'lastIndexOf',
  'mergeAll': 'merge',
  'mergeAllWith': 'mergeWith',
  'padChars': 'pad',
  'padCharsEnd': 'padEnd',
  'padCharsStart': 'padStart',
  'propertyOf': 'get',
  'rangeStep': 'range',
  'rangeStepRight': 'rangeRight',
  'restFrom': 'rest',
  'spreadFrom': 'spread',
  'trimChars': 'trim',
  'trimCharsEnd': 'trimEnd',
  'trimCharsStart': 'trimStart',
  'zipAll': 'zip'
};

/** Used to track methods that skip fixing their arity. */
exports.skipFixed = {
  'castArray': true,
  'flow': true,
  'flowRight': true,
  'iteratee': true,
  'mixin': true,
  'rearg': true,
  'runInContext': true
};

/** Used to track methods that skip rearranging arguments. */
exports.skipRearg = {
  'add': true,
  'assign': true,
  'assignIn': true,
  'bind': true,
  'bindKey': true,
  'concat': true,
  'difference': true,
  'divide': true,
  'eq': true,
  'gt': true,
  'gte': true,
  'isEqual': true,
  'lt': true,
  'lte': true,
  'matchesProperty': true,
  'merge': true,
  'multiply': true,
  'overArgs': true,
  'partial': true,
  'partialRight': true,
  'propertyOf': true,
  'random': true,
  'range': true,
  'rangeRight': true,
  'subtract': true,
  'zip': true,
  'zipObject': true,
  'zipObjectDeep': true
};

/***/ }),
/* 246 */
/***/ (function(module, exports, __webpack_require__) {

module.exports = {
  'ary': __webpack_require__(237),
  'assign': __webpack_require__(72),
  'clone': __webpack_require__(239),
  'curry': __webpack_require__(242),
  'forEach': __webpack_require__(43),
  'isArray': __webpack_require__(0),
  'isError': __webpack_require__(256),
  'isFunction': __webpack_require__(34),
  'isWeakMap': __webpack_require__(261),
  'iteratee': __webpack_require__(262),
  'keys': __webpack_require__(47),
  'rearg': __webpack_require__(267),
  'toInteger': __webpack_require__(106),
  'toPath': __webpack_require__(271)
};

/***/ }),
/* 247 */
/***/ (function(module, exports, __webpack_require__) {

var convert = __webpack_require__(14),
    func = convert('assignIn', __webpack_require__(238));

func.placeholder = __webpack_require__(9);
module.exports = func;

/***/ }),
/* 248 */
/***/ (function(module, exports, __webpack_require__) {

module.exports = __webpack_require__(247);

/***/ }),
/* 249 */
/***/ (function(module, exports, __webpack_require__) {

var convert = __webpack_require__(14),
    func = convert('isEmpty', __webpack_require__(255), __webpack_require__(32));

func.placeholder = __webpack_require__(9);
module.exports = func;

/***/ }),
/* 250 */
/***/ (function(module, exports, __webpack_require__) {

var convert = __webpack_require__(14),
    func = convert('isString', __webpack_require__(259), __webpack_require__(32));

func.placeholder = __webpack_require__(9);
module.exports = func;

/***/ }),
/* 251 */
/***/ (function(module, exports, __webpack_require__) {

var convert = __webpack_require__(14),
    func = convert('isUndefined', __webpack_require__(260), __webpack_require__(32));

func.placeholder = __webpack_require__(9);
module.exports = func;

/***/ }),
/* 252 */
/***/ (function(module, exports, __webpack_require__) {

var baseGet = __webpack_require__(73);

/**
 * Gets the value at `path` of `object`. If the resolved value is
 * `undefined`, the `defaultValue` is returned in its place.
 *
 * @static
 * @memberOf _
 * @since 3.7.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
 * @returns {*} Returns the resolved value.
 * @example
 *
 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
 *
 * _.get(object, 'a[0].b.c');
 * // => 3
 *
 * _.get(object, ['a', '0', 'b', 'c']);
 * // => 3
 *
 * _.get(object, 'a.b.c', 'default');
 * // => 'default'
 */
function get(object, path, defaultValue) {
  var result = object == null ? undefined : baseGet(object, path);
  return result === undefined ? defaultValue : result;
}

module.exports = get;

/***/ }),
/* 253 */
/***/ (function(module, exports, __webpack_require__) {

var baseHasIn = __webpack_require__(151),
    hasPath = __webpack_require__(194);

/**
 * Checks if `path` is a direct or inherited property of `object`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 * @example
 *
 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
 *
 * _.hasIn(object, 'a');
 * // => true
 *
 * _.hasIn(object, 'a.b');
 * // => true
 *
 * _.hasIn(object, ['a', 'b']);
 * // => true
 *
 * _.hasIn(object, 'b');
 * // => false
 */
function hasIn(object, path) {
  return object != null && hasPath(object, path, baseHasIn);
}

module.exports = hasIn;

/***/ }),
/* 254 */
/***/ (function(module, exports, __webpack_require__) {

var isArrayLike = __webpack_require__(19),
    isObjectLike = __webpack_require__(2);

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

module.exports = isArrayLikeObject;

/***/ }),
/* 255 */
/***/ (function(module, exports, __webpack_require__) {

var baseKeys = __webpack_require__(47),
    getTag = __webpack_require__(13),
    isArguments = __webpack_require__(18),
    isArray = __webpack_require__(0),
    isArrayLike = __webpack_require__(19),
    isBuffer = __webpack_require__(20),
    isPrototype = __webpack_require__(30),
    isTypedArray = __webpack_require__(35);

/** `Object#toString` result references. */
var mapTag = '[object Map]',
    setTag = '[object Set]';

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Checks if `value` is an empty object, collection, map, or set.
 *
 * Objects are considered empty if they have no own enumerable string keyed
 * properties.
 *
 * Array-like values such as `arguments` objects, arrays, buffers, strings, or
 * jQuery-like collections are considered empty if they have a `length` of `0`.
 * Similarly, maps and sets are considered empty if they have a `size` of `0`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is empty, else `false`.
 * @example
 *
 * _.isEmpty(null);
 * // => true
 *
 * _.isEmpty(true);
 * // => true
 *
 * _.isEmpty(1);
 * // => true
 *
 * _.isEmpty([1, 2, 3]);
 * // => false
 *
 * _.isEmpty({ 'a': 1 });
 * // => false
 */
function isEmpty(value) {
  if (value == null) {
    return true;
  }
  if (isArrayLike(value) && (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
    return !value.length;
  }
  var tag = getTag(value);
  if (tag == mapTag || tag == setTag) {
    return !value.size;
  }
  if (isPrototype(value)) {
    return !baseKeys(value).length;
  }
  for (var key in value) {
    if (hasOwnProperty.call(value, key)) {
      return false;
    }
  }
  return true;
}

module.exports = isEmpty;

/***/ }),
/* 256 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetTag = __webpack_require__(5),
    isObjectLike = __webpack_require__(2),
    isPlainObject = __webpack_require__(104);

/** `Object#toString` result references. */
var domExcTag = '[object DOMException]',
    errorTag = '[object Error]';

/**
 * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
 * `SyntaxError`, `TypeError`, or `URIError` object.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
 * @example
 *
 * _.isError(new Error);
 * // => true
 *
 * _.isError(Error);
 * // => false
 */
function isError(value) {
    if (!isObjectLike(value)) {
        return false;
    }
    var tag = baseGetTag(value);
    return tag == errorTag || tag == domExcTag || typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value);
}

module.exports = isError;

/***/ }),
/* 257 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsMap = __webpack_require__(155),
    baseUnary = __webpack_require__(49),
    nodeUtil = __webpack_require__(55);

/* Node.js helper references. */
var nodeIsMap = nodeUtil && nodeUtil.isMap;

/**
 * Checks if `value` is classified as a `Map` object.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a map, else `false`.
 * @example
 *
 * _.isMap(new Map);
 * // => true
 *
 * _.isMap(new WeakMap);
 * // => false
 */
var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;

module.exports = isMap;

/***/ }),
/* 258 */
/***/ (function(module, exports, __webpack_require__) {

var baseIsSet = __webpack_require__(159),
    baseUnary = __webpack_require__(49),
    nodeUtil = __webpack_require__(55);

/* Node.js helper references. */
var nodeIsSet = nodeUtil && nodeUtil.isSet;

/**
 * Checks if `value` is classified as a `Set` object.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a set, else `false`.
 * @example
 *
 * _.isSet(new Set);
 * // => true
 *
 * _.isSet(new WeakSet);
 * // => false
 */
var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;

module.exports = isSet;

/***/ }),
/* 259 */
/***/ (function(module, exports, __webpack_require__) {

var baseGetTag = __webpack_require__(5),
    isArray = __webpack_require__(0),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var stringTag = '[object String]';

/**
 * Checks if `value` is classified as a `String` primitive or object.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a string, else `false`.
 * @example
 *
 * _.isString('abc');
 * // => true
 *
 * _.isString(1);
 * // => false
 */
function isString(value) {
    return typeof value == 'string' || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
}

module.exports = isString;

/***/ }),
/* 260 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is `undefined`.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
 * @example
 *
 * _.isUndefined(void 0);
 * // => true
 *
 * _.isUndefined(null);
 * // => false
 */
function isUndefined(value) {
  return value === undefined;
}

module.exports = isUndefined;

/***/ }),
/* 261 */
/***/ (function(module, exports, __webpack_require__) {

var getTag = __webpack_require__(13),
    isObjectLike = __webpack_require__(2);

/** `Object#toString` result references. */
var weakMapTag = '[object WeakMap]';

/**
 * Checks if `value` is classified as a `WeakMap` object.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
 * @example
 *
 * _.isWeakMap(new WeakMap);
 * // => true
 *
 * _.isWeakMap(new Map);
 * // => false
 */
function isWeakMap(value) {
  return isObjectLike(value) && getTag(value) == weakMapTag;
}

module.exports = isWeakMap;

/***/ }),
/* 262 */
/***/ (function(module, exports, __webpack_require__) {

var baseClone = __webpack_require__(46),
    baseIteratee = __webpack_require__(161);

/** Used to compose bitmasks for cloning. */
var CLONE_DEEP_FLAG = 1;

/**
 * Creates a function that invokes `func` with the arguments of the created
 * function. If `func` is a property name, the created function returns the
 * property value for a given element. If `func` is an array or object, the
 * created function returns `true` for elements that contain the equivalent
 * source properties, otherwise it returns `false`.
 *
 * @static
 * @since 4.0.0
 * @memberOf _
 * @category Util
 * @param {*} [func=_.identity] The value to convert to a callback.
 * @returns {Function} Returns the callback.
 * @example
 *
 * var users = [
 *   { 'user': 'barney', 'age': 36, 'active': true },
 *   { 'user': 'fred',   'age': 40, 'active': false }
 * ];
 *
 * // The `_.matches` iteratee shorthand.
 * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
 * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
 *
 * // The `_.matchesProperty` iteratee shorthand.
 * _.filter(users, _.iteratee(['user', 'fred']));
 * // => [{ 'user': 'fred', 'age': 40 }]
 *
 * // The `_.property` iteratee shorthand.
 * _.map(users, _.iteratee('user'));
 * // => ['barney', 'fred']
 *
 * // Create custom iteratee shorthands.
 * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
 *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
 *     return func.test(string);
 *   };
 * });
 *
 * _.filter(['abc', 'def'], /ef/);
 * // => ['def']
 */
function iteratee(func) {
  return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
}

module.exports = iteratee;

/***/ }),
/* 263 */
/***/ (function(module, exports, __webpack_require__) {

var MapCache = __webpack_require__(41);

/** Error message constants. */
var FUNC_ERROR_TEXT = 'Expected a function';

/**
 * Creates a function that memoizes the result of `func`. If `resolver` is
 * provided, it determines the cache key for storing the result based on the
 * arguments provided to the memoized function. By default, the first argument
 * provided to the memoized function is used as the map cache key. The `func`
 * is invoked with the `this` binding of the memoized function.
 *
 * **Note:** The cache is exposed as the `cache` property on the memoized
 * function. Its creation may be customized by replacing the `_.memoize.Cache`
 * constructor with one whose instances implement the
 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
 * method interface of `clear`, `delete`, `get`, `has`, and `set`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to have its output memoized.
 * @param {Function} [resolver] The function to resolve the cache key.
 * @returns {Function} Returns the new memoized function.
 * @example
 *
 * var object = { 'a': 1, 'b': 2 };
 * var other = { 'c': 3, 'd': 4 };
 *
 * var values = _.memoize(_.values);
 * values(object);
 * // => [1, 2]
 *
 * values(other);
 * // => [3, 4]
 *
 * object.a = 2;
 * values(object);
 * // => [1, 2]
 *
 * // Modify the result cache.
 * values.cache.set(object, ['a', 'b']);
 * values(object);
 * // => ['a', 'b']
 *
 * // Replace `_.memoize.Cache`.
 * _.memoize.Cache = WeakMap;
 */
function memoize(func, resolver) {
  if (typeof func != 'function' || resolver != null && typeof resolver != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  var memoized = function memoized() {
    var args = arguments,
        key = resolver ? resolver.apply(this, args) : args[0],
        cache = memoized.cache;

    if (cache.has(key)) {
      return cache.get(key);
    }
    var result = func.apply(this, args);
    memoized.cache = cache.set(key, result) || cache;
    return result;
  };
  memoized.cache = new (memoize.Cache || MapCache)();
  return memoized;
}

// Expose `MapCache`.
memoize.Cache = MapCache;

module.exports = memoize;

/***/ }),
/* 264 */
/***/ (function(module, exports, __webpack_require__) {

var baseMerge = __webpack_require__(165),
    createAssigner = __webpack_require__(82);

/**
 * This method is like `_.assign` except that it recursively merges own and
 * inherited enumerable string keyed properties of source objects into the
 * destination object. Source properties that resolve to `undefined` are
 * skipped if a destination value exists. Array and plain object properties
 * are merged recursively. Other objects and value types are overridden by
 * assignment. Source objects are applied from left to right. Subsequent
 * sources overwrite property assignments of previous sources.
 *
 * **Note:** This method mutates `object`.
 *
 * @static
 * @memberOf _
 * @since 0.5.0
 * @category Object
 * @param {Object} object The destination object.
 * @param {...Object} [sources] The source objects.
 * @returns {Object} Returns `object`.
 * @example
 *
 * var object = {
 *   'a': [{ 'b': 2 }, { 'd': 4 }]
 * };
 *
 * var other = {
 *   'a': [{ 'c': 3 }, { 'e': 5 }]
 * };
 *
 * _.merge(object, other);
 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
 */
var merge = createAssigner(function (object, source, srcIndex) {
  baseMerge(object, source, srcIndex);
});

module.exports = merge;

/***/ }),
/* 265 */
/***/ (function(module, exports) {

/**
 * This method returns `undefined`.
 *
 * @static
 * @memberOf _
 * @since 2.3.0
 * @category Util
 * @example
 *
 * _.times(2, _.noop);
 * // => [undefined, undefined]
 */
function noop() {
  // No operation performed.
}

module.exports = noop;

/***/ }),
/* 266 */
/***/ (function(module, exports, __webpack_require__) {

var baseProperty = __webpack_require__(167),
    basePropertyDeep = __webpack_require__(168),
    isKey = __webpack_require__(54),
    toKey = __webpack_require__(16);

/**
 * Creates a function that returns the value at `path` of a given object.
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Util
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 * @example
 *
 * var objects = [
 *   { 'a': { 'b': 2 } },
 *   { 'a': { 'b': 1 } }
 * ];
 *
 * _.map(objects, _.property('a.b'));
 * // => [2, 1]
 *
 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
 * // => [1, 2]
 */
function property(path) {
  return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}

module.exports = property;

/***/ }),
/* 267 */
/***/ (function(module, exports, __webpack_require__) {

var createWrap = __webpack_require__(51),
    flatRest = __webpack_require__(187);

/** Used to compose bitmasks for function metadata. */
var WRAP_REARG_FLAG = 256;

/**
 * Creates a function that invokes `func` with arguments arranged according
 * to the specified `indexes` where the argument value at the first index is
 * provided as the first argument, the argument value at the second index is
 * provided as the second argument, and so on.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Function
 * @param {Function} func The function to rearrange arguments for.
 * @param {...(number|number[])} indexes The arranged argument indexes.
 * @returns {Function} Returns the new function.
 * @example
 *
 * var rearged = _.rearg(function(a, b, c) {
 *   return [a, b, c];
 * }, [2, 0, 1]);
 *
 * rearged('b', 'c', 'a')
 * // => ['a', 'b', 'c']
 */
var rearg = flatRest(function (func, indexes) {
  return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
});

module.exports = rearg;

/***/ }),
/* 268 */
/***/ (function(module, exports) {

/**
 * This method returns `false`.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {boolean} Returns `false`.
 * @example
 *
 * _.times(2, _.stubFalse);
 * // => [false, false]
 */
function stubFalse() {
  return false;
}

module.exports = stubFalse;

/***/ }),
/* 269 */
/***/ (function(module, exports, __webpack_require__) {

var toNumber = __webpack_require__(270);

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0,
    MAX_INTEGER = 1.7976931348623157e+308;

/**
 * Converts `value` to a finite number.
 *
 * @static
 * @memberOf _
 * @since 4.12.0
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {number} Returns the converted number.
 * @example
 *
 * _.toFinite(3.2);
 * // => 3.2
 *
 * _.toFinite(Number.MIN_VALUE);
 * // => 5e-324
 *
 * _.toFinite(Infinity);
 * // => 1.7976931348623157e+308
 *
 * _.toFinite('3.2');
 * // => 3.2
 */
function toFinite(value) {
  if (!value) {
    return value === 0 ? value : 0;
  }
  value = toNumber(value);
  if (value === INFINITY || value === -INFINITY) {
    var sign = value < 0 ? -1 : 1;
    return sign * MAX_INTEGER;
  }
  return value === value ? value : 0;
}

module.exports = toFinite;

/***/ }),
/* 270 */
/***/ (function(module, exports, __webpack_require__) {

var isObject = __webpack_require__(4),
    isSymbol = __webpack_require__(21);

/** Used as references for various `Number` constants. */
var NAN = 0 / 0;

/** Used to match leading and trailing whitespace. */
var reTrim = /^\s+|\s+$/g;

/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;

/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;

/** Built-in method references without a dependency on `root`. */
var freeParseInt = parseInt;

/**
 * Converts `value` to a number.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {number} Returns the number.
 * @example
 *
 * _.toNumber(3.2);
 * // => 3.2
 *
 * _.toNumber(Number.MIN_VALUE);
 * // => 5e-324
 *
 * _.toNumber(Infinity);
 * // => Infinity
 *
 * _.toNumber('3.2');
 * // => 3.2
 */
function toNumber(value) {
  if (typeof value == 'number') {
    return value;
  }
  if (isSymbol(value)) {
    return NAN;
  }
  if (isObject(value)) {
    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
    value = isObject(other) ? other + '' : other;
  }
  if (typeof value != 'string') {
    return value === 0 ? value : +value;
  }
  value = value.replace(reTrim, '');
  var isBinary = reIsBinary.test(value);
  return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
}

module.exports = toNumber;

/***/ }),
/* 271 */
/***/ (function(module, exports, __webpack_require__) {

var arrayMap = __webpack_require__(69),
    copyArray = __webpack_require__(15),
    isArray = __webpack_require__(0),
    isSymbol = __webpack_require__(21),
    stringToPath = __webpack_require__(102),
    toKey = __webpack_require__(16),
    toString = __webpack_require__(107);

/**
 * Converts `value` to a property path array.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Util
 * @param {*} value The value to convert.
 * @returns {Array} Returns the new property path array.
 * @example
 *
 * _.toPath('a.b.c');
 * // => ['a', 'b', 'c']
 *
 * _.toPath('a[0].b.c');
 * // => ['a', '0', 'b', 'c']
 */
function toPath(value) {
  if (isArray(value)) {
    return arrayMap(value, toKey);
  }
  return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
}

module.exports = toPath;

/***/ }),
/* 272 */
/***/ (function(module, exports, __webpack_require__) {

var copyObject = __webpack_require__(12),
    keysIn = __webpack_require__(22);

/**
 * Converts `value` to a plain object flattening inherited enumerable string
 * keyed properties of `value` to own properties of the plain object.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {Object} Returns the converted plain object.
 * @example
 *
 * function Foo() {
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.assign({ 'a': 1 }, new Foo);
 * // => { 'a': 1, 'b': 2 }
 *
 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
 * // => { 'a': 1, 'b': 2, 'c': 3 }
 */
function toPlainObject(value) {
  return copyObject(value, keysIn(value));
}

module.exports = toPlainObject;

/***/ }),
/* 273 */
/***/ (function(module, exports, __webpack_require__) {

var LazyWrapper = __webpack_require__(39),
    LodashWrapper = __webpack_require__(65),
    baseLodash = __webpack_require__(48),
    isArray = __webpack_require__(0),
    isObjectLike = __webpack_require__(2),
    wrapperClone = __webpack_require__(236);

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Creates a `lodash` object which wraps `value` to enable implicit method
 * chain sequences. Methods that operate on and return arrays, collections,
 * and functions can be chained together. Methods that retrieve a single value
 * or may return a primitive value will automatically end the chain sequence
 * and return the unwrapped value. Otherwise, the value must be unwrapped
 * with `_#value`.
 *
 * Explicit chain sequences, which must be unwrapped with `_#value`, may be
 * enabled using `_.chain`.
 *
 * The execution of chained methods is lazy, that is, it's deferred until
 * `_#value` is implicitly or explicitly called.
 *
 * Lazy evaluation allows several methods to support shortcut fusion.
 * Shortcut fusion is an optimization to merge iteratee calls; this avoids
 * the creation of intermediate arrays and can greatly reduce the number of
 * iteratee executions. Sections of a chain sequence qualify for shortcut
 * fusion if the section is applied to an array and iteratees accept only
 * one argument. The heuristic for whether a section qualifies for shortcut
 * fusion is subject to change.
 *
 * Chaining is supported in custom builds as long as the `_#value` method is
 * directly or indirectly included in the build.
 *
 * In addition to lodash methods, wrappers have `Array` and `String` methods.
 *
 * The wrapper `Array` methods are:
 * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
 *
 * The wrapper `String` methods are:
 * `replace` and `split`
 *
 * The wrapper methods that support shortcut fusion are:
 * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
 * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
 * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
 *
 * The chainable wrapper methods are:
 * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
 * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
 * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
 * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
 * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
 * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
 * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
 * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
 * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
 * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
 * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
 * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
 * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
 * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
 * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
 * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
 * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
 * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
 * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
 * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
 * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
 * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
 * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
 * `zipObject`, `zipObjectDeep`, and `zipWith`
 *
 * The wrapper methods that are **not** chainable by default are:
 * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
 * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
 * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
 * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
 * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
 * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
 * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
 * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
 * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
 * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
 * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
 * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
 * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
 * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
 * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
 * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
 * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
 * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
 * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
 * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
 * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
 * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
 * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
 * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
 * `upperFirst`, `value`, and `words`
 *
 * @name _
 * @constructor
 * @category Seq
 * @param {*} value The value to wrap in a `lodash` instance.
 * @returns {Object} Returns the new `lodash` wrapper instance.
 * @example
 *
 * function square(n) {
 *   return n * n;
 * }
 *
 * var wrapped = _([1, 2, 3]);
 *
 * // Returns an unwrapped value.
 * wrapped.reduce(_.add);
 * // => 6
 *
 * // Returns a wrapped value.
 * var squares = wrapped.map(square);
 *
 * _.isArray(squares);
 * // => false
 *
 * _.isArray(squares.value());
 * // => true
 */
function lodash(value) {
  if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
    if (value instanceof LodashWrapper) {
      return value;
    }
    if (hasOwnProperty.call(value, '__wrapped__')) {
      return wrapperClone(value);
    }
  }
  return new LodashWrapper(value);
}

// Ensure wrappers are instances of `baseLodash`.
lodash.prototype = baseLodash.prototype;
lodash.prototype.constructor = lodash;

module.exports = lodash;

/***/ }),
/* 274 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__integrations_MoneyPak__ = __webpack_require__(114);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__integrations_Paypal__ = __webpack_require__(115);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__integrations_BetCash__ = __webpack_require__(111);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__integrations_CreditCards__ = __webpack_require__(112);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__integrations_QuickDeposit__ = __webpack_require__(116);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__integrations_SightLine__ = __webpack_require__(117);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__integrations_GenericDeposit__ = __webpack_require__(113);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__tvg_angular_common_user_actions_events_user_actions_events__ = __webpack_require__(110);









var DepositGTM = function DepositGTM(defaultConfig) {
    var events = new __WEBPACK_IMPORTED_MODULE_7__tvg_angular_common_user_actions_events_user_actions_events__["a" /* default */](defaultConfig);
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_6__integrations_GenericDeposit__["a" /* register */])(events, defaultConfig);
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__integrations_MoneyPak__["a" /* register */])(events, defaultConfig);
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__integrations_Paypal__["a" /* register */])(events, defaultConfig);
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__integrations_BetCash__["a" /* register */])(events, defaultConfig);
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_3__integrations_CreditCards__["a" /* register */])(events, defaultConfig);
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_4__integrations_QuickDeposit__["a" /* register */])(events, defaultConfig);
    __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_5__integrations_SightLine__["a" /* register */])(events, defaultConfig);
};

/* harmony default export */ __webpack_exports__["default"] = (DepositGTM);

/***/ }),
/* 275 */
/***/ (function(module, exports) {

var screenNames = {
    'myprofile': 'My Account',
    'my-tracks': 'My Account',
    'my-favorite-tracks': 'My Account',
    'my-funds': 'My Account',
    'my-bets': 'My Account',
    'my-account-summary': 'My Account',
    'my-stable': 'My Account',
    'races': 'Races',
    'race': 'Program',
    'racetracks': 'Program',
    'handicapping': 'Handicapping',
    'info': 'Site Info',
    'home': 'Home',
    '': 'Home',
    'results': 'Races',
    'betslip': 'Bet Ticket',
    'promotions': 'Promotions',
    'registration': 'Registration Page',
    'password-recovery': 'Credentials Recovery',
    'forgot-credentials': 'Credentials Recovery',
    'reset-credentials': 'Credentials Recovery',
    'horse-race-track-list': 'Track List'
};

module.exports = screenNames;

/***/ }),
/* 276 */
/***/ (function(module, exports) {

var sectionNames = {
    'myprofile': {
        'translation': 'My Account',
        'my-tracks': 'My Tracks',
        'my-favorite-tracks': 'My Favorite Tracks',
        'funds': 'My Funds',
        'my-bets': 'My Bets',
        'my-account-summary': 'My Account Summary',
        'profile': 'My Profile',
        'deposit': 'Deposit',
        'bank': 'Payment Management',
        'withdraw': 'Withdraw',
        'my-stable': 'My Stable'
    },
    handicapping: {
        'translation': 'Handicapping',
        'handicapping-store': 'Handicapping Store',
        'free-pp': 'Free Past Performances',
        'talentpicks': 'Talent Picks',
        'racereplays': 'Race Replays',
        'talent-picks': 'Talent Picks',
        'race-replays': 'Race Replays'
    },
    promotions: {
        translation: 'Promotions',
        'wager-rewards': 'Wager Rewards'
    },
    horseracing: {
        translation: 'Races',
        races: 'Full Schedule',
        results: 'Results'
    },
    home: {
        translation: 'Home | Home Page'
    },
    programpage: {
        translation: 'Program Page'
    },
    siteinfo: {
        translation: 'Site Info',
        privacypolicy: 'Privacy Policy',
        wagerresponsibly: 'Wager Responsibly',
        termsandconditions: 'Terms and Conditions'
    },
    betslip: {
        translation: 'Bet Ticket',
        default: 'Bet Ticket Page'
    }
};

module.exports = sectionNames;

/***/ })
/******/ ]);
});
vendors/matchMedia/matchMedia.js
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. MIT license */

window.matchMedia || (window.matchMedia = function() {
    "use strict";

    // For browsers that support matchMedium api such as IE 9 and webkit
    var styleMedia = (window.styleMedia || window.media);

    // For those that don't support matchMedium
    if (!styleMedia) {
        var style       = document.createElement('style'),
            script      = document.getElementsByTagName('script')[0],
            info        = null;

        style.type  = 'text/css';
        style.id    = 'matchmediajs-test';

        if (!script) {
          document.head.appendChild(style);
        } else {
          script.parentNode.insertBefore(style, script);
        }

        // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
        info = ('getComputedStyle' in window) && window.getComputedStyle(style, null) || style.currentStyle;

        styleMedia = {
            matchMedium: function(media) {
                var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }';

                // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
                if (style.styleSheet) {
                    style.styleSheet.cssText = text;
                } else {
                    style.textContent = text;
                }

                // Test if media query is true or false
                return info.width === '1px';
            }
        };
    }

    return function(media) {
        return {
            matches: styleMedia.matchMedium(media || 'all'),
            media: media || 'all'
        };
    };
}());

define("matchMedia", function(){});

vendors/tvg-configuration/configurationMod.min.js
angular.module("TVG.Configuration",[]),angular.module("TVG.Configuration").factory("ConfigurationFac",["$http","$window",function($http,$window){function _getGTMContainerId(){var containerId,application=getApplicationContextItem("application"),product=getApplicationContextItem("product");return containerId="ios"==product?product:application}function _getStartupParameter(param,applicationContextName){var env=_getEnvironment(applicationContextName);return!(!env.environment||!env.context)&&getStartupConfig(env.environment,param,env.context)}function _setStartupParameter(param,applicationContextName,paramValue){var env=_getEnvironment(applicationContextName);return!(!env.environment||!env.context)&&setStartupConfig(env.environment,param,env.context,paramValue)}function _getEnvironment(applicationContextName){var environment=!1;if(racingAwsEnv)return"api"===applicationContextName?applicationContextName="api_fdr":"service_api"===applicationContextName&&(applicationContextName="service_api_fdr"),environment=racingAwsEnv,{environment:environment,context:applicationContextName};if(/fndlext\.net$/.test(domain)){if(/4njbets/gi.test(hostname)&&("api"===applicationContextName?applicationContextName="api_nj":"service_api"===applicationContextName&&(applicationContextName="service_api_nj")),/pabets/gi.test(hostname)&&"api"===applicationContextName&&(applicationContextName="api_pa"),/ia/gi.test(hostname)&&"api"===applicationContextName&&(applicationContextName="api_ia"),/\.int\./.test(hostname))return environment="aws-int",{environment:environment,context:applicationContextName};if(/\.stg\./.test(hostname))return environment="aws-stg",{environment:environment,context:applicationContextName};if(/\.prd\./.test(hostname))return environment="aws-prd",{environment:environment,context:applicationContextName}}return/tvg\.com$/.test(domain)?(/nj/gi.test(hostname)&&("api"===applicationContextName?applicationContextName="api_nj":"service_api"===applicationContextName&&(applicationContextName="service_api_nj")),/pa/gi.test(hostname)&&"api"===applicationContextName&&(applicationContextName="api_pa"),/ia/gi.test(hostname)&&"api"===applicationContextName&&(applicationContextName="api_ia"),/deposit\.dev./.test(hostname)?(environment="devDeposit",{environment:environment,context:applicationContextName}):/\.dev\./.test(hostname)?(environment="registration"==getApplicationContextItem("application")&&"njx"==getApplicationContextItem("product")?"njx_qa":"dev",{environment:environment,context:applicationContextName}):/qa\./.test(hostname)?(environment="registration"==getApplicationContextItem("application")&&"njx"==getApplicationContextItem("product")?"njx_qa":"qa",{environment:environment,context:applicationContextName}):/stage\.|staging\./.test(hostname)?(environment="staging",{environment:environment,context:applicationContextName}):(environment="production",{environment:environment,context:applicationContextName})):/fanduel\.com$/.test(domain)||/fndl\.dev$/.test(domain)?("api"===applicationContextName?applicationContextName="api_fdr":"service_api"===applicationContextName&&(applicationContextName="service_api_fdr"),/deposit\.dev./.test(hostname)?(environment="devDeposit",{environment:environment,context:applicationContextName}):/\.dev\./.test(hostname)?(environment="registration"==getApplicationContextItem("application")&&"njx"==getApplicationContextItem("product")?"njx_qa":"dev",{environment:environment,context:applicationContextName}):/qa\./.test(hostname)?(environment="registration"==getApplicationContextItem("application")&&"njx"==getApplicationContextItem("product")?"njx_qa":"qa",{environment:environment,context:applicationContextName}):/stage\.|staging\.|cert\./.test(hostname)?(environment="staging",{environment:environment,context:applicationContextName}):(environment="production",{environment:environment,context:applicationContextName})):!(!/betfair\./.test(domain)&&!/betfair$/.test(domain))&&(/\.dev\.|drk\.com\.|qa\.com\./.test(hostname)?(environment="registration"==getApplicationContextItem("application")&&"njx"==getApplicationContextItem("product")?"njx_qa":"dev",{environment:environment,context:applicationContextName}):/qa\./.test(hostname)?(environment="registration"==getApplicationContextItem("application")&&"njx"==getApplicationContextItem("product")?"njx_qa":"qa","service_api"===applicationContextName&&(applicationContextName="service_api_nj"),{environment:environment,context:applicationContextName}):/stage\.|staging\./.test(hostname)?(environment="staging","service_api"===applicationContextName&&(applicationContextName="service_api_nj"),{environment:environment,context:applicationContextName}):(environment="registration"==getApplicationContextItem("application")&&"njx"==getApplicationContextItem("product")?"njx_prod":"betfair",{environment:environment,context:applicationContextName}))}function getBrazeDevice(){var application=getApplicationContextItem("application");return"ios"===application?"iOS":"mobile"===application?/Android\./.test(navigator.userAgent)?"web_android":"web_ios":"AndroidOs"}function _getDevice(){var device,mobile_browser=_mobileBrowser(navigator.userAgent);if(mobile_browser===!0)switch(!0){case window.matchMedia("only screen and (orientation: landscape) and (max-device-width: 768px), only screen and (orientation: portrait) and (max-device-width: 480px), only screen and (min-device-width: 360px) and (max-device-height: 640px) and (-webkit-device-pixel-ratio: 3)").matches:device="phone";break;default:device="tablet"}else device="desktop";return device}function _mobileBrowser(a){var mobile_browser=!1;return(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))&&(mobile_browser=!0),mobile_browser}function getQubitId(environment){var domainPart=$window.location.hostname.split("."),domain=domainPart.length>2?domainPart.splice(1).join("."):2===domainPart.length?domainPart.join("."):domainPart,brand=/fanduel\.com$/.test(domain)||/fndl\.dev$/.test(domain)?"fdr":"tvg",qubitIds={tvg:{production:"4860",staging:"4864",qa:"4864"},fdr:{production:"5621",staging:"5622",qa:"5622"}},qubitId=qubitIds[brand][environment];return qubitId}function getBrazeId(environment){var domainPart=$window.location.hostname.split("."),domain=domainPart.length>2?domainPart.splice(1).join("."):2===domainPart.length?domainPart.join("."):domainPart,brand=/fanduel\.com$/.test(domain)||/fndl\.dev$/.test(domain)?"fdr":"tvg",brazeIds={tvg:{production:"908c5857-650b-4f31-8ec7-63b15dc11d1d",staging:"908c5857-650b-4f31-8ec7-63b15dc11d1d",qa:"a728acfe-5f28-42c0-9c08-174ecb4394d5"},fdr:{production:"e0b90c9d-dfd9-4809-a627-565a5cd7f3b2",staging:"e0b90c9d-dfd9-4809-a627-565a5cd7f3b2",qa:"d1c732dc-ad0d-49a5-acb7-d360cd0fee38"}},brazeId=brazeIds[brand][environment];return brazeId}var domainPart=$window.location.hostname.split("."),racingAwsEnv=$window.location.hostname.indexOf("int.racing")>-1||$window.location.hostname.indexOf("devstack-")>-1?"aws-int":$window.location.hostname.indexOf("stg.racing")>-1?"aws-stg":$window.location.hostname.indexOf("prd.racing")>-1?"aws-prd":null,domain=domainPart.length>2?domainPart.splice(1).join("."):2===domainPart.length?domainPart.join("."):domainPart,hostname=$window.location.hostname,absoluteRequests=!1,siteVersion={deposit:"TVG3",mobile:"mobile_web",desktop:"desktop",ios:"ios_native"},startupConfig={production:{baseUrl:{registration:"nodejs.tvg.com",content:"nodejs.tvg.com",deposit:"nodejs.tvg.com",mobile:"nodejs.tvg.com",desktop:"nodejs.tvg.com",api:"www.tvg.com",api_nj:"4njbets.tvg.com",api_pa:"pabets.tvg.com",api_ia:"ia.tvg.com",api_fdr:"racing.fanduel.com",service_api:"//service.tvg.com",service_api_nj:"//service.us.betfair.com",service_api_fdr:"//service.racing.fanduel.com"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"static.tvgresources.com/static/cms_files/",desktop:"static.tvgresources.com/static/cms_files/"},qubit:{key:getQubitId("production")},braze:{key:getBrazeId("production")},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"",fdr:""},googleTagAuthenticationId:{tvg:"",fdr:""},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-8156856-2",deposit:"UA-8156856-2",mobile:"UA-8156856-2",desktop:"UA-8156856-2",ios:"UA-8156856-2"},sightline:{iframeURL:"https://spanexpress.lcpportal.com/HostedFunding"},paypal:{baseURL:"https://www.paypal.com/cgi-bin/webscr"}},staging:{baseUrl:{registration:"www-staging.tvg.com",content:"www-staging.tvg.com",deposit:"www-staging.tvg.com",mobile:"www-staging.tvg.com",desktop:"www-staging.tvg.com",api:"www-staging.tvg.com",api_nj:"4njbets.stage.us.betfair.local",api_pa:"pabets-staging.tvg.com",api_ia:"ia-staging.tvg.com",api_fdr:"staging.racing.fanduel.com",service_api:"//service-staging.tvg.com",service_api_nj:"//service-staging.us.betfair.com",service_api_fdr:"//service-staging.racing.fanduel.com"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"static-staging.tvgresources.com/static/cms_files/",desktop:"static-staging.tvgresources.com/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"668",fdr:"7"},googleTagAuthenticationId:{tvg:"Q3mmSetXL-9o6LJDN6Tz1A",fdr:"f6IADDjEe2JEMvQbo_jxd"},braze:{key:getBrazeId("staging")},qubit:{key:getQubitId("staging")},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-8156856-11",deposit:"UA-8156856-11",mobile:"UA-8156856-11",android:"UA-8156856-11",desktop:"UA-8156856-11",ios:"UA-8156856-11"},sightline:{iframeURL:"https://spanexpress.lcpportal.com/HostedFunding"},paypal:{baseURL:"https://www.paypal.com/cgi-bin/webscr"}},qa:{baseUrl:{registration:"www-qa.tvg.com",content:"www-qa.tvg.com",deposit:"www-qa.tvg.com",mobile:"www-qa.tvg.com",desktop:"www-qa.tvg.com",api:"www-qa.tvg.com",api_nj:"prxnj.sprint.qa.tvg.com",api_fdr:"racing.qa.fndl.dev",service_api:"//service-qa.tvg.com",service_api_nj:"//service-qa.us.betfair.com",service_api_fdr:"//racing.qa.fndl.dev",graph_api:"http://service-qa.tvg.com/graph"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"/static/cms_files/",desktop:"/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"482",fdr:"5"},googleTagAuthenticationId:{tvg:"EM7EyobnJbhcGWCe5IOyyw",fdr:"brY2SVdkc5NjBXD6t4kZTg"},braze:{key:getBrazeId("qa")},qubit:{key:getQubitId("qa")},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-8156856-12",deposit:"UA-8156856-12",mobile:"UA-8156856-12",desktop:"UA-8156856-12",ios:"UA-8156856-12"},sightline:{iframeURL:"https://ceapspanex.slpuat.com/hostedfunding"},paypal:{baseURL:"https://www.sandbox.paypal.com/cgi-bin/webscr"}},dev:{baseUrl:{registration:"nodejs1.qa.tvg.com",content:"nodejs1.qa.tvg.com",deposit:"nodejs1.qa.tvg.com",mobile:"nodejs1.qa.tvg.com",desktop:"nodejs1.qa.tvg.com",api:"touch.dev.tvg.com:8081",api_nj:"touchnj.dev.tvg.com:8081",service_api:"",service_api_nj:"",service_api_fdr:"",protocol:"https://"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"/static/cms_files/",desktop:"/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"482",fdr:"5"},googleTagAuthenticationId:{tvg:"EM7EyobnJbhcGWCe5IOyyw",fdr:"brY2SVdkc5NjBXD6t4kZTg"},braze:{key:getBrazeId("qa")},qubit:{key:getQubitId("qa")},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-8156856-9",deposit:"UA-8156856-9",mobile:"UA-8156856-9",android:"UA-8156856-9",desktop:"UA-8156856-9",ios:"UA-8156856-9"},sightline:{iframeURL:"https://ceapspanex.slpuat.com/hostedfunding"},paypal:{baseURL:"https://www.sandbox.paypal.com/cgi-bin/webscr"}},devDeposit:{baseUrl:{registration:"nodejs1.qa.tvg.com",content:"nodejs1.qa.tvg.com",deposit:"deposit.dev.tvg.com:8081",mobile:"nodejs1.qa.tvg.com",desktop:"nodejs1.qa.tvg.com",api:"nodejs1.qa.tvg.com",api_nj:"nodejs1.qa.tvg.com",service_api:"//service-qa.tvg.com",service_api_nj:"//service-qa.us.betfair.com",service_api_fdr:"//racing.qa.fndl.dev",protocol:"https://"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"/static/cms_files/",desktop:"/static/cms_files/"},braze:{key:getBrazeId("qa")},qubit:{key:getQubitId("qa")},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"482",fdr:"5"},googleTagAuthenticationId:{tvg:"EM7EyobnJbhcGWCe5IOyyw",fdr:"brY2SVdkc5NjBXD6t4kZTg"},googleAnalyticsContainerId:{registration:"UA-8156856-9",deposit:"UA-8156856-9",mobile:"UA-8156856-9",android:"UA-8156856-9",desktop:"UA-8156856-9",ios:"UA-8156856-9"},sightline:{iframeURL:"https://ceapspanex.slpuat.com/hostedfunding"},paypal:{baseURL:"https://www.sandbox.paypal.com/cgi-bin/webscr"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"}},betfair:{baseUrl:{registration:"nodejs."+domain,content:"nodejs."+domain,deposit:"nodejs."+domain,mobile:"nodejs."+domain,desktop:"nodejs."+domain,api:"4njbets."+domain,service_api:"//service.us.betfair.com"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},braze:{key:getBrazeId("production")},qubit:{key:"4863"},cmsFilesUrl:{mobile:"static.tvgresources.com/static/cms_files/",desktop:"static.tvgresources.com/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"",fdr:""},googleTagAuthenticationId:{tvg:"",fdr:""},googleAnalyticsContainerId:{registration:"UA-8156856-2",deposit:"UA-8156856-2",mobile:"UA-8156856-2",desktop:"UA-8156856-2",ios:"UA-8156856-2"},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},sightline:{iframeURL:"https://spanexpress.lcpportal.com/HostedFunding"},paypal:{baseURL:"https://www.paypal.com/cgi-bin/webscr"}},njx_prod:{baseUrl:{registration:"nodejs.us.betfair.com",content:"nodejs.us.betfair.com",deposit:"nodejs.us.betfair.com",mobile:"nodejs.us.betfair.com",desktop:"nodejs.us.betfair.com",api:"4njbets.us.betfair.com",service_api:"//service.us.betfair.com"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"static.tvgresources.com/static/cms_files/",desktop:"static.tvgresources.com/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"",fdr:""},googleTagAuthenticationId:{tvg:"",fdr:""},braze:{key:getBrazeId("production")},qubit:{key:"4863"},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-43334570-42",deposit:"UA-43334570-42",mobile:"UA-43334570-42",android:"UA-43334570-42",desktop:"UA-43334570-42",ios:"UA-43334570-42"},sightline:{iframeURL:"https://spanexpress.lcpportal.com/HostedFunding"},paypal:{baseURL:"https://www.paypal.com/cgi-bin/webscr"}},njx_qa:{baseUrl:{registration:"nodejs1.qa.tvg.com",content:"nodejs1.qa.tvg.com",deposit:"nodejs1.qa.tvg.com",mobile:"nodejs1.qa.tvg.com",desktop:"nodejs1.qa.tvg.com",api:"prxsprint.qa.tvg.com",api_nj:"prxnj.sprint.qa.tvg.com",service_api:"//service-qa.us.betfair.com",service_api_nj:"//service-qa.us.betfair.com"},braze:{key:getBrazeId("qa")},qubit:{key:"4865"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"/static/cms_files/",desktop:"/static/cms_files/"},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"482",fdr:"5"},googleTagAuthenticationId:{tvg:"EM7EyobnJbhcGWCe5IOyyw",fdr:"brY2SVdkc5NjBXD6t4kZTg"},googleAnalyticsContainerId:{registration:"UA-8156856-12",deposit:"UA-8156856-12",mobile:"UA-8156856-12",android:"UA-8156856-12",desktop:"UA-8156856-12",ios:"UA-8156856-12"},sightline:{iframeURL:"https://ceapspanex.slpuat.com/hostedfunding"},paypal:{baseURL:"https://www.sandbox.paypal.com/cgi-bin/webscr"}},"aws-prd":{baseUrl:{registration:"www.prd.use2.racing.fndlext.net",content:"www.prd.use2.racing.fndlext.net",deposit:"www.prd.use2.racing.fndlext.net",mobile:"www.prd.use2.racing.fndlext.net",desktop:"www.prd.use2.racing.fndlext.net",api:"api.prd.use2.racing.fndlext.net",api_nj:"api.prd.use2.racing.fndlext.net",api_fdr:"api.prd.racing.fanduel.com",service_api:"//service.prd.use2.racing.fndlext.net",service_api_nj:"//service.4njbets.prd.use2.racing.fndlext.net",service_api_fdr:"//api.prd.racing.fanduel.com"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"static.tvgresources.com/static/cms_files/",desktop:"static.tvgresources.com/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"668",fdr:"7"},googleTagAuthenticationId:{tvg:"Q3mmSetXL-9o6LJDN6Tz1A",fdr:"f6IADDjEe2JEMvQbo_jxd"},braze:{key:getBrazeId("staging")},qubit:{key:getQubitId("staging")},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-8156856-11",deposit:"UA-8156856-11",mobile:"UA-8156856-11",android:"UA-8156856-11",desktop:"UA-8156856-11",ios:"UA-8156856-11"},sightline:{iframeURL:"https://spanexpress.lcpportal.com/HostedFunding"},paypal:{baseURL:"https://www.paypal.com/cgi-bin/webscr"}},"aws-stg":{baseUrl:{registration:"www.stg.use2.racing.fndlext.net",content:"www.stg.use2.racing.fndlext.net",deposit:"www.stg.use2.racing.fndlext.net",mobile:"www.stg.use2.racing.fndlext.net",desktop:"www.stg.use2.racing.fndlext.net",api:"api.stg.use2.racing.fndlext.net",api_nj:"api.stg.use2.racing.fndlext.net",api_fdr:"api.stg.racing.fanduel.com",service_api:"//service.stg.use2.racing.fndlext.net",service_api_nj:"//service.4njbets.stg.use2.racing.fndlext.net",service_api_fdr:"//api.stg.racing.fanduel.com"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"static-staging.tvgresources.com/static/cms_files/",desktop:"static-staging.tvgresources.com/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"668",fdr:"7"},googleTagAuthenticationId:{tvg:"Q3mmSetXL-9o6LJDN6Tz1A",fdr:"f6IADDjEe2JEMvQbo_jxd"},braze:{key:getBrazeId("staging")},qubit:{key:getQubitId("staging")},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-8156856-11",deposit:"UA-8156856-11",mobile:"UA-8156856-11",android:"UA-8156856-11",desktop:"UA-8156856-11",ios:"UA-8156856-11"},sightline:{iframeURL:"https://spanexpress.lcpportal.com/HostedFunding"},paypal:{baseURL:"https://www.paypal.com/cgi-bin/webscr"}},"aws-int":{baseUrl:{registration:"www.int.use2.racing.fndlext.net",content:"www.int.use2.racing.fndlext.net",deposit:"www.int.use2.racing.fndlext.net",mobile:"www.int.use2.racing.fndlext.net",desktop:"www.int.use2.racing.fndlext.net",api:"api.int.use2.racing.fndlext.net",api_nj:"api.int.use2.racing.fndlext.net",api_fdr:"api.int.racing.qa.fndl.dev",service_api:"//service.int.use2.racing.fndlext.net",service_api_nj:"//service.4njbets.int.use2.racing.fndlext.net",service_api_fdr:"//api.int.racing.qa.fndl.dev"},service:{graph:"/graph/v2/query",fcp:"/fcp/v1/query",behg:"/behg/v1/query",wtx:"/wtx/v1/users",pay:"/pay/v1",reports:"/reports/",log:"/uel/v1/log-event",usa:"/usa/v2",usa_v1:"/usa/v1",uam:"/uam/v1",ach:"/ach/v1",prf:"/prf/v1",upr:"/upr/v1",slp:"/slp/v1",uwt:"/uwt/v1",uas:"/uas/v1",wro:"/wro/v1",nav:"/nav/v1/lhn/",uar:"/uar/v1",njs:"/njs/v1",capi:"/capi/v1",geo:"/geo/v1",seo:"/seo/v1/",ufc:"/ufc/v1/",rwd:"/rwd/v1",pro:"/pro/v1",cus:"/cus/v1",fdr:"/fdr/v1",fdr_v2:"/fdr/v2",brt:"/brt/v1",pxp:"/pxp/v1/proxy"},cmsFilesUrl:{mobile:"/static/cms_files/",desktop:"/static/cms_files/"},googleTagContainerId:{tvg:{registration:"KTDSBG",deposit:"KTDSBG",mobile:"KTDSBG",desktop:"KTDSBG",ios:"KTDSBG"},fdr:{registration:"NSHBQSR",deposit:"NSHBQSR",mobile:"NSHBQSR",desktop:"NSHBQSR",ios:"NSHBQSR"}},googleTagEnvironmentId:{tvg:"482",fdr:"5"},googleTagAuthenticationId:{tvg:"EM7EyobnJbhcGWCe5IOyyw",fdr:"brY2SVdkc5NjBXD6t4kZTg"},braze:{key:getBrazeId("qa")},qubit:{key:getQubitId("qa")},googleApiKey:{apikey:"AIzaSyATtBSfC-JtQeEM1Axvr29rYY-067jyeoU"},tooltipIo:{apiKey:"glrNcLZhXCHc_uWj6PoCllRV4NhnKX_Yzglf3ZfVrBX"},googleAnalyticsContainerId:{registration:"UA-8156856-12",deposit:"UA-8156856-12",mobile:"UA-8156856-12",desktop:"UA-8156856-12",ios:"UA-8156856-12"},sightline:{iframeURL:"https://ceapspanex.slpuat.com/hostedfunding"},paypal:{baseURL:"https://www.sandbox.paypal.com/cgi-bin/webscr"}}},applicationContext={application:"mobile",wrapper:!1,device:_getDevice(),residence:"all",location:"all",product:"tvg",user_status:"logged_out"},getApplicationContext=function(){return applicationContext},getApplicationContextItem=function(item){return applicationContext[item]||null},setApplicationContextItem=function(item,value){return applicationContext[item]=value,applicationContext},getBaseUrl=function(module){return module=module||applicationContext.application,_getStartupParameter("baseUrl",module)},getBaseApiUrl=function(){return _getStartupParameter("baseUrl","api")},getBaseServiceUrl=function(){return _getStartupParameter("baseUrl","service_api")},getServiceApiUrl=function(service){return _getStartupParameter("baseUrl","service_api")+_getStartupParameter("service",service)},getGoogleAPIKey=function(applicationContext){return _getStartupParameter("googleApiKey",applicationContext)},getGTMContainerId=function(){var product=0===getApplicationContextItem("product").indexOf("fdr")?"fdr":"tvg",env=_getEnvironment(_getGTMContainerId());return!!(startupConfig.hasOwnProperty(env.environment)&&startupConfig[env.environment].hasOwnProperty("googleTagContainerId")&&startupConfig[env.environment].googleTagContainerId.hasOwnProperty(product)&&startupConfig[env.environment].googleTagContainerId[product].hasOwnProperty(env.context))&&startupConfig[env.environment].googleTagContainerId[product][env.context]},getGTMEnvironmentId=function(){var product=0===getApplicationContextItem("product").indexOf("fdr")?"fdr":"tvg",env=_getEnvironment(_getGTMContainerId());return startupConfig.hasOwnProperty(env.environment)&&startupConfig[env.environment].hasOwnProperty("googleTagEnvironmentId")&&startupConfig[env.environment].googleTagEnvironmentId.hasOwnProperty(product)?startupConfig[env.environment].googleTagEnvironmentId[product]:null},getGTMAuthenticationId=function(){var product=0===getApplicationContextItem("product").indexOf("fdr")?"fdr":"tvg",env=_getEnvironment(_getGTMContainerId());return startupConfig.hasOwnProperty(env.environment)&&startupConfig[env.environment].hasOwnProperty("googleTagAuthenticationId")&&startupConfig[env.environment].googleTagAuthenticationId.hasOwnProperty(product)?startupConfig[env.environment].googleTagAuthenticationId[product]:null},getGAContainerId=function(){return _getStartupParameter("googleAnalyticsContainerId",_getGTMContainerId())},getBaseUrlForApplicationContext=function(applicationContextName){return _getStartupParameter("baseUrl",applicationContextName)},getBaseUrlForCMSFiles=function(applicationContextName){return _getStartupParameter("cmsFilesUrl",applicationContextName)},setConfigParam=function(param,applicationContextName,paramValue){return _setStartupParameter(param,applicationContextName,paramValue)},getConfigParam=function(param,paramName){return _getStartupParameter(param,paramName)},getSightline=function(applicationContextName){return _getStartupParameter("sightline",applicationContextName);
},getPaypal=function(applicationContextName){var baseURL=_getStartupParameter("paypal",applicationContextName),cmd=["cmd=_express-checkout","desktop"===_getDevice()?"":"-mobile"].join("");return[baseURL,cmd].join("?")},getStartupConfig=function(environment,param,applicationContextName){return!!(startupConfig.hasOwnProperty(environment)&&startupConfig[environment].hasOwnProperty(param)&&startupConfig[environment][param].hasOwnProperty(applicationContextName))&&startupConfig[environment][param][applicationContextName]},setStartupConfig=function(environment,param,applicationContextName,configValue){startupConfig.hasOwnProperty(environment)&&startupConfig[environment].hasOwnProperty(param)&&startupConfig[environment][param].hasOwnProperty(applicationContextName)&&(startupConfig[environment][param][applicationContextName]=configValue)},getSiteVersion=function(){var appContext=getApplicationContextItem("application"),product=getApplicationContextItem("product");return"ios"===product?siteVersion.ios:siteVersion[appContext]},useAbsoluteRequests=function(){absoluteRequests=!0},getAbsoluteRequests=function(){return absoluteRequests};return{getApplicationContext:getApplicationContext,getApplicationContextItem:getApplicationContextItem,setApplicationContextItem:setApplicationContextItem,getBrazeDevice:getBrazeDevice,getBaseUrl:getBaseUrl,getBaseApiUrl:getBaseApiUrl,setConfigParam:setConfigParam,getConfigParam:getConfigParam,getGTMContainerId:getGTMContainerId,getGTMEnvironmentId:getGTMEnvironmentId,getGTMAuthenticationId:getGTMAuthenticationId,getGAContainerId:getGAContainerId,getBaseUrlForApplicationContext:getBaseUrlForApplicationContext,getBaseUrlForCMSFiles:getBaseUrlForCMSFiles,getStartupConfig:getStartupConfig,getSiteVersion:getSiteVersion,getSightline:getSightline,getPaypal:getPaypal,useAbsoluteRequests:useAbsoluteRequests,absoluteRequests:getAbsoluteRequests,getGoogleAPIKey:getGoogleAPIKey,getBaseServiceUrl:getBaseServiceUrl,getServiceApiUrl:getServiceApiUrl}}]);
define("Configuration", ["angular","matchMedia"], function(){});

vendors/tvg-content/contentMod.min.js
"use strict";angular.module("TVG.Content",["TVG.Configuration"]),angular.module("TVG.Content").filter("CMSValue",["ContentFac",function(ContentFac){return function(input,varsToReplaceList){return ContentFac.replaceVars(ContentFac.fetchValue(input),varsToReplaceList)}}]).filter("CMSLabels",["ContentFac",function(ContentFac){return function(label,section){try{return angular.fromJson(ContentFac.getCMSContent()[section])[label]}catch(e){return""}}}]),angular.module("TVG.Content").factory("ContentFac",["$http","$q","ConfigurationFac","$rootScope",function($http,$q,ConfigurationFac,$rootScope){function _setupResponse(namespace,data){var res;switch(namespace){case"widget":res=_setupWidgetResponse(data);break;default:res=data}return res}function _setupWidgetResponse(data){var widgets=[];return angular.forEach(data,function(value,key){if("_widgetCarousel"===key){var carouselValues=[];angular.forEach(value,function(cValue){carouselValues.push(cValue)}),widgets.push({type:"carousel",value:carouselValues})}else widgets.push({type:"standard",value:value})}),widgets}function _registrationDefaults(){return{}}function _depositDefaults(){return{depositsBetcashPeriodLimitExceeded:"No further BetCash deposits are permitted for this period.",depositsBetcashFirstDepositWaitingPeriod:"It takes 5 business days after your first BetCash deposit for your details to be saved. Tap Other Deposit Options for more choices.",depositsCreditCardPeriodLimitExceeded:"No further credit/debit card deposits are allowed for this period.",depositsGreenDotPeriodLimitExceeded:"No further GreenDot MoneyPak deposits are allowed for this period.",depositsSuccessfulDeposit:"Your deposit of ~depositamount~ from ~accounttype~ ~accountnumber~ was successfully deposited and should be available for wagering ~availabledate~.",depositsErrorDefault:'An error occurred while processing your request. Please contact customer service at <a data-rel="phone" href="tel:1-888-752-9884">1-888-PLAY-TVG (752-9884)</a> if the problem persists.',depositBetCashDisclaimer:"Disclaimer: By clicking the ~depositExecuteButton~ button you are authorising TVG to debit the amount specified from your checking account. By entering your PIN this serves as your electronic signature for this transaction. Funds will be transferred directly from your checking account to your TVG account, so make sure you have sufficient funds to avoid overdraft (NSF) charges from your bank.",depositExecuteButton:"Authorize Deposit",depositIBCTitle:"Pay directly from Bank Acct.",depositCheckingAccountNumber:"Checking Account Number",depositConfigOtherMenu:'[{"name":"Support","values":[{"name":"Email","url":"mailto:[email protected]","class":"item email-icon email"},{"name":"1-888-PLAY-TVG (752-9884)","url":"tel:+18887529884","class":"item phone-icon phone"}]}]',depositRoutingNumberInfo:"TVG BetCash is a secure and free way to transfer money from your bank account. BetCash Deposits will be available in your TVG Account immediately",depositCreditDebitInformation:"Credit and Debit Card Deposits will be available in your TVG Account immediately.",depositInvalidCardCodeMessage:"invalid input (16 digit number)",depositInvalidCardVerificationCode:"3 digit number on the back of your card",depositBetCashAvailabilityActionText:"For assistance please call 1-888-PLAY-TVG (752-9884).",depositGreenDotMoneyPakTitle:"Pay by GreenDot MoneyPak",depositGreenDotMoneyPakInvalidCardError:"Failed to Validate Cash Card",depositBetCashPendingMessageText:"BetCash Account unavailable. It takes about 5 business days after your first BetCash deposit for your details to be saved. Tap another deposit options for more choices.",depositInitialDataErrorMessage:"Failed to load necessary deposit data from server.",depositInitialDataErrorActionText:"For assistance please call  1-888-PLAY-TVG (752-9884).",depositGoToStoredPaymentsOption:"Or, use a stored payment method",depositGoToNewPaymentsOption:"Or, add a new payment method",depositNewCardTitle:"Pay by Credit/Debit",depositNewCardTypeLabel:" Card Type",depositNewCardNumberLabel:"Card Number",depositNewCardExpirationDateLabel:"Expiration Date",depositRoutingNumberLabel:"Bank Routing Number",depositBankNameLabel:"Bank Name",depositDriverLicenseStateLabel:"Driver's License State",depositDriverLicenseNumberLabel:"Driver's License Number",depositPasswordPinLabel:"TVG Account PIN / Password",depositInvalidPasswordPinText:"Invalid Pin / Password",depositCardVerificationNumberLabel:"CVV",depositAchOnFileSelectionLabel:"Pre-Authorized Account(s)",depositAmountFieldLabel:"I want to deposit $",depositMoneyPakNumberLabel:"MoneyPak Number",depositMinimumAmountText:"Minimum Deposit ~minAmount~",depositMaximumAmountText:"Maximum Deposit ~maxAmount~",depositBetCashUserAgreement:'{ "title": "BetCash Authorization Agreement", "body": "", "contentId": "depositBetCashUserAgreementHTML", "cancelButtonText": "OK", "cancelButtonEvent": "ok()" }',depositBetCashUserAgreementHTML:"I hereby authorize TVG to initiate credit and/or debit entries to my Checking Account indicated below and the depository institution; (bank, credit union, etc) below, hereinafter called the DEPOSITORY, to credit and/or debit the same to such account. I acknowledge that the origination of ACH transactions to my account must comply with the provision of U.S. law. This authorization is to remain in full force and effect until TVG and DEPOSITORY have received written notification from me of its termination in such time and in such manner as to afford TVG and DEPOSITORY a reasonable opportunity to act on it. I have the right to stop payment of a debit entry by notification to DEPOSITORY in such time as to afford DEPOSITORY a reasonable opportunity to act on it prior to charging account. After account has been changed, I have the right to have the amount of an erroneous debit immediately credited to my account by DEPOSITORY, provided I send written notice of such debit entry in error to DEPOSITORY within fifteen (15) days following issuance of an account statement or forty-five (45) days after posting, whichever occurs first. Please be advised that withdrawals from your TVG account may be subject to a five-business day hold pending bank verification of deposited funds. There will be a $35 fee charged for returned items.",depositConfigAvailableOptions:'["IBC","CC"]',depositConfigAmountOptions:'{"firstTimeAmountList":[ 20, 50, 100 ],"defaultAmountList":[ 20, 50, 100 ]}',depositWireTransferAndCheck:'<h2>Other payment methods</h2><h3>Checks or money orders</h3><p>To request deposit slips call 1-888-752-9884. Once you have received the slips mail your Check or Money Order made payable to "TVG" in the envelopes provBetfair ID:ed. For first-time deposits, a minimum of $25.00 is required to activate your account. There is no maximum deposit limit. Please allow 7-10 days for mail and processing time.Remember never send cash in the mail!</p><h2>Wire transfers</h2> <p>Wired funds that are received by TVG before 2:30pm PT Mon - Fri will be available same day. Requests for a withdrawal via Wire Transfer must be received by TVG no later than 2:00 pm PT to be processed in the same day. Wires requested after this time will be available in your bank account the next business day.</p> <p>To make a Wire Transfer Deposit or Wire Transfer Withdrawal complete and submit the appropriate form as instructed.</p> <p>Please keep in mind that your bank may charge fees for sending and receiving wire transfers. These fees vary from bank to bank, so please verify the amount with your bank.</p>'}}function _globalDefaults(){return{globalServersUnavailable:"It seems that we are unable to access our servers.\\n\\nAre you connected to the internet?",globalPrivacyPolicy:{title:"Privacy Policy",body:"",contentId:"globalPrivacyPolicyHtml",cancelButtonText:"OK",cancelButtonEvent:"ok()"},globalTermsAndConditions:{title:"Terms and Conditions",body:"",contentId:"globalTermsAndConditionsHtml",cancelButtonText:"OK",cancelButtonEvent:"ok()"},globalTermsAndConditionsHtml:'<div style="margin-top:10px;background:#fff;height:auto;padding-bottom:10px;">\r\n\r\n<p><b>WELCOME TO TVG!</b><br />\r\nThis agreement describes the terms and conditions applicable to the use of the account wagering services provided by TVG and our affiliated companies. The use of our wagering system will be taken as your acceptance of all of these terms, conditions, and disclosures contained herein.</p>\r\n\r\n<p><b>SUBSCRIPTION ELIGIBILITY</b><br />\r\nTo establish or maintain a wagering account, you must be:</p>\r\n\r\n<ul>\r\n<li>Be at least 21 years of age;</li>\r\n<li>Be a United States citizen or resident alien; and</li>\r\n<li>Be a resident of a state where wagering services are available.</li>\r\n<li>Certify that the application information you provide is accurate. False statements made in regard to an application may subject the applicant to prosecution.</li>\r\n</ul>\r\n\r\n<p><b>WAGER REWARDS*</b><br />\r\nWhen you sign up for a TVG wagering account you may enroll in our TVG Rewards Program (the “Rewards Program”) by checking the Opt-In box. You may also enroll at any other point by clicking on the Wager Rewards link at [custom:base-url]. Membership in the Rewards Program is subject to the Member’s continued status as a holder in good standing of a TVG wagering account and compliance in all respects to these Terms and Conditions as well as all of the Terms and Conditions applicable to Member’s Rewards Program. To opt-out of participation in the Rewards Program simply call TVG Customer Relations at 1-888-PLAY-TVG (752-9884).</p>\r\n\r\n<p>*TVG Wager Rewards may not be available through our Affiliate sites.</p>\r\n\r\n<p><b>WAGERING ACCOUNT PROCEDURES</b><br />\r\nYou may access your account and place wagers through our website at TVG.com, via touch-tone phone (IVR) by calling 1-888 TVG WAGER (884-9243), or through our mobile site, mobile.tvg.com, using tablets or mobile devices. Additionally, you may access your account and wager through TVG\'s Affiliate sites.</p>\r\n\r\n<p>For your protection and privacy, a wagering account can only be accessed by the registered account holder with a valid account number and Personal Identification Number (PIN).</p>\r\n\r\n<p>For your benefit, wagers placed through TVG wagering systems are sent into combined (commingled) pools at the host racetrack and are subject to all host racetrack rules and restrictions. From time to time TVG may operate separate wagering pools from the host racetrack when pools cannot be commingled. Separate pools will be subject to rules and regulations of the applicable jurisdictional authority.</p>\r\n\r\n<p>All wagers are considered final when a confirmation is received from our totalizator service provider and your wager is commingled with the host pool. If for some reason we are unable to commingle your wager with the host pool, your wager will be refunded to your account.</p>\r\n\r\n<p>We reserve the right to refuse any wagering transaction for any reason.</p>\r\n\r\n<p>Proceeds from successful wagers will be deposited into your account as soon as each race is posted official and winning payouts are available from the host racetrack.</p>\r\n\r\n<p>We reserve the right, at our sole discretion, to terminate an account at any time and for any reason. In the event an account is terminated, we shall return to you the balance of any funds in your account at the time of termination. If the balance of funds in your account at the time of termination is less than $2.00, we will retain the balance as an account termination fee. If your account is inactive for 6 consecutive months, a $1.75 per month account maintenance fee may be assessed until the balance reaches zero and the account is terminated.</p>\r\n\r\n<p>We reserve the right, at our sole discretion, to refer any dishonored financial instruments to collection agencies, check registries and credit reporting agencies and to collect any fees or charges incurred due to dishonored financial instruments and expenses, incurred as a result of our collection efforts, from the responsible accountholder.</p>\r\n\r\n<p>You authorize us to obtain, at our discretion, credit bureau reports in connection with your request for an account. If an account is opened, we may obtain, at our discretion, credit bureau reports in connection with the review of your account.</p>\r\n\r\n<p><b>WAGERING TRANSACTION CANCELLATIONS*</b><br />\r\nAs a TVG subscriber you may request to cancel wagering transactions on any race, with the exception of pools where cancellation is prohibited by the racetrack (Future Pools) or prohibited by the racetrack’s state jurisdictional authority. You may request to cancel up to twenty wagering transactions in any one day and up to two hundred wagering transactions in any calendar month (but not more than twenty in any one day) up to a maximum aggregate wagering transaction amount of $5,000 in a day and of $25,000 during that calendar month. Once the daily or monthly limits have been met, cancellations will no longer be allowed during the remainder of the day or calendar month. Wagering transaction cancellations may be made as follows:</p>\r\n\r\n<p>Online wagering transaction cancellations - A wagering transaction in the amount of $1,000* or less may be cancelled online at TVG.com.<br />\r\nWagering transaction cancellations through TVG’s Customer Relations Department - A wagering transaction in the amount of $1,000* or less may be cancelled upon your request and TVG’s verification that you have not reached your daily limit of $5,000 or monthly limit of $25,000 and/or daily and monthly limits of twenty wagering transactions per day or two hundred wagering transactions per month by calling 1-888-PLAY TVG (752-9884). Wagering transaction cancellation requests in the amount of more than $1,000* for a wagering transaction may be made by calling 1-888-PLAY TVG (752-9884) and must be approved by a TVG Customer Relations Supervisor after investigating the wager transaction cancellation request and verifying that you have not reached your daily limit of $5,000 or monthly limit of $25,000 and/or daily or monthly limits of twenty wagering transactions per day or two hundred wagering transactions per month. Accountholders requesting cancellations through the TVG Customer Relations Department must remain on the line until the wagering transaction cancellation is finalized. You will be notified of the completed cancellation or the reason the wagering transaction could not be cancelled.</p>\r\n\r\n<p><b>&nbsp;</b></p>\r\n\r\n<p><b>Important Wager Cancellation Restrictions</b></p>\r\n\r\n<p>TVG may refuse to accept a wager transaction cancellation request for any reason.<br />\r\nTVG may refuse to permit any accountholder the privilege of requesting or processing wagering cancellation requests for any reason.<br />\r\nWagering transactions may be cancelled until wagering is closed by the racetrack totalizator company for the racetrack hosting the live race on which the wagering transaction was made.<br />\r\nWagering transaction cancellations made by calling customer relations staff will be processed in the order received. TVG does not guarantee cancellation of a wager.<br />\r\nWagering transaction cancellations per subscriber account, whether made online or by customer relations staff, are limited to up to twenty wagering transactions in any one day and up to two hundred wagering transactions in any calendar month (but not more than twenty in any one day). No account holder may cancel wagering transactions over a maximum aggregate wagering transaction amount of $5,000 per day or $25,000 during a calendar month.<br />\r\nWagering transaction cancellations will not be provided via the IVR or Mobile.</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<p>*VA Residents Only --Wagering transaction cancellations are limited to $250 online at TVG.com. All wagering transaction cancellation requests over $250 must be reviewed and approved by a TVG customer relations supervisor and will be reported to the VA Racing Commission.</p>\r\n\r\n<p>*New York Residents Only – Online wagering transaction cancellations are limited to $500 in Win, Place or Show Pools on any betting entry and $50 for any one combination in multiple, exotic or super-exotic pools. Wagering transaction cancellation requests for amounts over $500 on Win, Place or Show pools on any betting entry and over $50 on any one combination in multiple, exotic or super-exotic pools may be requested by calling TVG’s customer relations center. Cancellations that, in the opinion of TVG management, may cause substantial altering of odds, prices or betting totals will be denied.</p>\r\n\r\n<p><b>TAX WITHHOLDING</b><br />\r\nBy law, any wager which results in proceeds of $600.00 or more must be reported to the Internal Revenue Service (IRS), if the amount of such proceeds is at least 300 times as large as the amount wagered. Any wager, which results in proceeds of more than $5,000.00, is subject to reporting and withholding, if the amount of such proceeds is at least 300 times as large as the amount wagered. If you are subject to IRS reporting and/or withholding requirements, we will send you Form W2-G summarizing information for tax purposes following the winning wager, less any applicable withholding, being deposited into your account. Upon written request, we will provide you with summarized tax information on your wagering activities.</p>\r\n\r\n<p>*Massachusetts Residents Only: By law, any wager that results in proceeds of $600.00 or more are subject to State Withholding Tax of 5%.</p>\r\n\r\n<p><b>WAGERING ACCOUNT BALANCE, DEPOSIT, AND WITHDRAWAL PROCEDURES</b><br />\r\nAccount deposits will be made available for customer use in accordance with normal financial industry availability standards. Deposits may be subject to deposit fee charges. Withdrawal requests will be processed within five business days after receipt. The availability of withdrawn funds is subject to standard banking restrictions.</p>\r\n\r\n<p>Your account balance bears no interest.</p>\r\n\r\n<p>You can check account balances through our various wagering platforms, our affiliate sites or by calling our Customer Relationship Representatives at 1-888 PLAY TVG (752-9884).</p>\r\n\r\n<p><b>DISCLOSURES AND POLICIES</b><br />\r\nPlease note: Your wagering account is for your personal use and is non-transferable. We reserve the right to void any wagering transaction if there is reason to believe that someone other than you deposited funds in or placed a wager from your account. By law, you must immediately notify us of a change in your state of residency by calling 1-888 PLAY TVG (752-9884). If you move to a state where wagering services are not available, we are required to terminate the account and return to you all remaining funds. We reserve the right to terminate an account at any time and for any reason.</p>\r\n\r\n<p>For your information, the data we (or any of our suppliers, including Equibase Company LLC) provide or compile generally is accurate, but occasionally errors and omissions occur as a result of incorrect data received from others, mistakes in processing and other causes. Accordingly, we along with our data providers and suppliers, including Equibase Company LLC, disclaim responsibility for the consequences, if any, of such errors and omissions, but would appreciate notification of any errors.</p>\r\n\r\n<p>TVG will report any activities that we reasonably believe constitute fraud or theft to the appropriate law enforcement authorities and may prosecute such activities to the full extent of the law. To the extent permitted by law, TVG will retain the proceeds resulting from such fraudulent activity or theft and use those funds to pay for damages and losses resulting from such fraudulent activity or theft.</p>\r\n\r\n<p><b>PATENT NOTICE</b><br />\r\nProducts and services offered by TVG, including the TVG.com website, are covered under one or more of the following United States patents: 6,554,709; 6,554,708; 6,089,981; 6,004,211; 5,830,068 to ODS Technologies, L.P. and/or its subsidiaries.</p>\r\n\r\n<p><b>LIABILITY LIMIT</b><br />\r\nExcept where provided otherwise by the regulatory authority, in no event will TVG, our Affiliate or our suppliers be liable for lost profits or any special, incidental or consequential damages arising out of or in connection with our services (however arising, including negligence). Our liability, and the liability of our Affiliates and suppliers, to you and any third parties in any circumstance is limited to the greater of (A) the total amount of wagers made by you through your account in the month prior to the action giving rise to liability, and (B) $100. Some states may not allow this limitation of liability, so the foregoing limitation may not apply to you.</p>\r\n\r\n<p><b>INDEMNIFICATION</b><br />\r\nYou agree to defend, indemnify and hold harmless TVG, its suppliers, distributors, contractors, subcontractors and its affiliates and related entities and their respective directors, officers, employees and agents, from and against all claims, losses, damages, liabilities and costs (included but not limited to reasonable attorneys’ fees and court costs), arising out of or relating to your breach of these Procedures, Terms and Conditions. The foregoing indemnification obligation shall survive termination of these Procedures, Terms and Conditions and your purchase of any product or service provided to you by TVG, its suppliers, distributors, contractors, subcontractors and its affiliates.</p>\r\n\r\n<p><b>ARBITRATION*</b><br />\r\nAny claim alleging that a non-payment has occurred will be resolved under the rules issued by the Oregon Racing Commission. All other controversies or claims arising out of or relating to our services (including but not limited to our account wagering services) will be settled by binding arbitration in accordance with the rules of the American Arbitration Association. Any such controversy or claim will be arbitrated on an individual basis, and may not be consolidated in any arbitration with any claim or controversy or any other party. The arbitration will be conducted in Beaverton, Oregon and judgment on the arbitration award may be entered into any court having jurisdiction over the losing party. Any party to the arbitration may seek any interim or preliminary relief from a court of competent jurisdiction in Beaverton, Oregon necessary to protect the rights or property of such party pending the completion of arbitration.<br />\r\n<br />\r\n*Maryland Residents Only: Unresolved claims alleging that nonpayment has occurred or unresolved exceptions to an account activity report will be resolved under the Telephone Account Betting Rules issued by the Maryland Racing Commission and provided along with your new subscriber information.</p>\r\n\r\n<p>*New York Residents Only: Unresolved claims alleging that nonpayment has occurred or unresolved exceptions to an account activity report will be resolved under the Rules issued by the New York Gaming Commission. The arbitration will be conducted in Albany, New York and judgment on the arbitration award may be entered into any court having jurisdiction over the losing party. Any party to the arbitration may seek any interim or preliminary relief from a court of competent jurisdiction in Albany, New York necessary to protect the rights or property of such party pending the completion of arbitration.</p>\r\n\r\n<p><b>WARRANTIES</b><br />\r\nTO THE FULL EXTENT PERMISSIBLE BY APPLICABLE LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.</p>\r\n\r\n<p><b>INFORMATION REQUESTS</b><br />\r\nAll requests for information, questions, account reconciliation, wagering discrepancies, etc., must be made to our Customer Relations Department by calling toll free 1-888 PLAY TVG (752-9884). For your protection, all conversations with our Customer Relationship Representatives are recorded and archived.</p>\r\n\r\n<p><b>OTHER</b><br />\r\nAccount wagering rules, policies, terms, conditions, and procedures are subject to change at any time. Changes will be posted on our Web site TVG.com - or can be obtained by calling 1-888-PLAY-TVG (752-9884). It is your responsibility to be aware of all wagering rules, policies, terms, conditions, and procedures, including any subsequent changes.</p>\r\n\r\n<p>This service has been approved by multiple regulatory authorities. All accounts are maintained and wagering information is processed at a licensed facility located in Oregon. It is not intended to be an offer or solicitation in those states where prohibited.</p>\r\n\r\n<p><b>We reserve the right to revise this policy, or any part thereof. Use of our service following notice of such revisions constitutes your acceptance of the revised policy.</b></p>\r\n</div>\r\n',globalPrivacyPolicyHtml:'<div style="margin-top:10px;background:#fff;height:auto;padding-bottom:10px;">\r\n\r\n<p><span class="eightptarial">PROTECTING YOUR PRIVACY </span></p>\r\n\r\n<p><span class="eightptarial">Protecting your privacy, along with financial transactions, is at the core of TVG\'s business. This notice describes the type of personally identifiable information we collect and how we use such information. </span></p>\r\n\r\n<p><span class="eightptarial">TYPE OF PERSONALLY IDENTIFIABLE INFORMATION COLLECTED</span></p>\r\n\r\n<p><span class="eightptarial">We collect, retain and use information about you to protect and administer your account and funds; to comply with applicable state and federal laws and regulations; and to help us design, improve and provide products and services in order to better serve you. When you subscribe as a TVG customer or when you submit a request or electronically pass information to TVG, you are sometimes asked to provide certain information, such as your name, e-mail address, mailing address, telephone numbers, social security number, birth date, credit card or bank account information. We ask for this in order to facilitate your requests, provide personalized services and communicate separately with you. Without your written or electronic consent, we will not collect personal information over our system unless it is necessary to provide you with our services or to prevent unauthorized access to our services. </span></p>\r\n\r\n<p><span class="eightptarial">DISCLOSURE OF PERSONALLY IDENTIFIABLE INFORMATION </span></p>\r\n\r\n<p><span class="eightptarial">You have chosen to do business with us, and we recognize our obligation to keep the information you provide to us secure and confidential. In our continuous effort to provide services that we believe you may find useful or of value, we may make your records available to better facilitate your requests, provide more personalized services and communicate separately with you. From time to time, we will use the information we collect to coordinate data entry and payments with the company that provides you with handicapping information, to coordinate marketing/rewards programs with partner racetracks, and to offer other enhancements to the service. Any third party receiving such information will have an obligation to hold it confidential. Without your written or electronic consent or where necessary to provide our services, we will not disclose your personally identifiable data to other companies outside of TVG or our affiliated companies. TVG does not currently sell customer information to advertisers or third party marketers. If we choose to do so in the future, we will provide you with information about how to remove your name from such lists. You will be provided with at least thirty (30) days within which to remove your name from such lists. If you would prefer that we not share any of your information with third parties, except under the circumstances where we are legally required, please contact us in writing at TVG, 19545 NW Von Neumann Drive, Suite 210, Beaverton, OR 97006-6935 to this effect. In circumstances where we inadvertently obtain information that appears to pertain to the commission of a crime or where we reasonably believe that an emergency involving immediate danger of death or serious physical injury to any person exists, TVG may voluntarily disclose the record or the contents of your communications or other information about you to law enforcement agencies and governmental entities without providing you advance notice. Upon receipt of an applicable search warrant or administrative, grand jury or trial subpoena, TVG may be required to disclose to the government or law enforcement agencies, without advance notice to you, the content of your communications and other records relating to your electronic communications, as well as the following records: your name and address; records of your online communication (including session times and duration); how long you have subscribed to our service(s) (including start date) and the type(s) of service(s) utilized; your telephone number or other subscriber account identifying number(s), including any Internet or network address(es) assigned to you by our network; and the means and source of your payment(s) (including any credit card or bank account number). </span></p>\r\n\r\n<p><span class="eightptarial">PROTECTING ONLINE ACCOUNT INFORMATION AND TRANSACTIONS </span></p>\r\n\r\n<p><span class="eightptarial">When you apply online to establish an account, access services or utilize online wagering, you provide personal and confidential information that is necessary for us to process your request. To ensure that your information remains confidential, the information is sent to us in a "secure session." Using the industry standard, Secure Socket Layer (SSL)-capable web browsers support encryption technology that helps prevent unauthorized users from viewing or manipulating your account information as it travels over the Internet. We will permit only authorized parties, who are trained in the proper handling of customer information, to have access to that information. Employees who violate our privacy policy will be subject to our disciplinary process. </span></p>\r\n\r\n<p><span class="eightptarial">RETENTION </span></p>\r\n\r\n<p><span class="eightptarial">We destroy customer information that is no longer necessary for the purpose for which it is collected unless there is a legitimate request or order to inspect the information still outstanding or the information remains in routine records that are periodically discarded under our document retention policies. The information that you have provided us is maintained in our management information system and billing systems, and is updated as new information is added. Accounting and billing records are retained for ten years for tax and accounting purposes or until the relevant income tax years for which the document was created have been closed for income tax purposes and/or all appeals have been exhausted. Records may remain on file even after you have terminated service. Subject to applicable law, we may also keep records to facilitate collection and to evaluate credit worthiness. </span></p>\r\n\r\n<p><span class="eightptarial">YOUR RIGHTS AND RESPONSIBILITIES </span></p>\r\n\r\n<p><span class="eightptarial">It is extremely important that you keep your account number, Personal Identification Number and other confidential account data protected and secure. Do not share your PIN or leave your computer unattended during an online wagering session. Please make sure that all information you provide to TVG is accurate and complete. Contact us immediately by email at [email protected], or by calling 1-888-PLAY-TVG (752-9884) if you find any discrepancies in your account data or if you wish to inspect the records pertaining to you at our offices. </span></p>\r\n<p><span class="eightptarial">NON-PERSONALLY IDENTIFIABLE INFORMATION</span></p>\r\n<p><span class="eightptarial">When your computer or mobile device contacts our web servers (for example, when you visit this website or view an HTML e-mail), our web servers automatically collect usage information.  Such usage information includes information about how our visitors use and navigate our website. It can include the number and frequency of visitors to each web page and the length of their stays, browser type, referrer data that identifies the web page visited prior and subsequent to visiting our website, and IP addresses. We also may determine the applicable technology available in order to serve you the most appropriate version of a web page, e-mail, advertising or promotional announcement or similar service. This information is used to analyze and improve this website and to provide you with a more fulfilling and relevant experience.</span></p>\r\n<p><span class="eightptarial">BROWSER COOKIES</span></p>\r\n<p><span class="eightptarial">Like many websites, we use browser “cookies”.  Cookies are a website’s way of remembering who you are.  A cookie is a small text file that is stored on your computer’s hard drive or stored temporarily in your computer’s memory. There are two kinds of cookies: those that are “session” oriented and those that are “persistent”.  Session cookies delete from your computer when you close your browser. Persistent cookies retain information for later use tomorrow, next week, next month, or whenever they are set to expire.  We use cookies to help us to identify account holders and to optimize their experience on our website.  Also, we will use cookies to monitor and maintain information about your use of this website.  Most web browsers accept cookies automatically.  You can delete cookies manually or set your browser to automatically delete cookies on a pre-determined schedule.  If you decline to accept cookies, you may not be able to take advantage of or participate in certain features of this website.</span></p>\r\n<p><span class="eightptarial">FLASH COOKIES</span></p>\r\n<p><span class="eightptarial">Our website enables the use of the Adobe Flash Player.  Adobe’s Flash Player is a commonly used software use by websites that offer video and other interactive content.  By default, your use of the Adobe Flash Player generates “flash cookies” (also known as “persistent identification elements” or “local shared objects”).  Adobe provides a short disclosure about Flash Cookies in its End User License Agreement, stating “Use of the web players, specifically the Flash Player, will enable the Software to store certain user settings as a local shared object on our computer.  These settings are not associated with you, but allow you to configure certain settings within the Flash Player.”  The Adobe Flash Player (and similar applications) use flash cookies to remember user settings, preferences and usage similar to the browser cookies referenced above, but flash cookies can store more information than browser cookies and are managed through a different interface than the one provided by your web browser.  You can control the degree to which you accept flash cookies by accessing your Adobe Flash Player management tools directly through the settings manager for Adobe Flash, located at http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager.html.  If you do not allow flash cookies to take any disc space on your computer, you may not be able to take advantage of or participate in certain features on the Site.  Users with a computer running the Windows operating system can view flash cookie files in this folder: \\Documents and Settings\\[username]\\Application Data\\Macromedia\\Flash Player.  Users with a computer running the Apple operating system can view flash cookie files in this folder: /users/[username]/Library/Preferences/macromedia/Flash Player.  Flash cookies, or LSO files are stored typically with an “.SOL” extension.</span></p>\r\n<p><span class="eightptarial">Although the Adobe Flash Player is a commonly used software used by websites that offer video content and/or games, it is not the only technology being used in the ever-shifting online and mobile content environment.  HTML5 is an increasingly popular web standard used for presenting content, especially content delivered to mobile devices.  HTML is the mark-up language used for the World Wide Web. Almost all web pages you visit on the internet are based around HTML code.  HTML5 is simply the fifth and latest iteration of this mark-up language that allows for more interactive web pages.  One of the real benefits of HTML5 is its potential to standardize the highly fragmented rich-media universe.  Some HTML5 code may allow your response to advertising and other activities to be monitored across websites and such information to be stored on your computer or mobile device.  Technology solutions that allow users to opt-out of or block this sort of tracking are being developed through browser add-ons and other tools.  However, please note that we do not process or comply with any browser’s “do not track” signal or other mechanism that indicates a request to disable online tracking.</span></p>\r\n<p><span class="eightptarial">WEB BEACONS</span></p>\r\n<p><span class="eightptarial">Our web pages or e-mail messages may contain a small graphic image called a web beacon, which is sometimes also called a "clear gif", that allows us to monitor and collect certain limited information about our users, such as the type of browser requesting the web beacon, the IP address of the computer that the web beacon is sent to and the time the web beacon was viewed. Web beacons can be very small or invisible to the user, but, in general, any electronic image viewed as part of a web page or e-mail, including HTML based content, can act as a web beacon. We may use web beacons to count visitors to our web pages or to monitor how our users navigate our website, and we may include web beacons in e-mail messages in order to count how many of the messages we sent were actually opened or acted upon. We use web beacons to compile aggregate statistics about our website and our marketing campaigns.</span></p>\r\n<p><span class="eightptarial">THIRD PARTY COOKIES</span></p>\r\n<p><span class="eightptarial">We allow third-party companies to collect anonymous information when you visit the website and to use that information to serve ads for TVG products or services or for products or services of other companies when you visit the website or other websites. These companies may use anonymous information (e.g., navigational, non-personally identifiable information, click stream information, browser type, time and date, subject of advertisements clicked or scrolled over, etc.) during your visits to the website and other websites in order to provide advertisements about our goods and services likely to be of interest to you. These parties may use a cookie or a third party web beacon, or other technologies, to collect this information.</span></p>\r\n\r\n<p><span class="eightptarial">THIRD PARTY WEB SITES </span></p>\r\n\r\n<p><span class="eightptarial">TVG\'s website contains links to other sites. TVG cannot be responsible for the privacy practices or the content of other web sites. When linking to other sites, please review their security and privacy policies. </span></p>\r\n\r\n<p><span class="eightptarial">RESPONSIBLE WAGERING </span></p>\r\n\r\n<p><span class="eightptarial">TVG&nbsp;is a recognized leader in the area of responsible wagering. TVG does not solicit any information from or market our services to anyone under the age of 21. National Gambling Helpline: 1-800-522-4700 We reserve the right to revise this policy, or any part thereof. Use of our service following notice of such revisions constitutes your acceptance of the revised policy.&nbsp;</span></p>\r\n</div>',
globalDepositErrorDefault:"An error occurred while processing your request. Please contact customer service at 1-888-PLAY-TVG (752-9884) if the problem persists.",globalDepositSuccess:"Your deposit of ~depositamount~ was successfully deposited and should be available for wagering ~availabledate~."}}function _loginDefaults(){return{loginForgotAccountPin:"Forgot your Account # or PIN? Call us.",loginForgotUsernamePassword:"Forgot your Username or Password? Call us.",loginUsernameAccountMissing:"Please enter your username or account number.",loginPasswordPinMissing:"Please enter your password or PIN.",loginPinMissing:"Please enter your PIN.",loginPasswordMissing:"Please enter your password.",loginInvalid:"You have entered an invalid login!  Please be aware that you have limited attempts before you lock your account.",loginPasswordPinPlaceholder:"Password / PIN",loginAccountLocked:"Your account has been locked. Please contact customer service at 1-888-752-9884 to unlock it.",loginResetPassword:"To reset your password, please call customer service at 1-888-752-9884.",loginResetPIN:"To reset your PIN, please call customer service at 1-888-752-9884.",loginWagerResponsibly:"AWARE – Always Wager Responsibly National Gambling Helpline: (800) 522-4700. Must be 21 years old or older and live in an area where TVG offers wagering services. Void where prohibited. Other restrictions apply.",loginPasswordPlaceholder:"Password",loginPinPlaceholder:"PIN",loginUsernameAccountPlaceholder:"Username / Account #",loginForgotCredentials:'<a href="tel:+1-888-752-9884" class="text-green">Forgot your credentials? Call us.</a>',loginJoinNowButton:'<button class="yellow"><strong>Join Now</strong></button>',loginInvalidCredentials:"Your login credentials are invalid"}}var self=this,cache={},cacheMessage={};return self.baseUrl=ConfigurationFac.getBaseUrl("content"),self.protocol=ConfigurationFac.getBaseUrl("protocol"),self.$rootScope=$rootScope,self.allResources={},self.setCMSContent=function(data){self.allResources=data},self.retrieveCache=function(){return cache},self.restoreCache=function(cacheData){cache=cacheData},self.getNamespaceContent=function(namespace){var deferred=$q.defer(),promise=self.getNamespaceContentAll([namespace]);return promise.then(function(data){if(data&&data.length&&data[0]&&Object.keys(data[0]).length){var res=_setupResponse(namespace,data[0]);deferred.resolve(res)}else deferred.reject()},function(){deferred.reject()}),deferred.promise},self.getNamespaceContentAll=function(namespaceList,withoutCache){var url,namespaceParam="?namespacelist=",useLegacyCMS=!1;if(self.$rootScope&&self.$rootScope.useAbsoluteRequests||ConfigurationFac.absoluteRequests())url=(self.protocol?self.protocol:"//")+self.baseUrl+"/deposit/api/public/v1.0/fetchAllDataFromCMS";else if(self.$rootScope&&self.$rootScope.activeFeatures&&self.$rootScope.activeFeatures.contentApi)url="/content/api/contentbynamespace";else if(namespaceList.indexOf("widget")>-1||namespaceList.indexOf("freepastperformances")>-1)url="/deposit/api/public/v1.0/fetchAllDataFromCMS",useLegacyCMS=!0;else{var productContext=ConfigurationFac.getApplicationContextItem("product"),deviceContext=ConfigurationFac.getApplicationContextItem("device"),locationContext=window.__TVG_GLOBALS__&&__TVG_GLOBALS__.BRAND?__TVG_GLOBALS__.BRAND:ConfigurationFac.getApplicationContextItem("location"),brand="all"==locationContext?"tvg":locationContext;url=ConfigurationFac.getServiceApiUrl("capi"),url=url+"/messages/namespace?product="+productContext+"&device="+deviceContext+"&brand="+brand,namespaceParam="&namespace="}var deferred=$q.defer(),context=JSON.stringify(ConfigurationFac.getApplicationContext()),config={accept:"application/json","x-tvgcontext":context},namespaceCacheList=[],namespace="";if(!withoutCache)if(namespaceList.length>1){for(var i=namespaceList.length-1;i>=0;i--)namespace=namespaceList[i],cache.hasOwnProperty(namespace)&&(namespaceList.splice(i,1),namespaceCacheList.push(namespace));namespaceCacheList.reverse()}else 1==namespaceList.length&&(namespace=namespaceList[0],cache.hasOwnProperty(namespace)&&(namespaceList=[],namespaceCacheList.push(namespace)));if(namespaceList.length>0)$http.get(url+namespaceParam+namespaceList.join(","),{headers:config}).success(function(data){var response=[];if(useLegacyCMS?response=data.response:namespaceList.forEach(function(namespace){data.response[namespace]&&response.push(data.response[namespace])}),withoutCache)deferred.resolve(response);else if(response.length){var x=0;angular.forEach(namespaceList,function(namespace,index){cache[namespace]=response[index],x++}),namespaceCacheList.forEach(function(namespace){response[x]={},angular.forEach(cache[namespace],function(value,index){response[x][index]=value}),x++}),deferred.resolve(response)}else deferred.reject(data)}).error(function(data){deferred.reject(data)});else{var response=[],x=0;namespaceCacheList.forEach(function(namespace){response[x]={},angular.forEach(cache[namespace],function(value,index){response[x][index]=value}),x++}),deferred.resolve(response)}return deferred.promise},self.getNamespaceMessagesContent=function(namespace,messagelist){var deferred=$q.defer(),messagelistArray=messagelist.split(","),promise=self.getNamespaceMessages(namespace,messagelistArray);return promise.then(function(data){if(data&&data.length&&data[0]&&Object.keys(data[0]).length){var res=_setupResponse(namespace,data[0]);deferred.resolve(res)}else deferred.reject()},function(){deferred.reject()}),deferred.promise},self.getNamespaceMessages=function(namespace,messagelist){var url;url=self.$rootScope&&self.$rootScope.useAbsoluteRequests||ConfigurationFac.absoluteRequests()?(self.protocol?self.protocol:"//")+self.baseUrl+"/deposit/api/public/v1.0/fetchMessageFromCMS":self.$rootScope&&self.$rootScope.activeFeatures&&self.$rootScope.activeFeatures.contentApi?"/content/api/contentbynamespace":"/deposit/api/public/v1.0/fetchMessageFromCMS";var deferred=$q.defer(),context=JSON.stringify(ConfigurationFac.getApplicationContext()),config={accept:"application/json","x-tvgcontext":context},messageCacheList=[],message="";if(messagelist.length>1){for(var i=messagelist.length-1;i>=0;i--)message=messagelist[i],cacheMessage.hasOwnProperty(message)&&(messagelist.splice(i,1),messageCacheList.push(message));messageCacheList.reverse()}else 1==messagelist.length&&(message=messagelist[0],cacheMessage.hasOwnProperty(message)&&(messagelist=[],messageCacheList.push(message)));if(messagelist.length>0)$http.get(url+"?namespace="+namespace+"&messagelist="+messagelist.join(","),{headers:config}).success(function(data){if("success"==data.status&&data.response.length){var x=0;angular.forEach(messagelist,function(message,index){cacheMessage[message]=data.response[index],x++}),messageCacheList.forEach(function(message){data.response[x]={},angular.forEach(cacheMessage[message],function(value,index){data.response[x][index]=value}),x++}),deferred.resolve(data.response)}else deferred.reject(data)}).error(function(data){deferred.reject(data)});else{var response=[],x=0;messageCacheList.forEach(function(message){response[x]={},angular.forEach(cacheMessage[message],function(value,index){response[x][index]=value}),x++}),deferred.resolve(response)}return deferred.promise},self.fetchValue=function(value){for(var p in self.allResources)if(self.allResources.hasOwnProperty(p)&&value.toLowerCase()==p.toLowerCase())return self.allResources[p]},self.replaceVars=function(string,varsToReplace){for(var property in varsToReplace)if(varsToReplace.hasOwnProperty(property)){var re=new RegExp("~"+property+"~","g");string=string.replace(re,varsToReplace[property])}return string},self.fetchAllDataFromCMS=function(namespacesList,featuresSeparated,withoutCache){var deferred=$q.defer(),promise=self.getNamespaceContentAll(namespacesList,withoutCache);return angular.forEach(namespacesList,function(name){switch(name.toLowerCase()){case"global":angular.extend(self.allResources,_globalDefaults());break;case"deposits":angular.extend(self.allResources,_depositDefaults());break;case"login":angular.extend(self.allResources,_loginDefaults());break;case"registration":angular.extend(self.allResources,_registrationDefaults())}}),promise.then(function(data){featuresSeparated&&(self.allResources._featureToggle=data[data.length-1],data.pop()),angular.forEach(data,function(value){angular.extend(self.allResources,value)}),deferred.resolve(self.allResources)},function(){deferred.reject()}),deferred.promise},{baseUrl:self.baseUrl,context:self.context,updateContext:function(){},getNamespaceContent:function(namespace){return self.getNamespaceContent(namespace)},getCMSContent:function(){return self.allResources},getNamespaceMessagesContent:function(namespace,messagelist){return self.getNamespaceMessagesContent(namespace,messagelist)},setCMSContent:self.setCMSContent,fetchAllDataFromCMS:self.fetchAllDataFromCMS,replaceVars:self.replaceVars,fetchValue:self.fetchValue,restoreCache:self.restoreCache,retrieveCache:self.retrieveCache}}]);
define("Content", ["angular"], function(){});

modules/AppCore/providers/appRootFac.js
'use strict';

define('AppRootFac',['lodash'],
    function (_) {

        AppRootFac.$inject = [
            '$rootScope',
            '$uibModal',
            'ConfigurationFac',
            'ContentFac',
            'FeaturesHandlerSvc',
            '$uibModalStack',
            '$location',
            '$window',
            'CMSCONTENT',
            'CookieFac',
            'UserSessionSvc',
            'GTMFac',
            'NewWindowGridFac',
            '$document',
            '$timeout',
            'SecuritySvc',
            'FavoriteTracksFac'
        ];

        function AppRootFac($rootScope,
                            $uibModal,
                            ConfigurationFac,
                            ContentFac,
                            FeaturesHandlerSvc,
                            $uibModalStack,
                            $location,
                            $window,
                            CMSCONTENT,
                            CookieFac,
                            UserSessionSvc,
                            GTMFac,
                            NewWindowGridFac,
                            $document,
                            $timeout,
                            SecuritySvc,
                            FavoriteTracksFac) {
            var doneUserGTM = false;
            var userSessionUnwatch;
            var GTMUserLoggedOutUnwatch;

            // Configuration needs to be set again when angular app boots
            ConfigurationFac.setApplicationContextItem('product', productContext);
            ConfigurationFac.setApplicationContextItem('application', applicationContext);
            ConfigurationFac.setApplicationContextItem('location', locationContext);

            //rootScope config variables
            $rootScope.isIE = document.documentMode !== undefined;//Check if the current browser is the IE.
            $rootScope.activeFeatures = {};
            $rootScope.enableGTM = true;
            $rootScope.appName = 'TVG';
            $rootScope.allowedRaces = [];
            $rootScope.uniqueVideoId = 0;
            $rootScope.withdrawData = {
                haveRequestedInfo: false,
                pendingListWithdraw: []
            };
            $rootScope.firstLoad = true;
            $rootScope.locationContext = locationContext;
            $rootScope.productContext = 'tvg4';

            // Location overrides
            if (locationContext == 'nj') {
                $rootScope.appName = '4NJBets';
                $rootScope.product = $rootScope.product + locationContext;
            }

            if ($location.path() === "/deposit") {
                $rootScope.showAccountPanel = true;
            }

            ContentFac.setCMSContent(CMSCONTENT);
            ContentFac.restoreCache(cmsCache);

            $rootScope.appReadyFired = false;
            $rootScope.sessionRequested = false;
            $rootScope.appReady = {};

            function _initBetSlip() {
                FeaturesHandlerSvc.init();

                if ($rootScope.activeFeatures.openBetWindowsInGrid) {
                    NewWindowGridFac.windowFunctions($window);
                }



                $rootScope.productContext = 'tvg4';
                applicationContext = 'desktop';
                ConfigurationFac.setApplicationContextItem('application', applicationContext);
                ConfigurationFac.setApplicationContextItem('device', 'desktop');
                $rootScope.cssFile = $rootScope.productContext;
                $rootScope.isBetslipApp = true;

                _gtmSessionWatchers();
            }

            function _redirectFromPaymentMethod(path) {
                if (_.includes(path, 'activeTab=sightline')) {
                    return {
                        tla: 'SLN',
                        menutab: getActiveMenuTab(path),
                        fullname: 'Sightline'
                    };
                }

                if (_.includes(path, 'activeTab=paypal')) {
                    return {
                        tla: 'PAY',
                        menutab: getActiveMenuTab(path),
                        fullname: 'Paypal'
                    };
                }

                return {};
            }

            /* ----- RootScope Functions ----- */

            function _fnGo() {
                $rootScope.go = function (path, param) {
                    param = typeof param !== 'undefined' ? param : false;

                    $timeout(function () {
                        if (param) {
                            $location.path(path).search(param);
                        }
                        else {
                            $location.path(path);
                        }
                    });


                    if (path === 'joinnow') {
                        $rootScope.firstTimeJoinNow = true;
                    }
                };
            }

            function _fnGetLocationPath() {
                $rootScope.getLocationPath = function () {
                    return $location.path();
                };
            }

            /* ----- RootScope Listeneners ----- */

            function _onUser() {
                var locationOnuser = $rootScope.$on('user', function () {
                    $rootScope.hasNeverLogin = !CookieFac.getCookie("hasLoginOnce");
                    _launchGTMEvent();
                    locationOnuser();
                });
            }

            function _onLocationChangeStart() {
                var redirectFromPaymentObj;

                $rootScope.$on('$locationChangeStart', function () {
                    var url = $location.url();
                    redirectFromPaymentObj = _redirectFromPaymentMethod(url);
                    // Scroll to top
                    _scrollToTop();

                    // On mobile videos need to be stopped to not crash application
                    if (applicationContext === 'mobile') {
                        _stopVideos();
                    }

                    if ($rootScope.userSession !== undefined || doneUserGTM) {
                        _launchGTMEvent();
                    }

                    // this prevents the session expired popup alert not to be dismissed when
                    // the session expires and we redirect the user to the home route
                    if ($location.hash() !== 'sessionExpired') {
                        // other than that, always dismiss all modals when changing routes
                        $uibModalStack.dismissAll();
                    }

                    var route = $location.path().split("/")[1];

                    $rootScope.hasNeverLogin = !CookieFac.getCookie("hasLoginOnce");
                    $rootScope.logoutOk = true;
                    $rootScope.loginOk = true;
                    $rootScope.isLandingPageLocation = !!(route == "joinnow" || route == "landingpage");

                    $rootScope.pageTitle = "";
                    $rootScope.pageTitleRaceMobile = "";
                    $rootScope.pageTitleTrackNameMobile = "";
                    $rootScope.pageSubTitle = "";
                    $rootScope.moreDetails = "";

                    if ($location.path() === "/registration") {
                        RegistrationPageGTMFac.register();
                        $rootScope.pageTitle = $rootScope.appName;
                        $rootScope.pageTitleRaceMobile = $rootScope.appName;
                        $rootScope.pageTitleTrackNameMobile = "";
                        $rootScope.pageSubTitle = "Member Registration";
                        $rootScope.moreDetails = "";
                        $rootScope.showNewRegistration = !!$location.search().redirected;
                    }

                    if (!_.isEmpty(redirectFromPaymentObj)) {
                        $rootScope.activeOption = {
                            tla: redirectFromPaymentObj.tla,
                            isPaymentConfirmation: _isPaymentConfirmation(url),
                            userCancelled: _userCancelled(url)
                        };
                        $rootScope.$emit(
                            'redirectFrom'.concat(redirectFromPaymentObj.fullname),
                            redirectFromPaymentObj.menutab,
                            $rootScope.activeOption.isPaymentConfirmation,
                            $rootScope.activeOption.userCancelled
                        );
                    } else {
                        $rootScope.activeOption = undefined;
                    }
                });
            }

            function _isPaymentConfirmation(url) {
                return _.includes(url, '&isPaymentConfirmation=true');
            }

            function _userCancelled(url) {
                return url.indexOf('&userCancelled=true') > -1;
            }

            function _onLocationChangeSuccess() {
                $rootScope.$on('$locationChangeSuccess', function () {
                    // Scroll to top
                    _scrollToTop();
                });
            }

            function _onRouteChangeStart() {
                $rootScope.$on("$routeChangeStart", function (event, next, current) {
                    $rootScope.pageLoadedFired = false;

                    // Scroll to top
                    _scrollToTop();

                    if ((!$rootScope.hasOwnProperty('userSession') || !$rootScope.userSession) && $rootScope.firstLoad === true) {
                        $rootScope.logoutOk = false;
                        $rootScope.firstLoad = false;
                    }

                    if (angular.isString(next.toggleKey)) {
                        var isToggleOff = $rootScope.activeFeatures[next.toggleKey] === false;
                        if (isToggleOff) {
                            $timeout(function () {
                                $location.path("/");
                            });
                        }
                    }

                    if(!$rootScope.sessionRequested) {
                        UserSessionSvc.validate().then(function () {
                            ConfigurationFac.setApplicationContextItem('user_status', 'logged_in');

                            if ($rootScope.userSession && next.originalPath === '/registration') {
                                $timeout(function () {
                                    $location.path('/');
                                });
                            }

                        }, function (response) {
                            //invalidate session only when we get a response with an ErrorCode or if user data doesn't exist
                            if(response.hasOwnProperty('messageKey') && response.messageKey == 'Not Authenticated' || !$rootScope.user) {

                                ConfigurationFac.setApplicationContextItem('user_status', 'logged_out');

                                $rootScope.user = null;
                                $rootScope.userSession = false;
                                FavoriteTracksFac.clearFavoriteList();

                                $rootScope.$broadcast('sessionInvalid');
                            }
                        }).finally(function () {
                            $rootScope.logoutOk = true;
                            $rootScope.sessionRequested = true;
                            $rootScope.appReady.session = true;
                            $rootScope.$broadcast('session');
                        });
                    }

                    if (current && next && next.originalPath !== current.originalPath && next.originalPath !== current.redirectTo && next.title !== 'Races' && next.title !== 'Results') {
                        $rootScope.appTitle = next.title;

                    } else {
                        $rootScope.appTitle = next.title || 'Home Screen';
                        $rootScope.pageReload = current ? true : false;
                        if (next.title === 'Races' && $rootScope.layout !== 'desktop') {
                            if (next.pathParams.raceNumber) {
                                $rootScope.appTitle = 'Races | Free Handicapping';
                            } else {
                                $rootScope.appTitle = 'Races | By Time';
                            }
                        }
                        if (next.title === 'Results') {
                            $rootScope.appTitle = 'Results | By Time';
                        }
                    }

                    if ($location.path() === "/registration" && angular.element(document.querySelector('#smartbanner')).length) {
                        angular.element(document.querySelector('#smartbanner')).hide();
                    } else if (angular.element(document.querySelector('#smartbanner')).length) {
                        angular.element(document.querySelector('#smartbanner')).show();
                    }

                    var route = $location.path().split("/")[1];
                    if (route == "bets" && productContext == "touch2") {
                        if ($rootScope.user) {
                            $uibModal.open({
                                backdropClass: 'tvgmodal-backdrop',
                                windowTemplateUrl: 'js/modules/Utilities/templates/modal-window.html',
                                windowClass: 'account',
                                template: '<stack-view data-root-url="js/mobile/modules/Account/templates/my-bets.html" data-root-title="My Bets"></stack-view>'
                            });
                        } else {
                            $uibModal.open({
                                backdropClass: 'tvgmodal-backdrop',
                                windowTemplateUrl: 'js/modules/Utilities/templates/modal-window.html',
                                windowClass: 'login',
                                template: '<login name="loginModal"></login>'
                            });
                        }
                        event.preventDefault();
                    } else if ((route === 'login' || route === 'dev-login') && productContext === 'tvg4') {
                        $rootScope.$broadcast("callLoginRequiredModal");

                        var gtmEvent = {
                            screenName: 'Login Page **',
                            sectionName: 'Login | Login Page'
                        };

                        GTMFac.GTMEvent().send($rootScope, '', gtmEvent);
                    }
                });
            }

            function _onScrollToTop() {
                $rootScope.$on('scrollToTop', function () {
                    _scrollToTop();
                });
            }

            function _onLogin() {
                $rootScope.$on('login', function () {
                    ConfigurationFac.setApplicationContextItem('user_status', 'logged_in');

                    var cmsCache = ContentFac.retrieveCache();
                    if (cmsCache.hasOwnProperty('landingpages')) {
                        delete cmsCache.landingpages;
                    }
                    ContentFac.restoreCache(cmsCache);

                    $rootScope.$broadcast('afterLogin', true);

                    $rootScope.hasNeverLogin = !CookieFac.getCookie("hasLoginOnce");
                });
            }

            function _onLogout() {
                $rootScope.$on("logout", function () {

                    var cmsCache = ContentFac.retrieveCache();

                    if (cmsCache.hasOwnProperty('landingpages')) {
                        delete cmsCache.landingpages;
                    }

                    ContentFac.restoreCache(cmsCache);

                    if (applicationContext === 'mobile') {
                        _stopVideos();
                    }

                    $rootScope.withdrawData = {
                        haveRequestedInfo: false,
                        pendingListWithdraw: []
                    };
                });
            }

            function _onSessionExpired() {
                $rootScope.$on('sessionExpired', function () {
                    SecuritySvc.logout().then(function () {
                        $timeout(function () {
                            $location.path('/').hash('sessionExpired');
                        });
                    });
                });
            }

            function _onAppReady() {
                $rootScope.$on("appReady", function (event, component) {
                    if ($location.path() === "/") {
                        var appReady = true;

                        if ($rootScope.appReady.hasOwnProperty(component)) {
                            $rootScope.appReady[component] = true;
                        }

                        for (var prop in $rootScope.appReady) {
                            if (!$rootScope.appReady[prop]) appReady = false;
                        }

                        if (appReady) {
                            if (!$rootScope.appReadyFired) {
                                $rootScope.appReadyFired = true;

                                for (var prop in $rootScope.appReady) {
                                    $rootScope.appReady[prop] = false;
                                }
                            }
                            else {
                                for (var prop in $rootScope.appReady) {
                                    $rootScope.appReady[prop] = false;
                                }
                            }
                        }
                    }
                });
            }

            function _onPageLoaded() {
                $rootScope.$on("pageLoaded", function (event, page) {
                    if (!$rootScope.pageLoadedFired) {
                        $rootScope.pageLoadedFired = true;
                    }
                });
            }

            /* ----- GTM Event Listeners ----- */

            function _gtmUserSession() {
                return $rootScope.$watch("userSession", function (currentValue, prevValue) {
                    var isDirectUrlRegistration = (typeof (prevValue) === "undefined" && $location.path().indexOf('registration') === 1);
                    if ((typeof (prevValue) === "undefined" && typeof (currentValue) !== "undefined")
                        || isDirectUrlRegistration) {
                        _launchGTMEvent();
                        //to remove watch
                        if (!isDirectUrlRegistration) {
                            doneUserGTM = true;
                        }
                        _launchGTMAndGAAndUnwatch();
                    }
                });
            }

            function _gtmSessionWatchers() {
                if ($rootScope.enableGTM) {
                    if ($rootScope.isBetslipApp) {
                        // just launch GTM and GA
                        _createGTMandGA();
                        return;
                    }
                    // GTM login and logout watchers
                    userSessionUnwatch = _gtmUserSession();
                    GTMUserLoggedOutUnwatch = _gtmUserLoggedOut();
                }
            }

            function _gtmUserLoggedOut() {
                return $rootScope.$on('GTMUserLoggedOut', function () {
                    doneUserGTM = true;
                    _launchGTMEvent();
                    _launchGTMAndGAAndUnwatch();
                });
            }

            function _launchGTMAndGAAndUnwatch() {
                // launch GTM and GA
                _createGTMandGA();
                GTMUserLoggedOutUnwatch();
                userSessionUnwatch();
            }

            /* ----- GTM Functions ----- */

            function _launchGTMEvent() {
                if (_shouldLaunchPageViewEvent()) {
                    var eventParams = {
                        event: 'ga_pageload',
                        graphVersion: $rootScope.activeFeatures.useJavaGraph ? 'v2' : 'v1'
                    };

                    GTMFac.GTMEvent().send($rootScope, '', eventParams);
                }
            }

            function _shouldLaunchPageViewEvent() {
                return _isPathValid() && _hasSectionName();
            }

            function _isPathValid() {
                return $location.path().split('/').length > 1;
            }

            function _hasSectionName() {
                return GTMFac.Tvg4SectionName() !== "";
            }

            function _createGTMandGA() {
                var noScript = document.createElement("noscript");
                noScript.text =
                    '<iframe src="//www.googletagmanager.com/ns.html?id=GTM-' +
                    ConfigurationFac.getGTMContainerId() +
                    '" height="0" width="0" style="display:none;visibility:hidden"></iframe>';
                document
                    .getElementsByTagName("body")
                    .item(0)
                    .appendChild(noScript);

                /**
                 * Google tag manager injection
                 */
                (function(w, d, s, l, i, e, a) {
                    w[l] = w[l] || [];
                    w[l].push({
                        "gtm.start": new Date().getTime(),
                        event: "gtm.js"
                    });
                    var f = d.getElementsByTagName(s)[0],
                        j = d.createElement(s),
                        dl = l != "dataLayer" ? "&l=" + l : "";
                    j.async = true;
                    j.src = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
                    if (e && a) {
                        j.src =
                            "https://www.googletagmanager.com/gtm.js?id=" +
                            i +
                            dl +
                            "&gtm_auth=" +
                            a +
                            "&gtm_preview=env-" +
                            e;
                    } else {
                        j.src = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
                    }
                    f.parentNode.insertBefore(j, f);
                })(
                    window,
                    document,
                    "script",
                    "dataLayer",
                    "GTM-" + ConfigurationFac.getGTMContainerId(),
                    ConfigurationFac.getGTMEnvironmentId(),
                    ConfigurationFac.getGTMAuthenticationId()
                );

                /* eslint-disable */
                (function (i, s, o, g, r, a, m) {
                    i['GoogleAnalyticsObject'] = r;
                    i[r] = i[r] || function () {
                            (i[r].q = i[r].q || []).push(arguments)
                        }, i[r].l = 1 * new Date();
                    a = s.createElement(o),
                        m = s.getElementsByTagName(o)[0];
                    a.async = 1;
                    a.src = g;
                    m.parentNode.insertBefore(a, m)
                })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
                /* eslint-enable */

                ga('create', ConfigurationFac.getGAContainerId(), 'auto');
            }

            function _scrollToTop() {
                var body = angular.element($document[0].getElementsByTagName("body"));
                if (body) {
                    $window.scrollTo(0, 0);
                    $window.scrollTo(0, 0);
                }
            }

            function _onDepositOpen() {
                $rootScope.$on('open', function (event, data) {
                    if (data === 'Deposit')
                        _goToDeposit();
                });
            }

            return {
                initBetSlip: _initBetSlip,
                fnGo: _fnGo,
                fnGetLocationPath: _fnGetLocationPath,
                onUser: _onUser,
                onLocationChangeStart: _onLocationChangeStart,
                onLocationChangeSuccess: _onLocationChangeSuccess,
                onRouteChangeStart: _onRouteChangeStart,
                onLogin: _onLogin,
                onLogout: _onLogout,
                onSessionExpired: _onSessionExpired,
                onAppReady: _onAppReady,
                onPageLoaded: _onPageLoaded,
                launchGTMEvent: _launchGTMEvent,
                createGTMandGA: _createGTMandGA,
                onDepositOpen: _onDepositOpen,
                onScrollToTop: _onScrollToTop
            };
        }

        return AppRootFac;
    });

modules/AppCore/providers/appRequestInterceptor.js
'use strict';

define(
    'AppRequestInterceptor',[],
    function () {
        function AppRequestInterceptor($httpProvider, $provide) {

            function _setHeadersRequest() {

                // @TODO remove RequestContextHeaders from SecurityMod and delete all manual overrides
                // of the 'x-tvg-context' header
                var TVG_CONTEXTS = {
                    tvg4_nj: 'tvg4-4njbets',
                    tvg4_pa: 'tvg4-pabets',
                    tvg4_all: 'tvg4-tvg',
                    tvg4_ia: 'tvg4-iowa',
                    touch2_nj: 'touch2-4njbets',
                    touch2_pa: 'touch2-pabets',
                    touch2_all: 'touch2-tvg',
                    touch2_ia: 'touch2-iowa'
                };

                // Set headers for all calls back to the server so it has context
                $httpProvider.defaults.headers.common = {
                    'X-ClientApp': window.clientApp,
                    'x-tvg-context': TVG_CONTEXTS[window.clientApp + '_' + window.locationContext]
                };

                $httpProvider.defaults.withCredentials = true;


                $httpProvider.interceptors.push(function () {
                    return {
                        'request': function (config) {
                            // Set headers only for tvg.com or us.betfair.com service calls back to the server so it has context
                            if (config.url.indexOf("tvg.com") != -1 || config.url.indexOf("us.betfair.com") != -1) {
                                config.headers['X-ClientApp'] = window.clientApp;
                                config.headers['x-tvg-context'] = TVG_CONTEXTS[window.clientApp + '_' + window.locationContext];
                            }

                            //Make sure we identify as a XMLHttpRequest when doing ajax calls
                            if (config.url.indexOf("ajax/") != -1) {
                                config.headers['X-ClientApp'] = window.clientApp;
                                config.headers['x-requested-with'] = 'XMLHttpRequest';
                                config.headers.Accept = 'application/json';
                            }
                            return config;
                        }
                    };
                });
            }

            function _setInterceptResponse() {

                //http interceptor used to detect User Session errors
                $httpProvider.interceptors.push(function ($q, $rootScope) {
                    return {
                        'response': function (response) {
                            if ($rootScope.user && response.data && ((response.data.status == 'error' && response.data.response && response.data.response.errorMessage == 'ApiUserSessionNotFound')
                                    || (response.data.ErrorStatus && response.data.ErrorStatus.name == 'Error' && response.data.ErrorCode && response.data.ErrorCode == 'ApiUserSessionNotFound')
                                )) {
                                $rootScope.$broadcast('sessionExpired');
                            }

                            return response;
                        },
                        'responseError': function (response) {
                            if ($rootScope.user && response.status === 403) {
                                $rootScope.$broadcast('sessionExpired');
                            }

                            return $q.reject(response);
                        }
                    };
                });
            }

            return {
                setHeadersRequest: _setHeadersRequest,
                setInterceptResponse: _setInterceptResponse,
                setMetadata: function () {
                    $provide.value('METADATA', __METADATA || {});
                    __METADATA = null;
                },
                setFeatures: function () {
                    $provide.value('FEATURES', __FEATURES);
                    __FEATURES = null;
                },
                setCmsContent: function () {
                    $provide.value('CMSCONTENT', __CMSCONTENT);
                    __CMSCONTENT = null;
                },
                $get: function () {
                    return {
                        xclientapp: $httpProvider.defaults.headers.common,
                        metadata: METADATA || null,
                        features: METADATA || null,
                        cmscontent: METADATA || null
                    };
                }
            };
        }

        return AppRequestInterceptor;
    });

modules/GTM/providers/GTMFac.js
'use strict';

define('GTMFac',['lodash', 'angular'], function (_, angular) {

    function GTMFac(
        $location,
        $rootScope,
        $routeParams,
        ScreenNames,
        SectionNames,
        METADATA,
        RaceUrlFac
    ) {

        var talentPicksList;

        function _formatGALAbelUpperCase(input) {
            if (input) {
                var result = input.replace(/([A-Z]+)/g, ",$1").replace(/^,/, "");

                return result.replace(/,/g, ' ').replace(/\b\w/g, function (m) {
                    return m.toUpperCase();
                });
            } else {
                return '';
            }
        }

        var _GAPageviews = function () {
            var sendCondition = true;
            var pageviewTitle = '';

            return {
                addPageViewTitle: function (name) {
                    pageviewTitle = name;
                    return this;
                },
                when: function (condition) {
                    if (sendCondition) {
                        sendCondition = condition;
                    }
                    return this;
                },
                send: function () {
                    if (sendCondition && typeof ga !== 'undefined') {
                        ga('send', 'pageview', {
                            title: pageviewTitle
                        });
                        return pageviewTitle;
                    } else {
                        return '';
                    }
                }
            };
        };

        var _GTMEvent = function () {
            var sendCondition = true;
            return {
                when: function (condition) {
                    if (sendCondition) {
                        sendCondition = condition;
                    }
                    return this;
                },
                send: function (scope, _eventName, aditionalParams, sendEvent) {
                    if (sendCondition) {
                        return sendGTMEvent(scope, _eventName, aditionalParams, sendEvent);
                    } else {
                        return false;
                    }
                }
            };
        };

        var _genericEvent = function (eventData) {
            var event = _EventBuilder()
                .withGaEventCategory(eventData.category)
                .withGaEventAction(eventData.action)
                .withGaEventLabel(eventData.gaLabel)
                .withEventLabel(eventData.label)
                .withScreenName(_tvg4ScreenName())
                .withSectionName(_tvg4SectionName())
                .build();

            var track = $routeParams.trackAbbr || $routeParams.trackName;

            if (track && $routeParams.raceNumber) {
                if (METADATA.allTracks && METADATA.allTracks.hasOwnProperty(track) && METADATA.hasOwnProperty('allTracks') && METADATA.allTracks[track].Name) {
                    event.trackName = METADATA.allTracks[track].Name;
                } else {
                    // Fallback in case there are inconsistencies between services.
                    event.trackName = track;
                }

                var raceNumber = $routeParams.raceNumber;
                if (typeof raceNumber === 'string') {
                    raceNumber = raceNumber.replace('race-','');
                }
                event.raceNumber = "R" + raceNumber;
            }

            return event;
        };

        function _EventBuilder() {
            var event = {};
            return {
                withScreenName: function(screenName) {
                    event.screenName = screenName;
                    return this;
                },
                withSectionName: function(sectionName) {
                    event.sectionName = sectionName;
                    return this;
                },
                withGaEventAction: function (gaEventAction) {
                    event.gaEventAction = gaEventAction;
                    return this;
                },
                withGaEventCategory: function (gaEventCategory) {
                    event.gaEventCategory = gaEventCategory;
                    return this;
                },
                withGaEventLabel: function (gaEventLabel) {
                    event.gaEventLabel = gaEventLabel;
                    return this;
                },
                withEventLabel: function (eventLabel) {
                    event.eventLabel = eventLabel;
                    return this;
                },
                withRaceNumber: function (raceNumber) {
                    event.raceNumber = 'R' + raceNumber;
                    return this;
                },
                withTrackName: function (trackName) {
                    event.trackName = trackName;
                    return this;
                },
                withBetName: function(betName) {
                    event.betName = betName;
                    return this;
                },
                withBetAmount: function(betAmount) {
                    event.betAmount = betAmount;
                    return this;
                },
                withBetType: function(betType) {
                    event.betType = betType;
                    return this;
                },
                withRunnerSelectionList: function(runnerSelectionList) {
                    event.runnerSelectionList = runnerSelectionList;
                    return this;
                },
                build: function () {
                    return event;
                }
            };
        }

        function _gaEventBuilder() {
            var gaData = {};
            return {
                withGaEventAction: function (gaEventAction) {
                    gaData.action = gaEventAction;
                    return this;
                },
                withGaEventCategory: function (gaEventCategory) {
                    gaData.category = gaEventCategory;
                    return this;
                },
                withGaEventLabel: function (gaEventLabel) {
                    gaData.gaLabel = gaEventLabel;
                    return this;
                },
                withEventLabel: function (eventLabel) {
                    gaData.label = eventLabel;
                    return this;
                },
                build: function () {
                    return gaData;
                }
            };
        }

        /**
         *
         * @param {type} s scope or rootScope param
         * @param {type} en event name
         * @returns {object} defaulParams
         */
        function _baseParams(s, en) {
            var eventParams = {};
            eventParams.customerStatus = $rootScope.hasInitialDeposit;
            eventParams.event = en;
            eventParams.sport = $location.search().greyhounds ? 'Greyhounds Racing' : 'Horse Racing';
            eventParams.accountId = s.userSession && s.user ? s.user.accountNumber : '';
            eventParams.residenceState = s.userSession && s.user && s.user.homeAddress ? s.user.homeAddress.StateAbbr : '';
            eventParams.loginStatus = s.userSession ? 'Logged In' : 'Logged Out';
            eventParams.registrationStatus = s.userSession ? 'Registered' : 'Unregistered';
            eventParams.screenName = _tvg4ScreenName();
            eventParams.sectionName = _tvg4SectionName();
            eventParams.siteVersion = 'TVG4';
            if (eventParams.screenName === 'Race') {
                eventParams.screenName = 'Races';
            }
            return eventParams;
        }
        function sendGTMEvent(scope, _eventName, aditionalParams, sendEvent) {
            sendEvent = typeof sendEvent !== 'undefined' ? sendEvent : true;

            if ($rootScope.enableGTM && sendEvent) {
                var finalParams = _baseParams(scope, _eventName);
                if (typeof aditionalParams === 'object') {
                    finalParams = angular.extend(finalParams, aditionalParams);
                }

                if (window.parent.dataLayer) {
                    window.parent.dataLayer.push(finalParams);
                }
                return finalParams;
            } else {
                return '';
            }
        }

        function _isTVG4() {
            return $rootScope.layout === 'desktop';
        }

        function _isTalentPick(currentAmount, currentSelectedBetTypeId) {
            var _pickBettype = $location.search().bettype;
            var _pickBetamount = $location.search().betamount;
            var _pickSelections = $location.search().betselections;
            var talentPicksListFormatted = '';

            if (talentPicksList && currentAmount && currentSelectedBetTypeId) {
                talentPicksList.forEach(function (entry) {
                    talentPicksListFormatted += entry + ';';
                });
                if (talentPicksListFormatted) {
                    talentPicksListFormatted = talentPicksListFormatted.substring(0, talentPicksListFormatted.length - 1);
                }
            }

            if (talentPicksListFormatted === _pickSelections && _pickBettype.toString() === currentSelectedBetTypeId.toString() && parseFloat(_pickBetamount).toFixed(2) === parseFloat(currentAmount).toFixed(2)) {
                return true;
            } else {
                return false;
            }
        }

        function _setCurrentSelectionList(val) {
            talentPicksList = val;
        }


        function _getScreenName(name) {
            switch (name) {
                case 'funds':
                    screenName = 'My Funds';
                    break;
                case 'wallet':
                  screenName = 'My Wallet';
                  break;
                case 'deposit':
                  screenName = 'Deposit';
                  break;
                case 'withdraw':
                  screenName = 'Withdraw';
                  break;
                case 'my-bets':
                    screenName = 'My Bets';
                    break;
                case 'my-account-summary':
                    screenName = 'My Account Summary';
                    break;
                case 'account':
                    screenName = 'My Account';
                    break;
                case 'handicapping-store':
                    screenName = 'Handicapping Store';
                    break;
                case 'free-pp':
                    screenName = 'Free Past Performances';
                    break;
                case 'talentpicks':
                    screenName = 'TVG Picks';
                    break;
                case 'my-tracks':
                    screenName = 'My Tracks';
                    break;
                case 'my-stable':
                    screenName = 'My Stable';
                    break;
                default:
                    screenName = name;
            }
            var screenName;
            return screenName;
        }

        function _tvg4SectionNameByURLSharp (name, params) {
            var parts = _URLParse(name),
                section = parts.pathname.replace('/', ''),
                hash = parts.hash.replace('#', ''),
                splitHash = hash.split('+'),
                translation = [section, 'translation'].join('.'),
                firstSection = _.isEmpty(splitHash[0]) ? '' : [section, splitHash[0]].join('.'),
                sectionName = _.get(SectionNames, translation),
                fullSectionName;

                if (splitHash.length > 1) {
                    var secondSection = [section, splitHash[1]].join('.');
                    fullSectionName = [sectionName, _.get(SectionNames, firstSection, ''), _.get(SectionNames, secondSection, '')].join(' | ');
                } else {
                    fullSectionName = _.isEmpty(firstSection) ? sectionName : [sectionName, _.get(SectionNames, firstSection, '')].join(' | ');
                }

            return _.isEmpty(params) ? fullSectionName : fullSectionName.concat(' | ').concat(params.sectionName);

        }

        function _URLParse(url) {
            var parser = document.createElement('a');
            parser.href = url;

            return {
                pathname: parser.pathname,
                hash: parser.hash
            };
        }

        function _tvg4SectionNameByURLToken (key, name, params) {
            var sectionName;

            if (_.isString(name) && !_.isEmpty(name) && SectionNames[key][name]) {
                sectionName = SectionNames[key].translation + ' | ' + SectionNames[key][name];
            } else {
                sectionName = SectionNames[key].translation;
            }

            if (!_.isEmpty(params) && !_.isEmpty(params.sectionName)) {
                sectionName += ' | ' + params.sectionName;
            }

            return sectionName;
        }

        function _tvg4SectionNameTrackName (key, params) {
            var sectionName = SectionNames[key].translation,
                track = params.trackName,
                raceNumber = params.raceNumber;

            if (_.isString(track) && !_.isEmpty(track) && METADATA.hasOwnProperty('allTracks')) {
                var trackName = _.isUndefined(METADATA.allTracks[track]) ? track : METADATA.allTracks[track].Name;
                if (typeof raceNumber === 'string') {
                    raceNumber = raceNumber.replace('race-','');
                }
                sectionName += ' | ' + trackName + ' | R' + raceNumber;
            }

            if (!_.isEmpty(params) && !_.isEmpty(params.sectionName)) {
                sectionName += ' | ' + params.sectionName;
            }

            return sectionName;
        }

        function _tvg4SectionNameOnlyParams (key, params) {
            var sectionName = SectionNames[key].translation;

            if (_.isUndefined(params) || _.isEmpty(params)) {
                sectionName += ' | ' + SectionNames[key].default;
            } else {
                sectionName += ' | ' + params.sectionName;
            }

            return sectionName;
        }

        function _getURLForRetroCompatibleGTM() {
            var url = $location.url();

            if (url.indexOf('my-funds/deposit') > -1) {
                return '/my-profile#funds+deposit';
            }
            else if (url.indexOf('my-funds/bank') > -1) {
                return '/my-profile#funds+bank';
            }
            else if (url.indexOf('my-funds/withdraw') > -1) {
                return '/my-profile#funds+withdraw';
            }

            return url;
        }

        function _tvg4SectionName (params) {
            var url = _getURLForRetroCompatibleGTM().split('/');
            var urlToken = (url[1].indexOf('?') > -1) ? url[1].split('?')[0] : url[1];

            if (urlToken.indexOf('#') > -1) {
                // TODO add this to the config object

                if (urlToken.indexOf('favorites') > -1 && _.isEmpty(params)) {
                    params = {
                        sectionName: 'All Tracks'
                    };
                }

                return _tvg4SectionNameByURLSharp(urlToken, params);
            }
            else {
                 var defaultParam;
                 var name;
                 switch (urlToken) {
                     case 'racetracks':
                         defaultParam = angular.extend({}, params,
                             RaceUrlFac.getRouteParamsForRaceBasedOnLocationPath());
                         return _tvg4SectionNameTrackName('programpage', defaultParam);
                     case 'forgot-credentials':
                         return _tvg4SectionNameByURLToken('forgot-credentials', null, params);
                     case 'reset-credentials':
                         return _tvg4SectionNameByURLToken('reset-credentials', null, params);
                     case 'password-recovery':
                         return _tvg4SectionNameByURLToken('password-recovery', null, params);
                    case 'registration':
                        return _tvg4SectionNameByURLToken('registration', null, params);
                     case 'info':
                         return _tvg4SectionNameByURLToken('siteinfo', url[2], params);
                     case 'races':
                         defaultParam = {
                             sectionName: 'By Time'
                         };
                         return _tvg4SectionNameByURLToken('horseracing', urlToken, _.isUndefined(params) || _.isEmpty(params) ? defaultParam : params);
                     case 'results':
                         defaultParam = {
                             sectionName: 'By Time'
                         };
                         return _tvg4SectionNameByURLToken('horseracing', urlToken, _.isUndefined(params) || _.isEmpty(params) ? defaultParam : params);
                     case 'betslip':
                         return _tvg4SectionNameOnlyParams('betslip', params);
                     case '':
                         return _tvg4SectionNameByURLToken('home', null, params);
                     case 'my-profile':
                         return _tvg4SectionNameByURLToken('my-profile', 'profile', params);
                     case 'my-favorite-tracks':
                         return _tvg4SectionNameByURLToken('my-profile', 'my-favorite-tracks', params);
                     case 'my-stable':
                         return _tvg4SectionNameByURLToken('my-profile', 'my-stable', params);
                     case 'my-tracks':
                         return _tvg4SectionNameByURLToken('my-profile', 'my-tracks', params);
                     case 'my-funds':
                         return _tvg4SectionNameByURLToken('my-profile', 'funds', params);
                     case 'my-bets':
                         return _tvg4SectionNameByURLToken('my-profile', 'my-bets', params);
                     case 'my-account-summary':
                         return _tvg4SectionNameByURLToken('my-profile', 'my-account-summary', params);
                     case 'handicapping':
                         name = url[2] || null;
                         return _tvg4SectionNameByURLToken('handicapping', name, params);
                     case 'promotions':
                         name = url[2] || null;
                         return _tvg4SectionNameByURLToken('promotions', name, params);
                    case 'horse-race-track-list':
                            defaultParam = {
                             sectionName: url[2]
                            };
                          return _tvg4SectionNameByURLToken('horse-race-track-list', 'track-list' , defaultParam);
                     default:
                         return '';
                }
            }
        }

        function _tvg4SectionNameForMyTracks(type) {
            return _tvg4SectionName() + _getMyTracksFilterForGtm(type);
        }

        function _getMyTracksFilterForGtm(type) {

            switch (type) {
                case "today":
                    return " | Today Tracks";
                case "favorites":
                    return " | Favorite Tracks";
                default:
                    return " | All Tracks";
            }
        }

        function _tvg4ScreenName () {
            var url = $location.path().split('/'),
                urlToken = url[1],
                screenName = ScreenNames[urlToken];

            if (_.isUndefined(screenName)) {
                return '';
            }

            return screenName;
        }

        return {
            GTMEvent: _GTMEvent,
            formatGALAbelUpperCase: _formatGALAbelUpperCase,
            GAPageviews: _GAPageviews,
            isTVG4: _isTVG4,
            getScreenName: _getScreenName,
            isTalentPick: _isTalentPick,
            setCurrentSelectionList: _setCurrentSelectionList,
            EventBuilder: _EventBuilder,
            Tvg4SectionName: _tvg4SectionName,
            Tvg4ScreenName: _tvg4ScreenName,
            tvg4SectionNameForMyTracks: _tvg4SectionNameForMyTracks,
            gaEventBuilder: _gaEventBuilder,
            genericEvent: _genericEvent,
            getURLForRetroCompatibleGTM: _getURLForRetroCompatibleGTM
        };
    }

    GTMFac.$inject = [
        '$location',
        '$rootScope',
        '$routeParams',
        'ScreenNames',
        'SectionNames',
        'METADATA',
        'RaceUrlFac'
    ];

    return GTMFac;
});

modules/GTM/constants/screenNames.js
'use strict';

define('ScreenNames',[],
    function () {
        return {
            'my-profile': 'My Account',
            'my-tracks': 'My Account',
            'my-favorite-tracks': 'My Account',
            'my-funds': 'My Account',
            'my-bets': 'My Account',
            'my-account-summary': 'My Account',
            'my-stable': 'My Account',
            'races': 'Races',
            'race': 'Program',
            'racetracks': 'Program',
            'handicapping': 'Handicapping',
            'info': 'Site Info',
            'home': 'Home',
            '': 'Home',
            'results': 'Races',
            'betslip': 'Bet Ticket',
            'promotions': 'Promotions',
            'registration': 'Registration Page',
            'password-recovery': 'Credentials Recovery',
            'forgot-credentials': 'Credentials Recovery',
            'reset-credentials': 'Credentials Recovery',
            'horse-race-track-list': 'Track List'
        };
    }
);

modules/GTM/constants/sectionNames.js
'use strict';

define('SectionNames',[],
    function () {
        return {
            'my-profile':
            {
                'translation': 'My Account',
                'my-tracks': 'My Tracks',
                'my-favorite-tracks': 'My Favorite Tracks',
                'funds': 'My Funds',
                'my-bets': 'My Bets',
                'my-account-summary': 'My Account Summary',
                'profile': 'My Profile',
                'deposit': 'Deposit',
                'bank': 'Payment Management',
                'withdraw': 'Withdraw',
                'my-stable': 'My Stable'
            },
            handicapping: {
                'translation': 'Handicapping',
                'handicapping-store': 'Handicapping Store',
                'free-pp': 'Free Past Performances',
                'talentpicks': 'Talent Picks',
                'racereplays': 'Race Replays',
                'talent-picks': 'Talent Picks',
                'race-replays': 'Race Replays'
            },
            promotions: {
                translation: 'Promotions',
                'wager-rewards': 'Wager Rewards'
            },
            horseracing: {
                translation: 'Races',
                races: 'Full Schedule',
                results: 'Results'
            },
            home: {
                translation: 'Home | Home Page'
            },
            programpage: {
                translation: 'Program Page'
            },
            siteinfo: {
                translation: 'Site Info',
                privacypolicy: 'Privacy Policy',
                wagerresponsibly: 'Wager Responsibly',
                termsandconditions: 'Terms and Conditions'
            },
            betslip: {
                translation: 'Bet Ticket',
                default: 'Bet Ticket Page'
            },
            'password-recovery': {
                translation: 'Info'
            },
            'registration': {
                translation: 'Registration | Single Step'
            },
            'reset-credentials': {
                translation: 'Credentials Recovery | Credentials Setup'
            },
            'forgot-credentials': {
                translation: 'Credentials Recovery | Start'
            },
            'horse-race-track-list': {
                translation: 'Track List | Track List Page'
            }
        };
    }
);
modules/RaceInfo/providers/raceInfoFac.js
'use strict';

define('RaceInfoFac',[
        'lodash'
    ],
    function (_) {
        function RaceInfoFac() {
            var _lowestOdd = Number.MAX_VALUE;

            function _setLowestOdd(arr) {
                _lowestOdd = Number.MAX_VALUE;
                var myOdd = Number.MAX_VALUE;

                //filter scratched horses for odd calculation
                var newArr = arr.length ? arr.filter(function (bettingInterest) {
                        var available = false;
                        var runners = bettingInterest.runners || bettingInterest.Runners;
                        _.each(runners, function (runner) {
                            var scratched = runner.scratched || runner.Scratched;
                            if (!scratched) {
                                available = true;
                            }
                        });
                        return available;
                    }) : [];

                for (var i = 0; i < newArr.length; i++) {

                    myOdd = _getDecimalOddsValue(newArr[i].CurrentOdds || newArr[i].currentOdds);

                    if (myOdd < _lowestOdd) {
                        _lowestOdd = myOdd;
                    }

                }
            }

            function _isFavoriteBIScratched(bettingInterests) {
                var isFavoriteBIScratched = false;

                bettingInterests.forEach(function (bettingInterest) {
                    var runners = bettingInterest.runners || bettingInterest.Runners || [bettingInterest];
                    
                    _.each(runners, function (runner) {
                        var scratched = runner.scratched || runner.Scratched;
    
                        if (bettingInterest.favorite && scratched) {
                            isFavoriteBIScratched = true;
                            return isFavoriteBIScratched;
                        }
                    });
                });
                return isFavoriteBIScratched;
            }

            function _isFavoriteOdd(bettingInterest) {
                return _lowestOdd === _getDecimalOddsValue(bettingInterest.currentOdds) && _lowestOdd !== 99;
            }

            function _getLowestOdd() {
                return _lowestOdd;
            }

            function _getDecimalOddsValue(obj) {
                if (obj) {
                    var denominator = obj.denominator;
                    var numerator = obj.numerator;
                    var decimal = denominator ? numerator / denominator : numerator;

                    if (isNaN(decimal)) {
                        return Number.MAX_VALUE;
                    }
                    return parseFloat(decimal);
                }
                else {
                    return Number.MAX_VALUE;
                }
            }


            return {
                setLowestOdd: _setLowestOdd,
                getLowestOdd: _getLowestOdd,
                isFavoriteOdd: _isFavoriteOdd,
                isFavoriteBIScratched: _isFavoriteBIScratched
            };
        }

        RaceInfoFac.$inject = [];

        return RaceInfoFac;

    });

modules/RaceInfo/entities/raceParamsEntity.js
"use strict";

define('RaceParamsEntity',[],function () {

    function RaceParams(trackAbbr, perfAbbr, raceNumber, raceId){

        this.trackAbbr = trackAbbr;
        this.perfAbbr = perfAbbr;
        this.raceNumber = raceNumber;
        this.raceId = raceId;
    }

    return RaceParams;

});


modules/RaceInfo/builders/raceParamsEntityBuilder.js
"use strict";

define('RaceParamsEntityBuilder',['RaceParamsEntity'], function (RaceParamsEntity) {

    function builder(){
        var raceParams = new RaceParamsEntity();

        return {
            withRaceId: function (raceId) {
                raceParams.raceId = raceId;
                return this;
            },
            withTrackAbbr: function (trackAbbr) {
                raceParams.trackAbbr = trackAbbr;
                return this;
            },
            withPerfAbbr: function (perfAbbr) {
                raceParams.perfAbbr = perfAbbr;
                return this;
            },
            withRaceNumber: function (raceNumber) {
                raceParams.raceNumber = raceNumber;
                return this;
            },
            build: function () {
                return raceParams;
            }
        };
    }

    return builder;

});


modules/RaceInfo/providers/raceUrlFac.js
"use strict";

define('RaceUrlFac',['RaceParamsEntityBuilder', 'lodash'],function(RaceParamsEntityBuilder, _){

    /*
    * This fac will be use to handle races url decode and encode
    * */
    function RaceUrlFac($location, $routeParams, METADATA, racePerformances){

        function _searchMetadataTrackByName(trackName) {
            var track = _.find(METADATA.allTracks, function(track) {
                return trackName.toLowerCase() === track.Name.trim().toLowerCase();
            });
            return track;
        }

        function _searchPerformanceByPerformanceName(performance) {
            var perf = _.find(racePerformances, function(racePerformance){
                return racePerformance.fullPerf.toLowerCase() === performance.toLowerCase();
            });
            return perf;
        }

        function _searchMetadataTrackByAbbr(trackAbbr) {
            var track = _.find(METADATA.allTracks, function(track) {
                return trackAbbr.toLowerCase() === track.Abbreviation.toLowerCase();
            });
            return track;
        }

        function _searchPerformanceByPerfAbbr(perfAbbr) {
            var perf = _.find(racePerformances, function(racePerformance){
                return racePerformance.perfAbbr.toLowerCase() === perfAbbr.toLowerCase();
            });
            return perf;
        }

        /*
            this function will look to route params to calculate trackAbbr, perfAbbr, and raceNumber
         */
        function _getRacesInfoFromRouteParams() {
            var trackName = $routeParams.trackName || '';
            var trackPerformance = $routeParams.trackPerformance || '';
            var raceNumber = $routeParams.raceNumber || '';
            var track, trackPerf, raceId;

            //remove the race
            if (typeof raceNumber === "string") {
                raceNumber = raceNumber.replace('race-',"");
            }


            if (trackName){
                trackName = trackName.split('-').join(' ');
                track = _searchMetadataTrackByName(trackName);
            }

            trackPerf = _searchPerformanceByPerformanceName(trackPerformance);

            if (_.isUndefined(track) || _.isUndefined(trackPerf)){
                raceId = _buildRaceId($routeParams.trackName, $routeParams.trackPerformance, raceNumber);
                return RaceParamsEntityBuilder()
                    .withTrackAbbr(trackName)
                    .withPerfAbbr(trackPerformance)
                    .withRaceNumber(raceNumber)
                    .withRaceId(raceId)
                    .build();
            }

            raceId = _buildRaceId(track.Abbreviation, trackPerf.perfAbbr, raceNumber);

            return RaceParamsEntityBuilder().withTrackAbbr(track.Abbreviation)
                                            .withPerfAbbr(trackPerf.perfAbbr)
                                            .withRaceNumber(raceNumber)
                                            .withRaceId(raceId)
                                            .build();
        }

        /**
         * This function uses the '$location.path' function instead of the '$routeParams' service
         * to get the new URL parameters' values.
         * This is useful when we want to get these values before a route change occurs,
         * '$routeChangeStart' and '$routeChangeSuccess' events.
         *
         * @returns {Object} route params that match the 'racetracks' route.
         */
        function _getRouteParamsForRaceBasedOnLocationPath() {
            var routeParams = {};
            var currentPathArray = $location.path().split('/');

            routeParams.country = currentPathArray[2];
            routeParams.trackName = currentPathArray[3];
            routeParams.trackPerformance = currentPathArray[4];
            routeParams.raceNumber = currentPathArray[5];
            routeParams.autoplay = currentPathArray[7];

            return routeParams;
        }

        function _buildRaceId(trackName, trackPerformance, raceNumber) {
            if (trackName && trackPerformance && raceNumber ) {
                return trackName + '_' + trackPerformance + '_' + raceNumber;
            }
            return '';
        }

        function _getRouteParamsForRace(trackAbbr, perfAbbr, raceNumber, autoplay) {
            var track = trackAbbr ? _searchMetadataTrackByAbbr(trackAbbr) : undefined;
            var perf = perfAbbr ? _searchPerformanceByPerfAbbr(perfAbbr) : undefined;
            var race = raceNumber;
            var trackName;

            if (_.isUndefined(track) || _.isUndefined(perf) || _.isUndefined(race)){
                return {
                    autoplay: autoplay ? autoplay.toString() : undefined,
                    trackName: trackAbbr,
                    trackPerformance: perfAbbr,
                    country: 'unknown',
                    raceNumber: raceNumber
                };
            } else {
                trackName = track.Name.trim().replace(/\s/g,"-").toLowerCase();
                return {
                    autoplay: autoplay ? autoplay.toString() : undefined,
                    trackName: trackName,
                    trackPerformance: perf.fullPerf,
                    country: track.CountryName,
                    raceNumber: race
                };
            }
        }

        function _calculateRacePath(trackAbbr, perfAbbr, raceNumber, autoplay) {
            var routeParams = _getRouteParamsForRace(trackAbbr, perfAbbr, raceNumber, autoplay);
            if (routeParams.trackName && routeParams.trackPerformance && routeParams.raceNumber) {
                return ("/racetracks/" + routeParams.country +
                    "/" + routeParams.trackName +
                    "/" + routeParams.trackPerformance +
                    "/race-" + routeParams.raceNumber).concat(autoplay ? '/autoplay/' + autoplay.toString() : '');
            }
            return "/racetracks/unknown/unknown/unknown/unknown";
        }

        function _generateRacePath(trackName, raceNumber, countryName, autoplay) {
            trackName = trackName.trim().replace(/\s/g,"-").toLowerCase();

            if (trackName && raceNumber && countryName) {
                return ("/racetracks/" + ( countryName ? countryName : 'unknown' ) +
                    "/" + trackName +
                    "/race-" + raceNumber).concat(autoplay ? '/autoplay/' + autoplay.toString() : '');
            }
            return "/racetracks/unknown/unknown/unknown/unknown";
        }

        return {
            getRouteParamsForRace: _getRouteParamsForRace,
            getRouteParamsForRaceBasedOnLocationPath: _getRouteParamsForRaceBasedOnLocationPath,
            getRacesInfoFromRouteParams: _getRacesInfoFromRouteParams,
            calculateRacePath: _calculateRacePath,
            generateRacePath: _generateRacePath
        };
    }

    RaceUrlFac.$inject = [
        '$location',
        '$routeParams',
        'METADATA',
        'racePerformances'
    ];

    return RaceUrlFac;

});

modules/RaceInfo/filters/raceLinkFilter.js
'use strict';

define('RaceLinkFilter',[],
    function () {
        function RaceLinkFilter(RaceUrlFac) {
            return function(race) {
                return RaceUrlFac.calculateRacePath(race.trackAbbr, race.perfAbbr, race.raceNumber);
            };
        }

        RaceLinkFilter.$inject = [
            'RaceUrlFac'
        ];

        return RaceLinkFilter;
    }
);

modules/RaceInfo/providers/raceMtpStatusFac.js
'use strict';

define(
    'RaceMtpStatusFac',['lodash'],
    function (_) {
    /**
     * This factory starts a polling to know every race's MTP that is under 120 MTP (2 hours)
     * and will broadcast an event to the entire application when detecting changes.
     * All MTPs across the platform must come from here.
     *
     * @param GraphRacesMtpStatus
     * @param $rootScope
     * @param CookieFac
     * @param $log
     * @returns {{getRaceMtpStatus: getRaceMtpStatus}}
     * @constructor
     */
    function RaceMtpStatusFac(GraphRacesMtpStatus, $rootScope, CookieFac, $log, $filter) {
        var graphqlEnabled = $rootScope.activeFeatures.graphqlEnabled;
        var globalMtpFeature = graphqlEnabled && $rootScope.activeFeatures.globalMtpRefreshSystem;
        var mtpStatusRegistry = {};

        var subscriptionTimer = $filter('CMSLabels')('low', 'graphqlPollingRates') || 30000; // in ms

        function _getWagerProfile() {
            return CookieFac.getCookie('wp') && $rootScope.userSession ? CookieFac.getCookie('wp') : 'PORT-Generic';
        }

        function _onSuccess(result) {
            _.forEach(mtpStatusRegistry, function (race) {
                race.raceStatus = 'RO';
            });

            _.forEach(result, function (race) {
                mtpStatusRegistry[race.raceId] = race;
            });

            $rootScope.$broadcast('mtpStatusUpdated');
        }

        function _subscribe() {
            GraphRacesMtpStatus.subscribe(
                { wagerProfile: _getWagerProfile() },
                { success: _onSuccess, fail: _onError },
                subscriptionTimer,
                true
            );
        }

        function _refreshData() {
            GraphRacesMtpStatus.refetch({ wagerProfile: _getWagerProfile() });
        }

        function _onError() {
            $log.error('Error getting the MTP status via GraphQL');
        }

        (function () {
            // TODO: remove globalMtpRefreshSystem toggle validation from here once is 100% on
            if (globalMtpFeature) {

                // Subscription has to be made after session validation to prevent duplicate requests
                var unbindOnSession = $rootScope.$on('session', function () {
                    _subscribe();
                    unbindOnSession();
                });


                $rootScope.$on('login', function() {
                    _refreshData();
                });

               $rootScope.$on('userLogout', function () {
                    _refreshData();
                });
            }
        }());

        return {
            getRaceMtpStatus: function (raceId) {
                return mtpStatusRegistry[raceId] || {};
            },
            getClosestRaceToBet: function() {
                return _.find(mtpStatusRegistry, function (race) {
                    var code = (race.raceStatus.code || '').toLowerCase();
                    return code === 'ic' || code === 'o' || code === 'mo';
                });
            }
        };
    }

    RaceMtpStatusFac.$inject = [
        'GraphRacesMtpStatus',
        '$rootScope',
        'CookieFac',
        '$log',
        '$filter'
    ];

    return RaceMtpStatusFac;

});

modules/RaceInfo/raceInfoMod.js
'use strict';

define('RaceInfo',[
    'RaceInfoFac',
    'RaceUrlFac',
    'RaceLinkFilter',
    'RaceMtpStatusFac'
], function (RaceInfoFac, RaceUrlFac, RaceLinkFilter, RaceMtpStatusFac) {

    return angular
        .module('TVG.RaceInfo', [])
        .factory('RaceInfoFac', RaceInfoFac)
        .factory('RaceUrlFac', RaceUrlFac)
        .factory('RaceMtpStatusFac', RaceMtpStatusFac)
        .filter('raceLink', RaceLinkFilter)
        .constant('racePerformances', [
            {perfAbbr:'Adv', fullPerf:'Advance'},
            {perfAbbr:'Day', fullPerf:'Day'},
            {perfAbbr:'Eve', fullPerf:'Evening'},
            {perfAbbr:'Fut', fullPerf:'Future'},
            {perfAbbr:'Mat', fullPerf:'Matinee'},
            {perfAbbr:'Ngt', fullPerf:'Night'},
            {perfAbbr:'Twi', fullPerf:'Twilight'}
        ])
        .name;
    }
);

modules/GTM/gtmMod.js
'use strict';

define('GTMMod',[
    'angular',
    'angularRoute',
    'GTMFac',
    'ScreenNames',
    'SectionNames',
    'TVGCommon',
    'RaceInfo'
], function (
    angular,
    ngRoute,
    GTMFac,
    ScreenNames,
    SectionNames,
    TVGCommon,
    RaceInfo
) {
    return angular
        .module('TVG.Common.GTM', ['ngRoute', TVGCommon.default, RaceInfo])
        .factory('GTMFac', GTMFac)
        .constant('ScreenNames', ScreenNames)
        .constant('SectionNames', SectionNames)
        .name;
});

modules/AppCore/appCoreMod.js
'use strict';

define('AppCore',[
        'AppRootFac',
        'AppRequestInterceptor',
        'GTMMod'
    ],
    function (AppRootFac,
              AppRequestInterceptor
    ) {

        return angular.module('TVG.AppCore', [
            'TVG.Common.GTM',
            'TVG.Utilities'
        ])
            .factory('AppRootFac', AppRootFac)
            .provider('AppRequestInterceptor', AppRequestInterceptor)
            .name;
    }
);

modules/Layout/directives/layout-directive.js
'use strict';

define('LayoutDir',[],function () {
    function layoutDir($window, $location, $rootScope, $route, $timeout, $routeParams, GTMFac, LayoutFac, METADATA) {
        return {
            restrict: 'E',
            link: function (scope, elem) {

                var layout = "desktop",
                    subLayout = null,
                    body = angular.element(document.getElementById('angular-app'));

                scope.routeParams = $routeParams;
                scope.currentPage = $location.path().split('/')[1];


                scope.GTMEvents = function (section) {
                    var p = {};
                    p.gaEventCategory = 'Site Click';
                    p.gaEventAction = GTMFac.Tvg4ScreenName() + ' Page Click';
                    p.screenName = GTMFac.Tvg4ScreenName();

                    if (GTMFac.isTVG4()) {
                        p.sectionName = GTMFac.Tvg4SectionName();
                    }

                    if($routeParams.trackAbbr && $routeParams.raceNumber && METADATA.hasOwnProperty('allTracks') && METADATA.allTracks.hasOwnProperty($routeParams.trackAbbr) && METADATA.allTracks[$routeParams.trackAbbr].Name) {
                        p.trackName = METADATA.allTracks[$routeParams.trackAbbr].Name;
                        p.raceNumber = "R" + $routeParams.raceNumber;
                    }

                    GTMFac.GTMEvent().send($rootScope, 'siteClick', p);
                };

                scope.onResize = function () {
                    var calculatedLayout = LayoutFac.calculateLayout(scope.currentPage);
                    layout = calculatedLayout.layout;
                    subLayout = calculatedLayout.subLayout;

                    if (layout != scope.layout) {
                        body.addClass(layout);
                        scope.layout = layout;
                        scope.subLayout = subLayout;
                        $rootScope.layout = layout;
                        $rootScope.subLayout = subLayout;
                        if ($rootScope.raceInfoModal) {
                            $rootScope.raceInfoModal.close();
                            $rootScope.raceInfoModal = null;
                        }
                        _applyChanges();
                    } else if (subLayout != scope.subLayout) {
                        scope.subLayout = subLayout;
                        _applyChanges();
                    }


                    if ($window.CSS_LOADED === true) {
                        /*
                         Time to apply CSS
                         The app is already loading the modules in the background
                         because the $rootScope.layout is already defined
                         */
                        setTimeout(function () {
                            body.removeClass("loading");
                            body.removeClass("menu-expanded");
                            elem.removeClass("hidden");
                            $rootScope.apploaded = true;
                        }, 150);
                    } else {
                        scope.$watch(
                            function () {
                                return $window.CSS_LOADED;
                            }, function (currentValue) {
                                /*
                                 Time to apply CSS
                                 The app is already loading the modules in the background
                                 because the $rootScope.layout is already defined
                                 */
                                if (currentValue) {
                                    setTimeout(function () {
                                        body.removeClass("loading");
                                        body.removeClass("menu-expanded");
                                        elem.removeClass("hidden");
                                        $rootScope.apploaded = true;
                                    }, 150);
                                }
                            }
                        );
                    }
                };

                //CMS data is present when we boot the app
                scope.onResize();

                scope.goToHomePage = function () {
                    $location.path("/");
                };

                function _applyChanges() {
                    if (!_.isUndefined($rootScope.$$phase) &&
                        $rootScope.$$phase !== '$apply' &&
                        $rootScope.$$phase !== '$digest') {

                        scope.$apply();
                    }
                }
            }
        };
    }

    layoutDir.$inject = [
        '$window',
        '$location',
        '$rootScope',
        '$route',
        '$timeout',
        '$routeParams',
        'GTMFac',
        'LayoutFac',
        'METADATA'
    ];

    return layoutDir;
});

modules/Layout/directives/switch-layout-for-directive.js
'use strict';

define('SwitchLayoutForDir',[],function () {

    function SwitchLayoutForDir(LayoutFac) {
        return {
            restrict: 'A',
            scope: {
                layout: '@switchLayoutFor'
            },
            link: function (scope, elem) {

                function _onElemClick() {

                    if (!scope.layout) {
                        return;
                    }

                    switch (scope.layout.toLowerCase()) {
                        case "mobile":
                            LayoutFac.goToMobile();
                            window.location.reload();
                            break;

                        case "desktop":
                            LayoutFac.goToDesktop();
                            window.location.reload();
                            break;
                    }
                }

                elem.on("click", _onElemClick);
            }
        };
    }

    SwitchLayoutForDir.$inject = [
        "LayoutFac"
    ];

    return SwitchLayoutForDir;
});

modules/Layout/providers/factories/layoutFac.js
'use strict';

define(
    'LayoutFac',[],function () {
        function LayoutFac($rootScope, $window, $location, CookieFac) {

            var cookieName = 'layout';


            function _goToDesktop() {
                _setLayoutName('desktop');
                $location.url('/');
            }

            function _goToMobile() {
                _setLayoutName('mobile');
                $location.url('/');
            }

            function _setLayoutName(layoutName) {
                CookieFac.setCookie(cookieName, layoutName);
            }

            function isWindow(currentPage) {
                switch (currentPage) {
                    case "betslip":
                        return true;
                    default:
                        return false;
                }
            }

            function isDesktop() {
                return __LAYOUT === 'desktop';
            }

            function isPhone() {
                return __LAYOUT === 'mobile' && $window.innerWidth < 800;
            }

            function isPhoneLarge() {
                return __LAYOUT === 'mobile' && $window.innerWidth > 500;
            }

            function isTabletLarge() {
                return __LAYOUT === 'mobile' && $window.innerWidth > 1280;
            }

            function _calculateLayout(currentPage) {
                var layout = {};

                if (isDesktop()) {
                    layout.layout = "desktop";
                    if (isWindow(currentPage)) {
                        layout.subLayout = "window";
                    }
                } else if (isPhone()) {
                    layout.layout = "phone";
                    if (isPhoneLarge()) {
                        layout.subLayout = "large";
                    } else {
                        layout.subLayout = "small";
                    }
                } else {
                    layout.layout = "tablet";
                    if (isTabletLarge()) {
                        layout.subLayout = "large";
                    }
                }

                return layout;
            }

            return {
                calculateLayout: _calculateLayout,
                setLayoutName: _setLayoutName,
                goToMobile: _goToMobile,
                goToDesktop: _goToDesktop
            };
        }

        LayoutFac.$inject = [
            '$rootScope',
            '$window',
            '$location',
            'CookieFac'
        ];

        return LayoutFac;
    });

modules/Layout/layoutMod.js
'use strict';

define('Layout',[
        'LayoutDir',
        'SwitchLayoutForDir',
        'LayoutFac',
        'GTMMod'
    ],
    function (LayoutDir,
              SwitchLayoutForDir,
              LayoutFac) {

        angular.module('TVG.Layout', [
            'TVG.Common.GTM'
        ])

            .factory('LayoutFac', LayoutFac)

            .directive('layout', LayoutDir)
            .directive('switchLayoutFor', SwitchLayoutForDir);
    }
);

modules/Utilities/formatters/dateTimeFormatters.js
'use strict';

define('DateTimeFormatters',[],
    function () {
        /***
         * Get relative string day between given date and current date
         * @param raceDate
         * @returns {string}
         *                      - "ystrd" When Yesterday;
         *                      - "today" When Today;
         *                      - "tmrrw" When Tomorrow;
         *                      - "" Fallback;
         * @private
         */
        function _getRelativeDayBasedOnGivenDate(raceDate, todayDate) {
            var raceDateDay = new Date(raceDate.getFullYear(), raceDate.getMonth(), raceDate.getDate()),
                todayWithoutHours = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate()),
                tomorrow = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate() + 1),
                yesterday = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate() - 1),
                relativeDay = "";

            if (raceDateDay.getTime() === todayWithoutHours.getTime()) {
                relativeDay = "today";
            } else if (raceDateDay.getTime() === yesterday.getTime()) {
                relativeDay = "ystrd";
            } else if (raceDateDay.getTime() === tomorrow.getTime()) {
                relativeDay = "tmrrw";
            }

            return relativeDay;
        }

        return {
            getRelativeDayBasedOnGivenDate: _getRelativeDayBasedOnGivenDate
        };
    });
modules/RaceInfo/filters/raceMTP.js
"use strict";

define('RaceMTP',[
    'moment',
    'DateTimeFormatters',
    'lodash'
], function (moment, DateTimeFormatters, _) {

    function RaceMTP(racePostTime) {
        if (angular.isDate(racePostTime)) {
            this.racePostTime = racePostTime;
        } else {
            this.racePostTime = new Date(racePostTime);
        }
    }

    RaceMTP.prototype.mtpDateFormats = {
        WITH_PM_AM_AND_TIME_DAY: 1,
        WITH_PM_AM: 2
    };

    RaceMTP.prototype.getMTPDate = function (mtp) {
        var output = {
            mtp: undefined,
            date: undefined,
            timeWithDay: undefined
        };

        if (moment(this.racePostTime).isValid()) {
            if (!_.isUndefined(mtp)) {
                output.mtp = mtp;
            } else {
                var millisecondsCurrentTime = new Date().getTime();
                var millisecondsToRaceStart = this.racePostTime.getTime() - millisecondsCurrentTime;
                var minutesToRaceStart = millisecondsToRaceStart / 1000 / 60;

                if (minutesToRaceStart >= 0 && minutesToRaceStart <= 60) {
                    output.mtp = Math.round(minutesToRaceStart);
                } else if (minutesToRaceStart < 0) {
                    output.mtp = 0;
                } else {
                    // minutesToRaceStart >= 120
                    output.date = moment(this.racePostTime).format("hh:mm A");
                    output.timeWithDay = {
                        time: moment(this.racePostTime).format("hh:mm"),
                        amPmMarker: moment(this.racePostTime).format("A"),
                        day: DateTimeFormatters.getRelativeDayBasedOnGivenDate(this.racePostTime, new Date())
                    };
                }
            }
        }

        return output;
    };

    RaceMTP.prototype.getDisplayableTime = function () {
        var mtpDate = this.getMTPDate();
        return angular.isDefined(mtpDate.mtp) ? mtpDate.mtp + " MTP" : mtpDate.date;
    };

    return RaceMTP;

});



modules/Races/filters/raceMTPFilter.js
'use strict';

define('RaceMTPFilter',[
        'RaceMTP'
    ],
    function (RaceMTP) {

        function RaceMTPFilter(input) {
            if (!angular.isDate(input)) {
                return input;
            }

            var raceMTP = new RaceMTP(input);
            return raceMTP.getDisplayableTime();
        }

        return function () {
            return RaceMTPFilter;
        };

    });

modules/Races/controllers/models/mtpDisplay.js
"use strict";

define(
    'MtpDisplayModel',[
        'RaceMTP'
    ],

    function (RaceMTP) {
        function MtpDisplay(date, mtp) {
            this.mtp = mtp;

            if (!angular.isDate(date)) {
                this.time = undefined;
            } else {
                this.time = new RaceMTP(date);
            }

            this.mtpStatus = this.getMtpStatus();
            this.timeText = this.toString();
        }

        MtpDisplay.prototype = {
            mtpStatusValues: ['near', 'med', 'far', 'time-format'],

            toString: function () {
                if (this.mtp) {
                    return this.mtp + ' MTP';
                } else {
                    if (this.time && this.time.getDisplayableTime) {
                        return this.time.getDisplayableTime();
                    }
                }

                return '';
            },

            getMtpStatus: function () {
                if (angular.isDefined(this.time) || angular.isDefined(this.mtp)) {
                    var mtpDate;

                    if (angular.isDefined(this.mtp)) {
                        mtpDate = { mtp: this.mtp };
                    } else if (this.time.getMTPDate) {
                        mtpDate = this.time.getMTPDate();
                    } else {
                        return MtpDisplay.prototype.mtpStatusValues[3];
                    }

                    if (mtpDate.mtp <= 5) {
                        return MtpDisplay.prototype.mtpStatusValues[0];
                    } else if (mtpDate.mtp <= 15) {
                        return MtpDisplay.prototype.mtpStatusValues[1];
                    } else if (mtpDate.mtp <= 60) {
                        return MtpDisplay.prototype.mtpStatusValues[2];
                    }
                }

                return MtpDisplay.prototype.mtpStatusValues[3];
            }
        };

        return MtpDisplay;

    });

modules/Utilities/tools/raceStatusUtils.js
"use strict";

define('RaceStatusUtils',['lodash'], function (_) {

    return {

        // from API code
        RACE_STATUS: {
            OPEN: 'O',             // Open
            STEWARDS_KEY: 'SK',    // Steward's Key
            RACE_OFFICIAL: 'RO',   // Race Official
            UP_NEXT: 'IC',         // Up Next
            MANUALLY_OPENED: 'MO', // Manually Opened
            MANUALLY_CLOSED: 'MC'  // Manually Closed
        },

        /**
         * Get the race status label to be rendered in the MTP label
         * @param  {String} raceStatus  Race status code
         * @return {String}             Label for race status
         */
        getRaceStatusLabel: function (raceStatus) {

            // stop
            if (!_.isString(raceStatus)) { return undefined; }

            var code = raceStatus.toUpperCase();
            var labels = {};


            labels[this.RACE_STATUS.OPEN] = 'Open';
            labels[this.RACE_STATUS.STEWARDS_KEY] = 'Race Off';
            labels[this.RACE_STATUS.RACE_OFFICIAL] = 'Result';
            labels[this.RACE_STATUS.MANUALLY_CLOSED] = 'Closed';

            return labels[code];
        },

        /**
         * Check if the race is open for betting, according to its race status
         *
         * @param  {Object}  race         Race
         * @param  {String}  race.status  Race status code
         * @return {Boolean}              Is it open?
         */
        isRaceOpenForBetting: function (race) {
            var status = this._getStatusCode(race);

            // cannot be closed
            if (this.isStatusRaceOfficial(status) ||
                this.isStatusManuallyClosed(status) ||
                this.isStatusStewardsKey(status)) {
                return false;
            }

            // it's not open if there are already runners
            if (this._hasRunners(race.results)) {
                return false;
            }

            return true;
        },

        /**
         * Check if the race has live video, according to its race status
         *
         * @param  {Object}  race         Race
         * @param  {String}  race.status  Race status code
         * @return {Boolean}              Is it open?
         */
        isRaceOpenForLiveVideo: function (race) {
            var status = this._getStatusCode(race);

            // cannot be closed
            if (this.isStatusRaceOfficial(status) ||
                this.isStatusManuallyClosed(status)) {
                return false;
            }

            // it's not open if there are already runners
            if (this._hasRunners(race.results)) {
                return false;
            }

            return true;
        },

        /**
         * Has the race been marked as open (status="O")?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is it manually closed?
         */
        isStatusOpen: function (raceStatus) {
            return this._normalizeCode(raceStatus) === this.RACE_STATUS.OPEN;
        },

        /**
         * Has the race been marked as stewards's key (status="SK")?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is it manually closed?
         */
        isStatusStewardsKey: function (raceStatus) {
            return this._normalizeCode(raceStatus) === this.RACE_STATUS.STEWARDS_KEY;
        },

        /**
         * Has the race been marked as official (status="RO")?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is it official?
         */
        isStatusRaceOfficial: function (raceStatus) {
            return this._normalizeCode(raceStatus) === this.RACE_STATUS.RACE_OFFICIAL;
        },

        /**
         * Has the race been marked as up next (status="IC")?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is it official?
         */
        isStatusUpNext: function (raceStatus) {
            return this._normalizeCode(raceStatus) === this.RACE_STATUS.UP_NEXT;
        },

        /**
         * Has the race been marked as manually opened (status="MO")?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is it manually closed?
         */
        isStatusManuallyOpened: function (raceStatus) {
            return this._normalizeCode(raceStatus) === this.RACE_STATUS.MANUALLY_OPENED;
        },

        /**
         * Has the race been marked as manually closed (status="MC")?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is it manually closed?
         */
        isStatusManuallyClosed: function (raceStatus) {
            return this._normalizeCode(raceStatus) === this.RACE_STATUS.MANUALLY_CLOSED;
        },

        /**
         * Does the race already has reuslts?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Does it have results?
         */
        hasRaceResults: function (raceStatus) {
            return this.isStatusRaceOfficial(raceStatus) ||
                this.isStatusManuallyClosed(raceStatus);
        },

        /**
         * Is the race closed for betting?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is it closed for betting?
         */
        isClosedForBetting: function (raceStatus) {
            return this.isStatusRaceOfficial(raceStatus) ||
                this.isStatusManuallyClosed(raceStatus) ||
                this.isStatusStewardsKey(raceStatus);
        },

        /**
         * Make sure race status code is a uppercased string
         * @param {String} raceStatus  Race status code
         * @return {String}            Uppercase status code
         */
        _normalizeCode: function (raceStatus) {
            return _.isString(raceStatus) ?
                raceStatus.toUpperCase() : '';
        },

        /**
         * Is one of the valid race status?
         *
         * @param  {String}  raceStatus  Race status code
         * @return {Boolean}             Is the status valid?
         */
        _isValidStatus: function (raceStatus) {

            // must be a string
            if (!_.isString(raceStatus)) { return false; }

            var status = this._getRaceStatusList();
            var code = raceStatus.toUpperCase();


            return status.indexOf(code) > -1;
        },

        /**
         * Get status code from race
         *
         * @param {Object} race  Race details
         * @return {String}      Status code
         */
        _getStatusCode: function (race) {
            race = race || {};

            var status = _.has(race, 'status.code') ?  race.status.code : race.status;

            // if the race status is not a valid one, something's phishy...
            if (!this._isValidStatus(status)) {
                throw new Error('Invalid race status code (' + status + ')');
            }

            return status;
        },

        /**
         * Are there runners in the results?
         * @param  {Object}  results  Race results
         * @return {Boolean}          Whether has runners
         */
        _hasRunners: function (results) {
            return _.has(results || {}, 'runners.length') &&
                results.runners.length > 0;
        },

        /**
         * Extract RACE_STATUS values to an array
         * @return {Array}  Race statuses array
         */
        _getRaceStatusList: function () {
            return Object.keys(this.RACE_STATUS).map(function (key) {
                    return this.RACE_STATUS[key];
                }.bind(this));
        }
    };

});

modules/Races/directives/race-status-label-directive.js
'use strict';

define('RaceStatusLabelDir',[
    'RaceStatusUtils'
], function (raceStatusUtils) {

    function RaceStatusLabelDir () {
        return {
            restrict: 'E',
            template:
                '<span class="info" ' +
                    'ng-show="shouldShowRaceStatusLabel()" ' +
                    'ng-class="raceStatus">' +
                    '<strong ' +
                        'ng-bind="raceStatusLabel" ' +
                        'qa-label="raceStatusLabel">' +
                    '</strong>' +
                '</span>',
            scope: {
                raceStatus: '=',
                raceShowOnlyForClosed: '='
            },
            link: function (scope) {

                scope.shouldShowRaceStatusLabel = function () {
                    var statesWithLabel = {};

                    statesWithLabel[raceStatusUtils.RACE_STATUS.RACE_OFFICIAL] = true;
                    statesWithLabel[raceStatusUtils.RACE_STATUS.STEWARDS_KEY] = true;
                    statesWithLabel[raceStatusUtils.RACE_STATUS.MANUALLY_CLOSED] = true;

                    return !scope.raceShowOnlyForClosed || statesWithLabel[scope.raceStatus];
                };

                function _setRaceStatusLabel(raceStatus) {
                    scope.raceStatusLabel = raceStatusUtils.getRaceStatusLabel(raceStatus);
                }

                (function init() {
                    _setRaceStatusLabel(scope.raceStatus);
                }());

                scope.$watch('raceStatus', _setRaceStatusLabel);
            }
        };
    }

    RaceStatusLabelDir.$inject = [];

    return RaceStatusLabelDir;

});

modules/Races/components/raceMtpLabel/directives/raceMtpLabelDir.js
"use strict";

define('RaceMtpLabelDir',[
    'RaceMTP'
], function (RaceMTP) {

    function RaceMtpLabelDir() {

        return {
            restrict: '',
            replace: false,
            scope: {
                racePostTime: "=",
                withTimeDay: "=",
                mtp: '='
            },
            templateUrl: 'js/modules/Races/components/raceMtpLabel/templates/race-mtp-label.html',
            link: function (scope) {
                scope.mtpFormat = {};
                scope.raceMtp = {};
                scope.mtpFormatsEnum = {
                    MTP: 1,
                    TIME: 2,
                    TIME_WITH_DAY: 3,
                    NONE: 4
                };

                scope.currentMtpFormat = scope.mtpFormatsEnum.NONE;

                function _getMtpFormat(mtpDate) {
                    if (angular.isDefined(mtpDate.mtp)) {
                        return scope.mtpFormatsEnum.MTP;
                    }
                    else if (scope.withTimeDay && angular.isDefined(mtpDate.timeWithDay)) {
                        return scope.mtpFormatsEnum.TIME_WITH_DAY;
                    }
                    else if (!scope.withTimeDay && angular.isDefined(mtpDate.date)) {
                        return scope.mtpFormatsEnum.TIME;
                    }
                    return scope.mtpFormatsEnum.NONE;
                }

                function _updateBindings() {
                    if (!scope.racePostTime) {
                        return;
                    }
                    var raceMTP = new RaceMTP(scope.racePostTime);

                    scope.raceMtp = raceMTP.getMTPDate(scope.mtp);
                    scope.currentMtpFormat = _getMtpFormat(scope.raceMtp);
                }

                (function init() {
                    _updateBindings();
                }());

                scope.$watch("racePostTime", _updateBindings);
                scope.$watch("mtp", _updateBindings);
            }
        };

    }

    RaceMtpLabelDir.$inject = [];

    return RaceMtpLabelDir;

});

modules/Races/components/raceMtpLabel/raceMtpLabelMod.js
"use strict";

define('RaceMtpLabelMod',[
        'RaceMtpLabelDir'

    ],
    function (raceMtpLabelDir) {

        angular.module('TVG.RaceMTPLabel', [])

            .directive('raceMtpLabel', raceMtpLabelDir);

    }
);

modules/Races/racesMod.js
'use strict';

define(
    'Races',[
        'RaceMTPFilter',
        'MtpDisplayModel',
        'RaceStatusLabelDir',
        'RaceMtpLabelMod',
    ],

    function (
            RaceMTPFilter,
            MtpDisplay,
            RaceStatusLabelDir,
            RaceMtpLabelMod
        ) {

        angular.module('TVG.Races', [
                'TVG.RaceMTPLabel',
                'TVG.Common.GTM'
        ])

            .filter('raceMtp', RaceMTPFilter)

            .directive('raceStatusLabel', RaceStatusLabelDir)
            .directive('mtpIcon', function() {
                return {
                    restrict: '',
                    replace: true,
                    scope: {
                        racePostTime: '=',
                        mtp: '='
                    },
                    template: ['<i class="tvg-icon-mtp"',
                        'ng-class="{',
                            '\'mtp-near\' : mtpDisplay.mtpStatus == \'near\',',
                            '\'mtp-med\' : mtpDisplay.mtpStatus == \'med\',',
                            '\'mtp-far\' : mtpDisplay.mtpStatus == \'far\'}"',
                            'ng-show="mtpDisplay.mtpStatus && mtpDisplay.mtpStatus != \'time-format\'"></i>'].join(''),
                    link: function (scope) {
                        scope.mtpDisplay = {};

                        function _setMtpDisplay() {
                            scope.mtpDisplay = new MtpDisplay(scope.racePostTime, scope.mtp);
                        }

                        (function init(){
                            _setMtpDisplay();
                        }());

                        scope.$watch('racePostTime', _setMtpDisplay);
                        scope.$watch('mtp', _setMtpDisplay);
                    }
                };
            });
    }
);

modules/Security/providers/securitySvc.js
'use strict';

define('SecuritySvc',['lodash'], function (_) {

    /**
     * Security service
     * Handles session authentication and user account details management
     *
     * Some of the methods that need to connect to the backend may use different
     * versions of the API/services, according to the feature flags
     * "gkeLogin" and "gkeSession".
     */
    function SecuritySvc(
            $http,
            $q,
            $rootScope,
            $timeout,
            $filter,
            $window,
            $httpParamSerializerJQLike,
            CookieFac,
            GTMFac,
            GeoComplyLoginSvc,
            ConfigurationFac,
            FavoriteTracksFac,
            RequestContextHeaders,
            PreferencesFac
        ) {

        var Security = {

            /**
             * Login user using one of the following methods:
             * - new login, using 'usa' microservices
             * - new geolocation login, using 'usa' microservices
             * - old login, using tvg3 php services
             *
             * @param  {Object} params               Login credentials
             * @param  {String} params.loginType     Login type ['pin', 'email']
             * @param  {String} params.stateAbbr     US state abbreviation
             * @param  {String} params.accountField  User's account number or email
             * @param  {String} params.pinField      User's account pin or password
             *
             * @return {Promise}
             */
            login: function (params) {

                // @TODO include 4njbets logic in new _login()
                if (_isNjBets() && _useGeoComply()) {
                    return GeoComplyLoginSvc.login(params);
                }

                if (_isGkeLogin()) {
                    return _login(params);
                } else {
                    return _legacyLogin(params);
                }
            },

            /**
             * Logout user using one of the following methods:
             * - new login, using 'usa' microservices
             * - new geolocation login, using 'usa' microservices
             * - old login, using tvg3 php services
             *
             * @return {Promise}
             */
            logout: function () {

                // @TODO include 4njbets logic in new _login()
                if (_isNjBets()) {
                    return GeoComplyLoginSvc.logout();
                }

                if (_isGkeLogin()) {
                    return _logout();
                } else {
                    return _legacyLogout();
                }
            },

            /**
             * Validate user session only.
             * This method does not change the global user object.
             * (the cookie "tvg3token" must be present in the request)
             *
             * @return {Promise} Promised request
             */
            validateSession: function () {

                if (_isGkeSession()) {
                    return _validateSession();
                } else {
                    return _legacyValidateSession();
                }
            },

            /***
             * Validate user session and set the global user object based on response
             * Was setUserProfileFromSession() before.
             * (the cookie "tvg3token" must be present in the request)
             *
             * @returns {Promise}  Promised request
             */
            restoreSession: function () {

                if (_isGkeSession()) {
                    return _restoreSession();
                } else {
                    return _legacyRestoreSession();
                }
            },

            /**
             * Get user validation endpoint to use in other modules
             * @return {String}  Session validation endpoint URL
             */
            getValidateSessionUrl: getValidateSessionUrl,

            changePin: function (params) {
                var deferred = $q.defer();
                var ret = null;

                params.id = 'change_pin';

                $http(_getAccountConfig(params)).success(function (response) {

                    ret = _handlePinUpdateResponse(response);

                    if (response.status == 'success') {
                        if ($rootScope.user && $window.clientApp === 'touchclient') {
                            var p = {};
                            p.gaEventCategory = 'Account';
                            p.gaEventAction = GTMFac.isTVG4() ? 'Profile' : 'Preferences';
                            p.gaEventLabel = 'Change Pin Number';
                            p.sectionName = GTMFac.isTVG4() ? 'My Account|Profile' : 'My Account';

                            GTMFac.GTMEvent().send($rootScope, 'changePin', p);
                        }
                        deferred.resolve(ret);
                    } else {
                        deferred.reject(ret);
                    }
                }).error(function (response) {
                    ret = _handlePinUpdateResponse(response);
                    deferred.reject(ret);
                });

                return deferred.promise;
            },

            changePassword: function (params) {
                var deferred = $q.defer();
                var ret = null;

                params.id = 'change_password';

                $http(_getAccountConfig(params)).success(function (response) {

                    ret = _handlePasswordUpdateResponse(response);

                    if (response.status == 'success') {
                        if ($rootScope.user) {
                            var p = {};
                            p.gaEventCategory = 'Account';
                            p.gaEventAction = GTMFac.isTVG4() ? 'Profile' : 'Preferences';
                            p.gaEventLabel = 'Change Password Number';
                            p.sectionName = GTMFac.isTVG4() ? 'My Account|Profile' : 'My Account';

                            GTMFac.GTMEvent().send($rootScope, 'changePassword', p);
                        }
                        deferred.resolve(ret);
                    } else {
                        deferred.reject(ret);
                    }
                }).error(function (response) {
                    ret = _handlePasswordUpdateResponse(response);
                    deferred.reject(ret);
                });

                return deferred.promise;
            },

            changeEmail: function (params) {
                var deferred = $q.defer();
                var ret = null;

                params.id = 'change_email';

                $http(_getAccountConfig(params)).success(function (response) {

                    ret = _handleEmailUpdateResponse(response);

                    if (response.status == 'success') {
                        if ($rootScope.user) {
                            $rootScope.user.emailAddress = params.email;
                            _broadcastUser();

                            var p = {};
                            p.gaEventCategory = 'Account';
                            p.gaEventAction = GTMFac.isTVG4() ? 'Profile' : 'Preferences';
                            p.gaEventLabel = 'Change Email';
                            p.sectionName = GTMFac.isTVG4() ? 'My Account|Profile' : 'My Account';

                            GTMFac.GTMEvent().send($rootScope, 'changeEmail', p);
                        }
                        deferred.resolve(ret);
                    } else {
                        deferred.reject(ret);
                    }
                }).error(function (response) {
                    ret = _handleEmailUpdateResponse(response);
                    deferred.reject(ret);
                });

                return deferred.promise;
            },

            addUsername: function (params) {
                var deferred = $q.defer();
                var ret = null;

                params.id = 'add_username';

                $http(_getAccountConfig(params)).success(function (response) {

                    // TODO - fix this handling, since the operation is not implemented in the backend
                    ret = _handleAddUsernameResponse(response);

                    if (response.status == 'success') {
                        $rootScope.user.userName = params.username;
                        _broadcastUser();
                        deferred.resolve(ret);
                    } else {
                        deferred.reject(ret);
                    }
                }).error(function (response) {
                    // TODO - fix this handling, since the operation is not implemented in the backend
                    ret = _handleAddUsernameResponse(response);
                    deferred.reject(ret);
                });

                return deferred.promise;
            },

            changeUsername: function (params) {
                var deferred = $q.defer();
                var ret = null;

                params.id = 'change_username';

                $http(_getAccountConfig(params)).success(function (response) {

                    ret = _handleChangeUsernameResponse(response);

                    if (response.status == 'success') {
                        $rootScope.user.userName = params.username;
                        _broadcastUser();
                        deferred.resolve(ret);
                    } else {
                        deferred.reject(ret);
                    }
                }).error(function (response) {
                    ret = _handleChangeUsernameResponse(response);
                    deferred.reject(ret);
                });

                return deferred.promise;
            },

            checkUsername: function (username) {
                var deferred = $q.defer();
                $http.get('/ajax/registration/method/usernameCheck/username/' + username).success(function (response) {
                    deferred.resolve((response === true || response === 'true'));
                }).error(function () {
                    // The error type doesn't matter too much because the app will try to add the user anyway
                    var errorResponse = {
                        status: 'error'
                    };
                    deferred.reject(errorResponse);
                });

                return deferred.promise;
            },

            getUserAccountNumber: _getUserAccountNumber,

            apiResponseTransformer: function (rawData) {
                rawData = rawData || {};

                return {
                    accountNumber: rawData.AccountNumber,
                    firstName: rawData.FirstName,
                    lastName: rawData.LastName,
                    phoneNumber: rawData.PrimaryPhone,
                    userName: rawData.userName,
                    wagerStatus: rawData.WagerStatus,
                    homeAddress: rawData.HomeAddress,
                    mailingAddress: rawData.MailingAddress,
                    emailAddress: rawData.EmailAddress,
                    signalProviderId: rawData.SignalProviderId,
                    signalProviderNeedsUpdate: rawData.SignalProviderNeedsUpdate,
                    transportId: rawData.TransportId
                };
            }
        };


        function _broadcastUser() {
            CookieFac.setCookie('hasLoginOnce', true, {path: '/', expires: 365});

            $timeout(function () {
                //Timer Needed to insure that the pref cookie has been
                //stored by the browser.
                $rootScope.$broadcast('user', $rootScope.user);
            }, 100);
        }

        function _broadcastInvalidSession() {
            $rootScope.$broadcast('invalidSession');
        }

        function _broadcastGTMUserLogout() {
            $rootScope.$broadcast('GTMUserLoggedOut');
        }

        function _getAccountConfig(params) {
            return {
                method: 'POST',
                url: '/ajax/accounts/',
                data: $httpParamSerializerJQLike(params),
                headers: {
                    'content-type': 'application/x-www-form-urlencoded'
                }
            };
        }

        function _handlePinUpdateResponse(response) {
            var message = $filter('CMSValue')('changePinError');
            var status = 'error';

            if (response.status == 'success') {
                status = 'success';
                message = $filter('CMSValue')('pinSuccessfullyChanged');
            } else if (response && response.Error && response.Error.Name == 'AccountInvalidPin') {
                message = $filter('CMSValue')('oldPinInvalid');
            }

            return {
                status: status,
                message: message
            };
        }

        function _handlePasswordUpdateResponse(response) {
            var message = $filter('CMSValue')('errorChangePassword');
            var status = 'error';

            if (response && response.status == 'success') {
                status = 'success';
                message = $filter('CMSValue')('passwordSuccessfullyChanged');
            } else if (response && (response.ErrorMessage == 'InputInvalidPassword' || response.ErrorMessage == 'IncorrectPassword')) {
                message = $filter('CMSValue')('oldPasswordInvalid');
            }

            return {
                status: status,
                message: message
            };
        }

        function _handleEmailUpdateResponse(response) {
            var message = $filter('CMSValue')('changeEmailError');
            var status = 'error';

            //TODO Review this once the service is implemented
            if (response && response.status == 'success') {
                status = 'success';
                message = $filter('CMSValue')('emailSuccessfullyChanged');
            }
            return {
                status: status,
                message: message
            };
        }

        /**
         * Select the appropriate message according to the API response
         * @param  {Object} response  API response
         * @return {Object}           Handled error/success information
         */
        function _handleAddUsernameResponse(response) {
            /* istanbul ignore next */
            response = response || {};

            var errors = {
                'UsernameAlreadyExists'     : 'usernameAlreadyExists',
                'InputInvalidUsername'      : 'accountInputInvalidUsername',
                'AccountAlreadyHasUsername' : 'accountAlreadyHasUsername',
                'default'                   : 'errorCreatingUsername'
            };
            var status = 'success';
            var code = 'usernameSuccessfullyCreated';


            if (response.status !== 'success') {
                code = errors[response.ErrorMessage] || errors.default;
                status = 'error';
            }

            return {
                status: status,
                message: $filter('CMSValue')(code)
            };
        }

        /**
         * Select the appropriate message according to the API response
         * @param  {Object} response  API response
         * @return {Object}           Handled error/success information
         */
        function _handleChangeUsernameResponse(response) {
            /* istanbul ignore next */
            response = response || {};

            var errors = {
                'UsernameAlreadyExists'     : 'usernameAlreadyExists',
                'InputInvalidUsername'      : 'accountInputInvalidUsername',
                'AccountAlreadyHasUsername' : 'accountAlreadyHasUsername',
                'IncorrectPassword'         : 'usernameChangeIncorrectPassword',
                'default'                   : 'errorUpdatingUsername'
            };
            var status = 'success';
            var code = 'usernameSuccessfullyUpdated';


            if (response.status !== 'success') {
                code = errors[response.ErrorMessage] || errors.default;
                status = 'error';
            }

            return {
                status: status,
                message: $filter('CMSValue')(code)
            };
        }

        function _buildSuccessResponse(response) {
            var status = response.AccountStatus;
            var errors = {
                14: 'ValidButNeedsEmailAndQuestions',
                15: 'ValidButNeedsQuestions',
                16: 'ValidButNeedsEmail',
                17: 'ValidButNeedsSignProvider',
                18: 'ValidButHasNewPricingPlan',
                19: 'ValidButHasDelinquentPricingPlan',
                default: 'Valid'
            };

            return {
                message: '',
                messageKey: errors[status] || errors.default,
                redirectUrl: ''
            };
        }

        /**
         * Get the microservice URL, prepending the correct domain (if needed)
         * Service keys must match the ones in ConfigurationFac.js
         *
         * @return {String}  Service URL with correct host prepended
         */
        function _getServiceUrl(path, service) {
            // available services [usa, usa_v1, uam] -> match ConfigurationFac
            var baseUrl = ConfigurationFac.getServiceApiUrl(service || 'usa');

            return  baseUrl + path;
        }

        /**
         * Extract the response.data to comply with legacy
         * responses/methods.
         *
         * @TODO move to some kind of utilities
         *
         * @param  {Object} response  Response data
         * @return {Object}
         */
        function _extractResponseData(response) {

            /* istanbul ignore next */
            var data = response || {};
            var hasWrapper = _.every(['data', 'status', 'headers'], function (key) {
                return data.hasOwnProperty(key);
            });

            return hasWrapper ?
                response.data : response;
        }

        /**
         * Generate microservices' required headers
         * @return {Object}  Headers
         */
        function _generateServiceHeaders(overrides) {

            var clientApp = $window.clientApp;
            var locationContext = $window.locationContext;
            var tvgContext = RequestContextHeaders[clientApp + '_' + locationContext];
            var defaults = {
                'accept': 'application/json',
                'content-type': 'application/json',
                'x-clientapp': clientApp,
                'x-tvg-context': tvgContext
            };

            return _.defaults(overrides || {}, defaults);
        }

        /**
         * Are we currently in 4NJBets platform?
         *
         * @TODO  move to configuration fac
         *
         * @return {Boolean} is NJBets?
         */
        function _isNjBets() {
            return (ConfigurationFac.getApplicationContext().location === 'nj');
        }

        /**
         * Should we use the 'usa' microservice to login/logout?
         * @return {Boolean}  Use 'usa' microservice?
         */
        function _isGkeLogin() {
            /* istanbul ignore next */
            return ($rootScope.activeFeatures || {}).gkeLogin;
        }

        /**
         * Should we use the 'usa' microservice to restore sessions?
         * @return {Boolean}  Use 'usa' microservice?
         */
        function _isGkeSession() {
            /* istanbul ignore next */
            return ($rootScope.activeFeatures || {}).gkeSessionBetslip;
        }

        /**
         * Should use geocomply service to authenticate?
         * @returns {boolean}
         * @private
         */
        function _useGeoComply() {
            /* istanbul ignore next */
            return !!($rootScope.activeFeatures || {}).geoComply;
        }

        /**
         * Get session cookies from old /ajax session request
         * @TODO remove as soon as preferences are ready!
         *
         * @param {Object}  response  Login response to reply with
         * @return {Object}           Handled login response
         */
        function _getSessionCookies(response) {

            return $http({
                    method: 'GET',
                    url: '/ajax/accounts/id/session'
                })
                // don't mess with login/logout's original response
                // don't break on errors...
                .then(function () {
                    return response;
                })
                .catch(function () {
                    return response;
                });
        }

        /**
         * Try to load user's favorites tracks, ignoring any error that may occur,
         * and bypassing the input response to the next method of the promise chain
         *
         * @param {Object} response   Response to bypass
         * @return {Promise}          Promise wrapping the input response argument
         */
        function _loadFavoriteTracks(response) {

            var returnReponse = function () {
                return response;
            };

            return FavoriteTracksFac.loadFavoriteTracks()
                .then(returnReponse)
                .catch(returnReponse); // don't block login because of this
        }

        //
        // LOGIN
        //

        /**
         * Login using the 'usa' microservice
         * (login v2)
         *
         * @param  {Object} params               Login credentials
         * @param  {String} params.stateAbbr     US state abbreviation
         * @param  {String} params.accountField  User's account number or email
         * @param  {String} params.pinField      User's account pin or password
         * @param  {String} [params.geoPacket]   GeoComply information
         *
         * @return {Promise}        Login promise
         */
        function _login(params) {

            var data = {
                account: params.accountField,
                stateAbbr: params.stateAbbr,
                pin: params.pinField
            };


            _startLoginLoader();


            return $http({
                    method: 'POST',
                    url: _getServiceUrl('/login', 'usa'),
                    data: data,
                    headers: _generateServiceHeaders()
                })
                .then(_extractResponseData)
                .then(_appendSignalProviderProperty)
                .then(_toLegacyLoginSuccessResponse)
                .then(_getSessionCookies)
                .then(_handleLoginSuccess)
                .then(_loadFavoriteTracks)
                .catch(_handleLoginError);
        }

        /**
         * Login using old TVG3 PHP services and .net api
         * (login v1)
         *
         * @param  {Object} params               Login credentials
         * @param  {String} params.loginType     Login type ['pin', 'email']
         * @param  {String} params.stateAbbr     US state abbreviation
         * @param  {String} params.accountField  User's account number or email
         * @param  {String} params.pinField      User's account pin or password
         * @return {Promise}                     Login promise
         */
        function _legacyLogin(params) {

            var data = {
                loginType: params.loginType,
                stateAbbr: params.stateAbbr,
                accountField: params.accountField,
                pinField: params.pinField
            };


            _startLoginLoader();


            return $http({
                    method: 'POST',
                    url: '/login',
                    data: $httpParamSerializerJQLike(data),
                    headers: _generateServiceHeaders({
                        'content-type': 'application/x-www-form-urlencoded'
                    })
                })
                .then(_extractResponseData)
                .then(_appendSignalProviderProperty)
                .then(_handleLoginSuccess)
                .then(_loadFavoriteTracks)
                .catch(_handleLoginError);
        }

        /**
         * Extracts SignalProviderNeedsUpdate property from the response
         * TEMPORARY SOLUTION
         * **/
        function _appendSignalProviderProperty(response) {

            var isSignalProviderEnabled = ($rootScope.activeFeatures || {}).signalProviderModal;

            if (!isSignalProviderEnabled) {
                return $q.resolve(response);
            }

            return $http({
                method: 'GET',
                url: _getServiceUrl('/profile', 'uam'),
                headers: _generateServiceHeaders()
            })
            .then(_extractResponseData)
            .then(function (data) {
                _.merge(response.userDetails, _.pick(data, 'signalProviderNeedsUpdate'));
                return response;
            })
            .catch(function () {
                return response;
            });
        }

        /**
         * Transform the login v2 success response into a login v1 sucecss response
         * so the following parsers and ui models don't break.
         *
         * @param {Object} response  New microservice response
         * @return {Object}          Parsed response (similar to old service)
         */
        function _toLegacyLoginSuccessResponse(response) {
            return _extractLegacyUserDetails(response);
        }

        /*
         * Extract a user details model from login or session restore API
         * responses.
         *
         * @param {Object} response  New microservice response
         * @return {Object}          Parsed response (similar to old service)
         */
        function _extractLegacyUserDetails(response) {

            /* istanbul ignore next */
            var user = (response || {}).userDetails;
            var parsed = response;
            var homeAddress;
            var mailingAddress;


            if (user) {
                /* istanbul ignore next */
                homeAddress = user.homeAddress || {};
                /* istanbul ignore next */
                mailingAddress = user.mailingAddress || {};

                parsed = {
                    status: (user.status || '').toLowerCase(),
                    AccountNumber: user.accountNumber,
                    FirstName: user.firstName,
                    LastName: user.lastName,
                    PrimaryPhone: user.primaryPhone,
                    WagerStatus: user.wagerStatus,
                    EmailAddress: user.emailAddress,
                    HomeAddress: {
                        StreetNumber: homeAddress.streetNumber,
                        Address1: homeAddress.address1,
                        Address2: homeAddress.address2,
                        City: homeAddress.city,
                        StateAbbr: homeAddress.stateAbbr,
                        State: homeAddress.state,
                        Zip: homeAddress.zip
                    },
                    MailingAddress: {
                        StreetNumber: mailingAddress.streetNumber,
                        Address1: mailingAddress.address1,
                        Address2: mailingAddress.address2,
                        City: mailingAddress.city,
                        StateAbbr: mailingAddress.stateAbbr,
                        State: homeAddress.state,
                        Zip: mailingAddress.zip
                    },
                    SignalProviderId: user.signalProviderId,
                    SignalProviderNeedsUpdate: user.signalProviderNeedsUpdate,
                    TransportId: user.transportId,
                    userName: user.userName
                };
            }

            // normalize missing email address as string
            if (parsed && !parsed.EmailAddress) {
                parsed.EmailAddress = '';
            }

            return parsed;
        }

        /**
         * Transform the login v2 error response into a login v1 error response
         * so the following parsers and ui models don't break.
         *
         * @param {Object} response  New microservice response
         * @return {Object}          Parsed response (similar to old service)
         */
        function _toLegacyLoginErrorResponse(response) {

            /* istanbul ignore next */
            response = response || {};

            // some codes from .net API, proxied by USA microservice
            var handledErrors = {
                ACCOUNT_DISABLED           : { ErrorCode: 213 , ErrorMessage: 'LoginFailureAccountDisabled'         },
                ACCOUNT_LOCKED             : { ErrorCode: 207 , ErrorMessage: 'LoginFailureAccountLocked'           },
                ACCOUNT_UPDATE_REQUIRED    : { ErrorCode: 0   , ErrorMessage: 'LoginFailureAccountUpdateRequired'   },
                BLOCKED_SERVICE            : { ErrorCode: 0   , ErrorMessage: 'GeoLocationBlockedService'           },
                BLOCKED_SOFTWARE           : { ErrorCode: 0   , ErrorMessage: 'GeoLocationBlockedSoftware'          },
                GEO_SERVICE_FAILURE        : { ErrorCode: 0   , ErrorMessage: 'LoginFailureGeneric'                 },
                INVALID_CREDENTIALS        : { ErrorCode: 201 , ErrorMessage: 'LoginFailureInvalidCredentials'      },
                INVALID_GEO                : { ErrorCode: 0   , ErrorMessage: 'GeoLocationUnconfirmedOrInvalid'     },
                INVALID_GEOPACKET          : { ErrorCode: 0   , ErrorMessage: 'GeoLocationUnconfirmedOrInvalid'     },
                INVALID_WAGERING_STATE     : { ErrorCode: 208 , ErrorMessage: 'LoginFailureInvalidWageringState'    },
                LOGIN_FAILED               : { ErrorCode: 0   , ErrorMessage: 'LoginFailureGeneric'                 },
                LOGIN_REDIRECT             : { ErrorCode: 0   , ErrorMessage: 'LoginSiteRedirect'                   },
                MISSING_TOKEN              : { ErrorCode: 0   , ErrorMessage: 'ApiMissingUserSessionToken'          },
                NON_LEGAL_STATE            : { ErrorCode: 0   , ErrorMessage: 'LoginFailureGeneric'                 },
                OUT_OF_BOUNDARY            : { ErrorCode: 0   , ErrorMessage: 'GeoLocationOutOfBoundary'            },
                SESSION_NOT_FOUND          : { ErrorCode: 0   , ErrorMessage: 'ApiUserSessionNotFound'              },
                SESSION_TIMEOUT            : { ErrorCode: 0   , ErrorMessage: 'ApiUserSessionTimedOut'              },
                UNCONFIRMED_BOUNDARY       : { ErrorCode: 0   , ErrorMessage: 'GeoLocationUnconfirmedOrInvalid'     },
                USER_SESSION_LIMIT_REACHED : { ErrorCode: 0   , ErrorMessage: 'LoginFailureUserSessionLimitReached' },
                default                    : { ErrorCode: 0   , ErrorMessage: 'LoginFailureGeneric'                 }
            };
            var parsed = response;
            var redirectUrl = parsed.redirectUrl || parsed.RedirectUrl;


            // convert (if not already converted)
            if (!parsed.ErrorCode && !parsed.ErrorMessage) {
                parsed = handledErrors[response.exception];

                if (!parsed) {
                    if (redirectUrl) {
                        parsed = handledErrors.LOGIN_REDIRECT;
                        parsed.redirectUrl = redirectUrl;
                    } else {
                        parsed = handledErrors.default;
                    }
                }
            }

            return parsed;
        }

        /**
         * Handle login success by loading user's favorite tracks and then
         * logging the event with GTM and parsing API response
         *
         * @param  {Object} response  API response
         * @return {Object}           Parsed login response
         */
        function _handleLoginSuccess(response) {

            // catch login errors with _handleLoginError()
            if (!response || response.status !== 'success') {
                return $q.reject(response);
            }

            var data = _parseSuccessResponse(response);

            _stopLoginLoader();
            _logLoginSuccessWithGTM(response);
            _emitGlobalLoginEvent();

            return data;
        }

        /**
         * Parse the successfull login response data
         * @param  {Object} response  Raw login response
         * @return {Object}           Parsed login response
         */
        function _parseSuccessResponse(response) {
            //TODO: response.ErrorMessage === 'LoginRedirect' -> For Now lets just consider this a success login and do nothing!!
            var successResponse = _buildSuccessResponse(response);

            $rootScope.user = Security.apiResponseTransformer(response);
            $rootScope.userSession = true;

            return successResponse;
        }

        /**
         * Handle login error by logging the event with GTM and
         * parsing API response
         *
         * @param  {Object} response  Unsuccessful API response
         * @return {Object}           Parsed error login object
         */
        function _handleLoginError(response) {
            var data = null;

            response = _extractResponseData(response);
            response = _toLegacyLoginErrorResponse(response);
            data = _parseLoginErrors(response);

            _stopLoginLoader();
            _logLoginErrorWithGTM(response);

            $rootScope.$broadcast('loginError', data);

            return $q.reject(data);
        }

        /**
         * Parse the unsuccessfull login response data
         * @param  {Object} response  Raw login response
         * @return {Object}           Parsed login response
         */
        function _parseLoginErrors(response) {

            var errorKey = response.ErrorMessage || response.errorMessage || '';
            var errorCode = response.ErrorCode || response.errorCode || 0;
            var httpKey = 'http_' + errorCode;
            var redirectUrl = response.RedirectUrl || response.redirectUrl || '';
            var messages = {
                LoginFailureUserSessionLimitReached : 'loginFailureUserSessionLimitReached',
                LoginFailureInvalidCredentials      : 'loginFailureInvalidCredentials',
                LoginFailureAccountUpdateRequired   : 'loginFailureAccountUpdateRequired',
                LoginFailureAccountLocked           : 'loginFailureAccountLocked',
                LoginFailureAccountDisabled         : 'loginFailureAccountDisabled',
                LoginSiteRedirect                   : 'loginSiteRedirect',
                ApiMissingUserSessionToken          : 'apiUserSessionTimedOut',
                ApiUserSessionTimedOut              : 'apiUserSessionTimedOut',
                ApiUserSessionNotFound              : 'apiUserSessionTimedOut',
                http_208                            : 'loginFailureNonLegalState',
                default                             : 'loginFailureGeneric'
            };
            var cmsKey = messages[httpKey] || messages[errorKey] || messages.default;
            var message = $filter('CMSValue')(cmsKey);


            // new services only return "redirectUrl", without the "LoginSiteRedirect" errorMessage
            if (redirectUrl) {
                message += redirectUrl;
                redirectUrl = _ensureProtocol(redirectUrl);
            }

            return {
                message: message,
                messageKey: errorKey,
                redirectUrl: redirectUrl
            };
        }

        /**
         * Make sure the URL contains a valid HTTP/HTTPS protocol
         * @param {String} url  Raw URL
         * @return {String}     Parsed URL
         */
        function _ensureProtocol(url) {
            url = url || '';

            // does not start with http://, https:// or //
            if (!url.match('^(https?:)?//.*')) {
                url = '//' + url;
            }

            return url;
        }

        /**
         * Start login's loader
         */
        function _startLoginLoader() {
            $rootScope.loginOk = false;
        }

        /**
         * Stop login's loader
         */
        function _stopLoginLoader() {
            $rootScope.loginOk = true;
        }

        /**
         * Broadcast everyone that a login has been made
         * (don't know why the timeout hack is needed, because _broadcastUser()
         * alreay has a timeout inside...)
         */
        function _emitGlobalLoginEvent() {

            // @TODO why the timeout???
            $timeout(function () {
                $rootScope.$broadcast('login', true);
            }, 100);

            _broadcastUser();
        }

        /**
         * Register login 'success' using GTM
         * @param  {Object} response  API login response
         */
        function _logLoginSuccessWithGTM(response) {
            /* istanbul ignore next */
            response = response || {};

            // user details are defined here, because GTMFac may not have them
            // already defined in rootScope to use
            var event = {
                gaEventCategory: 'Login',
                gaEventAction: 'Login Success',
                accountId: response.AccountNumber,
                residenceState: response.HomeAddress ?
                    response.HomeAddress.StateAbbr : null,
                loginStatus: 'Logged In',
                registrationStatus: 'Registered'
            };

            GTMFac.GTMEvent()
                .send($rootScope, 'loginSuccess', event);
        }

        /**
         * Register any login errors using GTM
         * @param  {Object} response  API login response
         */
        function _logLoginErrorWithGTM(response) {
            /* istanbul ignore next */
            response = response || {};

            var event = {
                gaEventCategory: 'Login',
                gaEventAction: 'Login Error',
                gaEventLabel: response.message,
                errorType: 'Login Error',
                errorMessage: response.message
            };

            GTMFac.GTMEvent()
                .send($rootScope, 'loginError', event);
        }

        //
        // LOGOUT
        //

        /**
         * Logout using the 'usa' microservice
         * (logout v2)
         *
         * @return {Promise}        Logout promise
         */
        function _logout() {

            _startLogoutLoader();

            return $http({
                    method: 'POST',
                    url: _getServiceUrl('/logout', 'usa'),
                    headers: _generateServiceHeaders()
                })
                .then(_extractResponseData)
                .then(_toLegacyLogoutSuccessResponse)
                .then(_getSessionCookies)
                .then(_handleLogoutSuccess)
                .then(_removeTVG3Link)
                .catch(_handleLogoutError);
        }

        /**
         * Remove TVG3 Link local storage key
         */
        function _removeTVG3Link() {
            localStorage.removeItem("tvg3Link");
            $rootScope.$broadcast('changedTvg3Link');
        }

        /**
         * Logout using old TVG3 PHP services and .net api
         * (logout v1)
         *
         * @return {Promise}        Logout promise
         */
        function _legacyLogout() {

            _startLogoutLoader();

            return $http.get('/login/log/out', {
                    headers: _generateServiceHeaders()
                })
                .then(_extractResponseData)
                .then(_removeTVG3Link)
                .then(_handleLogoutSuccess)
                .catch(_handleLogoutError);
        }

        /**
         * Transform the logout v2 response into a logout v1 response
         * so the following parsers and ui models don't break.
         *
         * @param {Object} response  New microservice response
         * @return {Object}          Parsed response (similar to old service)
         */
        function _toLegacyLogoutSuccessResponse(response) {
            return response;
        }

        /**
         * Transform the logout v2 error response into a logout v1 error response
         * so the following parsers and ui models don't break.
         *
         * @param {Object} response  New microservice response
         * @return {Object}          Parsed response (similar to old service)
         */
        function _toLegacyLogoutErrorResponse(response) {
            return response;
        }

        /**
         * Handle logout success by loading clearing user's favorite tracks and then
         * logging the event with GTM and parsing API response
         *
         * @param  {Object} response  API response
         * @return {Promise}          Parsed logout response
         */
        function _handleLogoutSuccess(response) {

            return $q(function (resolve) {

                _logLogoutSuccessWithGTM();

                $rootScope.user = null;
                $rootScope.userSession = false;

                $timeout(function () {
                    FavoriteTracksFac.clearFavoriteList();

                    _emitGlobalLogoutEvent();
                    _stopLogoutLoader();

                    resolve(response);
                }, 100);
            });
        }

        /**
         * Handle logout error by logging the event with GTM and
         * parsing API response
         *
         * @param  {Object} response  Unsuccessful API response or runtime error
         * @return {Promise}          Rejected API response
         */
        function _handleLogoutError(response) {

            response = _extractResponseData(response);
            response = _toLegacyLogoutErrorResponse(response);

            _stopLogoutLoader();

            return $q.reject(response);
        }

        /**
         * Start logout's loader
         */
        function _startLogoutLoader() {
            $rootScope.logoutOk = false;
        }

        /**
         * Stop logout's loader
         */
        function _stopLogoutLoader() {
            $rootScope.logoutOk = true;
        }

        /**
         * Broadcast everyone that a logout has been made
         */
        function _emitGlobalLogoutEvent() {
            $rootScope.$broadcast('logout');

            /*
             TODO: luis almeida
             created another event for logout, as I think this is the 'real' logout:
             this only fires when the user actually presses the logout button.
             Lets review how we fire session / user / logout / login events
             */
            $rootScope.$broadcast('userLogout');
        }

        /**
         * Register logout 'success' using GTM
         */
        function _logLogoutSuccessWithGTM() {

            var event = {
                gaEventCategory: 'Login',
                gaEventAction: 'Logout Success'
            };

            GTMFac.GTMEvent()
                .send($rootScope, 'logoutSuccess', event);
        }

        //
        // SESSION
        //

        /**
         * Validate session using USA v2 microservice.
         * The cookie "tvg3token" must be present in the request!
         * (hosted in GKE).
         *
         * @return {Promise} Promised request
         */
        function _validateSession() {

            return $http({
                    method: 'GET',
                    url: getValidateSessionUrl(),
                    headers: _generateServiceHeaders()
                })
                .then(_extractResponseData)
                .then(_toLegacySessionSuccessResponse)
                .then(_handleValidateSessionSuccess)
                .catch(_handleValidateSessionError);
        }

        /**
         * Validate session using USA v1 microservice.
         * The cookie "tvg3token" must be present in the request!
         * (hosted in AWS)
         *
         * @return {Promise} Promised request
         */
        function _legacyValidateSession() {

            return $http({
                    method: 'GET',
                    url: getValidateSessionUrl(),
                    headers: _generateServiceHeaders()
                })
                .then(_extractResponseData)
                .then(_handleValidateSessionSuccess)
                .catch(_handleValidateSessionError);
        }

        /**
         * Get user validation endpoint to use in other modules (e.g. videos)
         * @return {String}  Session validation endpoint URL
         */
        function getValidateSessionUrl() {
            var service = _isGkeSession() ? 'usa' : 'usa_v1';

            return _getServiceUrl('/authenticated', service);
        }

        /**
         * Transform the session v2 response into a session v1 response
         * so the following parsers and ui models don't break.
         *
         * @param {Object} response  New microservice response
         * @return {Object}          Parsed response (similar to old service)
         */
        function _toLegacySessionSuccessResponse(response) {
            return response;
        }

        /**
         * Transform the session v2 error response into a session v1 error response
         * so the following parsers and ui models don't break.
         *
         * @param {Object} response  New microservice response
         * @return {Object}          Parsed response (similar to old service)
         */
        function _toLegacySessionErrorResponse(response) {

            /* istanbul ignore next */
            response = response || {};

            // some codes from .net API, proxied by USA microservice
            var handledErrors = {
                default: { 'ErrorCode': 0, 'ErrorMessage': 'Not Authenticated' }
            };
            var parsed = response;


            // convert (if not already converted)
            if (!parsed.ErrorCode && !parsed.ErrorMessage) {
                parsed = handledErrors[response.exception] || handledErrors.default;
            }

            return parsed;
        }

        function _handleValidateSessionSuccess() {

            //
            // @TODO must check if broadcast user really makes sense, because
            // validate session doesn't return any user details
            //

            $rootScope.userSession = true;
            _broadcastUser();

            return null;
        }

        function _handleValidateSessionError(response) {

            response = _extractResponseData(response);
            response = _toLegacySessionErrorResponse(response);

            _broadcastInvalidSession();

            return $q.reject(response);
        }

        /**
         * Validate user session and set the global user object based
         * on response, using USA v2 microservice.
         * The cookie "tvg3token" must be present in the request!
         * (hosted in GKE)
         *
         * @return {Promise} Promised request
         */
        function _restoreSession() {
            var userId;

            try {
                userId = sessionStorage.getItem('userId');
            } catch(e) {
                // Unable to read from session storage, fallback to request userId from service
                _getUserAccountNumber().then(_getUserProfileAndRestoreSession);
            }

            return userId ?
                _getUserProfileAndRestoreSession(userId) :
                _getUserAccountNumber().then(_getUserProfileAndRestoreSession);
        }

        function _getUserAccountNumber() {
            return $http({
                method: 'GET',
                url: _getServiceUrl('/session/context', 'usa'),
                headers: _generateServiceHeaders()
            })
            .then(function(response) {
                var userId = response && response.data ? response.data.accountNumber : null;
                try {
                    sessionStorage.setItem('userId', userId);
                } catch(e) {};

                return userId;
            })
            .catch(_handleRestoreSessionError);
        }

        function _getUserProfileAndRestoreSession(userId) {
            return $http({
                method: 'GET',
                url: _getServiceUrl('/users/' + userId + '/profile', 'uam'),
                headers: _generateServiceHeaders()
            })
            .then(_extractResponseData)
            .then(_toLegacyRestoreSessionSuccessResponse)
            .then(_handleRestoreSessionSuccess)
            .catch(_handleRestoreSessionError);
        }

        /**
         * Validate session using USA v1 microservice.
         * The cookie "tvg3token" must be present in the request!
         * (hosted in AWS)
         *
         * @return {Promise} Promised request
         */
        function _legacyRestoreSession() {

            return $http({
                    method: 'GET',
                    url: '/ajax/accounts/id/session'
                })
                .then(_extractResponseData)
                .then(_handleRestoreSessionSuccess)
                .catch(_handleRestoreSessionError);
        }

        function _toLegacyRestoreSessionSuccessResponse(response) {

            response = response || {};
            response.status = 'success';

            return _extractLegacyUserDetails({userDetails: response });
        }

        function _handleRestoreSessionSuccess(response) {

            // catch login errors with _handleRestoreSessionError()
            if (!response || response.status !== 'success') {
                return $q.reject(response);
            }

            var data = _parseSuccessResponse(response);

            // success -> return data after loading favs
            return _loadFavoriteTracks()
                .then(_broadcastUser) // must exec after _parseSuccessResponse
                .then(function () {
                    return data;
                });
        }

        function _handleRestoreSessionError(response) {

            var err = null;

            response = response || {};
            response = _extractResponseData(response);
            response = _toLegacySessionErrorResponse(response);

            if (response.hasOwnProperty('ErrorCode')) {
                _broadcastInvalidSession();
                err = _parseLoginErrors(response);
                return $q.reject(err);
            } else {
                //if we dont have a user session, reject
                if(!$rootScope.user) {
                    _broadcastGTMUserLogout();
                    _broadcastInvalidSession();
                    err = response;
                    return $q.reject(err);
                } else {
                    //keep active user session when the request fails
                    return $q.resolve();
                }
            }
        }

        return Security;
    }

    SecuritySvc.$inject = [
        '$http',
        '$q',
        '$rootScope',
        '$timeout',
        '$filter',
        '$window',
        '$httpParamSerializerJQLike',
        'CookieFac',
        'GTMFac',
        'GeoComplyLoginSvc',
        'ConfigurationFac',
        'FavoriteTracksFac',
        'RequestContextHeaders',
        'PreferencesFac'
    ];

    return SecuritySvc;
});

modules/Security/providers/pollingScheduler.js
"use strict";

define('PollingScheduler',[],function () {

    function PollingScheduler(intervalMs, callback) {
        this.intervalMs = intervalMs;
        this.intervalId = undefined;
        this.intervalCallback = callback;
    }

    PollingScheduler.prototype.cancel = function () {
        if (typeof this.intervalId === 'undefined') {
            return;
        }
        clearInterval(this.intervalId);
    };

    PollingScheduler.prototype.start = function () {
        this.cancel();
        this.intervalId = setInterval(this.intervalCallback, this.intervalMs);
    };

    return PollingScheduler;
});

modules/Security/providers/userSessionSvc.js
"use strict";

define('UserSessionSvc',['PollingScheduler'], function (PollingScheduler) {

    function UserSessionSvc(SecuritySvc, $q, $rootScope) {

        var USER_SESSION_INTERVAL_MS = 60000;
        var _userSessionScheduler;

        function _shouldSetUserProfile(forceGetUserProfile) {
            return forceGetUserProfile || !$rootScope.user;
        }

        function _initializeUserSessionPolling() {
            if (!_userSessionScheduler) {
                _userSessionScheduler = new PollingScheduler(USER_SESSION_INTERVAL_MS, function () {
                    _validateUserSession(true);
                });
            }
            return _userSessionScheduler;
        }

        function _validateUserSession(forceGetUserProfile) {
            var deferred = $q.defer();

            if (_shouldSetUserProfile(forceGetUserProfile)) {
                SecuritySvc.restoreSession()
                    .then(function (response) {
                        _userSessionScheduler.start();
                        deferred.resolve(response);
                    }, function (err) {
                        deferred.reject(err);
                    });
            } else {
                SecuritySvc.validateSession()
                    .then(function (response) {
                        deferred.resolve(response);
                    }, function (err) {
                        deferred.reject(err);
                    });
            }

            return deferred.promise;
        }

        /**
         * Check if there's a created session
         * (should return true after the session validation process runs)
         *
         * @TODO should be moved to the correct fac (if any)
         *
         * @return {Boolean} Whether has session
         */
        function hasSession() {
            var appReady = $rootScope.appReady || {};

            return !!(appReady.session || $rootScope.userSession || $rootScope.appReadyFired);
        }

        /**
         * Execute the passed "method" after the session start event
         * is triggered
         *
         * @TODO should we unbind when rootScope is destroyed?
         *
         * @param {Function} method  Method to delay
         * @return {Promise}
         */
        function callAfterSession(method) {
            var deferred = $q.defer();
            var unbinds = [];
            var sessionHandler = function () {
                var response;

                // unbind all listeners
                unbinds.forEach(function (unbind) {
                    unbind();
                });

                unbinds = [];

                if (typeof method === 'function') {
                    response = method();
                }

                deferred.resolve(response);
            };

            // bind to session and afterLogin
            unbinds.push($rootScope.$on('session', sessionHandler));
            unbinds.push($rootScope.$on('afterLogin', sessionHandler));

            return deferred.promise;
        }


        return {
            validate: function (forceGetUserProfile) {
                var promise;

                if (!$rootScope.activeFeatures.userSessionOnly || $rootScope.activeFeatures.gkeSessionBetslip) {
                    promise = SecuritySvc.restoreSession();
                } else {
                    _initializeUserSessionPolling();
                    promise = _validateUserSession(forceGetUserProfile);
                }

                return promise;
            },
            initializeUserSessionPolling: _initializeUserSessionPolling,
            hasSession: hasSession,
            callAfterSession: callAfterSession,

        };

    }


    UserSessionSvc.$inject = [
        'SecuritySvc',
        '$q',
        '$rootScope'
    ];

    return UserSessionSvc;
});

modules/Security/providers/geoComplyLoginSvc.js
'use strict';

define('GeoComplyLoginSvc',['lodash'], function (_) {

    function GeoComplyLoginSvc(
            $http,
            $rootScope,
            $log,
            $timeout,
            $q,
            $filter,
            $window,
            GeoComplySvc,
            CookieFac,
            RequestContextHeaders,
            FavoriteTracksFac,
            ConfigurationFac
        ) {

        var _errorDictionary = { //.Net Api errors
            INVALID_CREDENTIALS: 'loginFailureInvalidCredentials', //USA Api error
            ACCOUNT_LOCKED: 'loginFailureAccountLocked', //USA Api error
            ACCOUNT_DISABLED: 'loginFailureAccountDisabled', //USA Api error
            LOGIN_REDIRECT: 'loginApplicationRedirect', //USA Api error
            LOGIN_FAILED: 'loginFailureGeneric', //USA Api error
            GEO_SERVICE_FAILURE: 'loginFailureGeneric', //USA Api error
            OUT_OF_BOUNDARY: 'geoLocationOutOfBoundary', //USA Api error
            UNCONFIRMED_BOUNDARY: 'geoLocationUnconfirmedOrInvalid', //USA Api error
            INVALID_GEO: 'geoLocationUnconfirmedOrInvalid', //USA Api error
            BLOCKED_SERVICE: 'geoLocationBlockedService', //USA Api error
            BLOCKED_SOFTWARE: 'geoLocationBlockedSoftware', //USA Api error

            0: 'geoClientErrorUnexpected',
            801: 'geoClientGeoLocationNotSupportedByBrowser', //Solus SDK Error
            802: 'geoClientGeoLocationUnavailable', //Solus SDK Error
            803: 'geoLocationBlockedByDevice', //Solus SDK Error
            804: 'geoClientGeoLocationTimeout' //Solus SDK Error
        };

        GeoComplySvc.setupGeoComply();

        /**
         * @TODO  move to proper service
         *
         * Generate microservices' required headers
         * @return {Object}  Headers
         */
        function _generateServiceHeaders(overrides) {
            var clientApp = $window.clientApp;
            var locationContext = $window.locationContext;
            var tvgContext = RequestContextHeaders[clientApp + '_' + locationContext];
            var defaults = {
                'accept': 'application/json',
                'content-type': 'application/json',
                'x-clientapp': clientApp,
                'x-tvg-context': tvgContext
            };

            return _.defaults(overrides || {}, defaults);
        }

        /**
         *
         * Sets necessary global user attributes and broadcasts login specific events.
         * It also sets the cookie hasLoginOnce to true with an expiration date of 365 days.
         * @private
         */
        function _setUpGlobalApplicationUserAttributes(response) {
            FavoriteTracksFac.loadFavoriteTracks().finally(function() {
                $rootScope.user = {
                    accountNumber: response.accountNumber,
                    firstName: response.firstName,
                    lastName: response.lastName,
                    phoneNumber: response.primaryPhone,
                    userName: response.userName,
                    wagerStatus: response.wagerStatus,
                    homeAddress: response.homeAddress,
                    mailingAddress: response.mailingAddress,
                    emailAddress: response.emailAddress,
                    signalProviderId: response.signalProviderId,
                    transportId: response.transportId
                };

                $rootScope.userSession = true;

                $rootScope.$broadcast('login', true);

                CookieFac.setCookie("hasLoginOnce", true, {path: "/", expires: 365});

                $timeout(function () {
                    //Timer Needed to insure that the pref cookie has been
                    //stored by the browser.
                    $rootScope.$broadcast('user', $rootScope.user);
                }, 100);
            });
            return response;
        }

        /**
         * Handles the response error from login
         * @param response
         * @returns {{message: string, messageKey: (*|string), redirectUrl: (*|string)}}
         * @private
         */
        function _handleErrorResponse(response) {

            //Error cause is used for geo location specific errors
            var errorKey = response.exception ? response.exception : (!_.isUndefined(response.code) ? response.code : null),
                redirectUrl = response.redirectUrl || ''; //TODO: Adjust this redirectUrl when USA is gonna be used on PA and IA

            var message = _errorDictionary[errorKey] ? $filter('CMSValue')(_errorDictionary[errorKey]) : $filter('CMSValue')('loginFailureGeneric');

            if (redirectUrl && redirectUrl.indexOf("http://") == -1 && redirectUrl.indexOf("https://") == -1) {
                redirectUrl = '//' + redirectUrl; // I don't really understand this double slash. Keeping it to avoid breaking stuff.
            }

            return {
                message: message,
                redirectUrl: redirectUrl
            };
        }

        /**
         * Get the login endpoint URL (either from AWS or GKE)
         * @return {String}  Login endpoint
         */
        function _getServiceUrl(path) {
            var baseUrl = '/usa/v2'; // from AWS
            var isGKE = !!($rootScope.activeFeatures || {}).gkeLogin;

            if (isGKE) {
                baseUrl = ConfigurationFac.getServiceApiUrl('usa'); // from GKE
            }

            return  baseUrl + path;
        }

        /**
         * Executes user login request
         * @param userData
         * @private
         */
        function _loginRequest(userData) {
            return function (geoPacket) {
                return $http({
                    method: 'POST',
                    url: _getServiceUrl('/login'),
                    data: {
                        account: userData.accountField,
                        stateAbbr: userData.stateAbbr,
                        pin: userData.pinField,
                        geo: geoPacket
                    },
                    headers: _generateServiceHeaders()
                })
                    .then(function (response) {
                        return response.data.userDetails;
                    })
                    .then(_setUpGlobalApplicationUserAttributes)
                    .then(function () { //Is this object even necessary? Keeping it for now ... TODO: Remove it asap.
                        return {
                            message: '',
                            messageKey: 'Valid',
                            redirectUrl: ''
                        };
                    })
                    .finally(function () {
                        $rootScope.loginOk = true;
                    });
            };
        }

        /**
         * Logs in user based on geo localization
         * Receives an object with: accountField,pinField,loginType,stateAbbr
         * @param params
         * @private
         */
        function _login(params) {
            $rootScope.loginOk = false;

            if (!GeoComplySvc.getGeoClient()) {
                $log.error('Non existing GeoClient');
                $rootScope.loginOk = true;
                return $q.reject(_handleErrorResponse({code: 0}));
            }

            return GeoComplySvc.getGeoPacket(params.accountField)
                .then(_loginRequest(params))
                .catch(function (err) {
                    var errorResponse = _handleErrorResponse(err.data || err);
                    $rootScope.$broadcast('loginError', errorResponse);
                    return $q.reject(errorResponse);
                }).finally(function () {
                    $rootScope.loginOk = true;
                });
        }

        /**
         * Logs out the current user.
         * @returns {*}
         * @private
         */
        function _logout() {
            $rootScope.logoutOk = false;

            return $http({
                method: 'POST',
                url: _getServiceUrl('/logout'),
                headers: _generateServiceHeaders()
            })
                .then(function (response) {
                    return response.data;
                })
                .then(function (response) {
                    $rootScope.user = null;
                    $rootScope.userSession = false;
                    FavoriteTracksFac.clearFavoriteList();
                    $rootScope.$broadcast('logout');
                    /*
                        TODO: luis almeida
                        created another event for logout, as I think this is the "real" logout:
                        this only fires when the user actually presses the logout button.
                        Lets review how we fire session / user / logout / login events
                    */
                    $rootScope.$broadcast('userLogout');
                    return response;
                })
                .catch(function (error) {
                    return $q.reject(error.data);
                })
                .finally(function () {
                    $rootScope.logoutOk = true;
                });
        }

        return {
            login: _login,
            logout: _logout
        };

    }

    GeoComplyLoginSvc.$inject = [
        '$http',
        '$rootScope',
        '$log',
        '$timeout',
        '$q',
        '$filter',
        '$window',
        'GeoComplySvc',
        'CookieFac',
        'RequestContextHeaders',
        'FavoriteTracksFac',
        'ConfigurationFac'
    ];

    return GeoComplyLoginSvc;
});

modules/Security/providers/geoComplySvc.js
'use strict';

define('GeoComplySvc',['lodash', 'PollingScheduler'], function (_, PollingScheduler) {

        function GeoComplySvc($window, $log, $q, $http, RequestContextHeaders, ConfigurationFac) {
            var geoClient = null, geoLicense = null;
            var GET_REGION_INTERVAL_MS = 60000, _getRegionScheduler;

            /**
             * Configures geoComply object to interact with its API and registers the necessary events
             * @private
             */
            function _setUpGeoComply() {
                if (locationContext && locationContext === 'nj' && angular.isDefined($window.GcHtml5)) {
                    geoClient = $window.GcHtml5.createClient(null, null);

                    geoClient.setReason('Awesome geoComply login for TVG');

                    $http({
                        method: 'GET',
                        url: ConfigurationFac.getBaseServiceUrl() + "/geo/v1/license",
                        headers: {
                            'X-ClientApp': clientApp,
                            Accept: 'application/json',
                            'x-tvg-context': RequestContextHeaders[clientApp + '_' + locationContext]
                        }
                    }).success(function (data) {
                        geoLicense = data.license;
                    });

                    // Register the onSuccess handler
                    geoClient.events.on('engine.success', function (text, xml) {
                        geoClient.events.emit('geoPacketAvailable', {success: {text: text, xml: xml}});
                    });

                    // Register error handler
                    geoClient.events.on('*.failed', function (code, message) {
                        geoClient.events.emit('geoPacketAvailable', {error: {code: code, message: message}});
                    });
                }
            }

            /**
             * Gets a geo packet for the user.
             * @param userId
             * @returns {*|promise}
             * @private
             */
            function _getGeoPacket(userId) {
                var deferred = $q.defer();

                if (!userId) {
                    return $q.reject({code: 0});
                } else {
                    if (geoClient && geoLicense) { //request GeoPacket

                        geoClient.events.once('geoPacketAvailable', function (data) {
                            if (data.success) {
                                deferred.resolve(data.success.text);
                            } else {
                                deferred.reject(data.error);
                            }
                        });

                        geoClient.setUserId(userId);
                        geoClient.setLicense(geoLicense);
                        geoClient.request();
                    } else {
                        $log.error('error getting GeoPacket. Client or license not present!');
                        return $q.reject({code: 0});
                    }
                }

                return deferred.promise;
            }

            function _getGeoClient() {
                return geoClient;
            }

            /**
             * Gets a list of Regions
             * @param latitude
             * @param longitude
             * @private
             */
            function _getGeoRegion(position){
                var deferred = $q.defer();
                if (_.isUndefined(position.coords.latitude) && _.isUndefined(position.coords.longitude)) {
                    $log.error('longitude is undefined!');
                    return $q.reject({code: 0});
                } else {
                    $http({
                        method: 'GET',
                        url: ConfigurationFac.getBaseServiceUrl() + "/geo/v1/regions/search/findByGpsCoordinate?latitude=" + position.coords.latitude + '&longitude=' + position.coords.longitude,
                        headers: {
                            'X-ClientApp': clientApp,
                            Accept: 'application/json',
                            'x-tvg-context': RequestContextHeaders[clientApp + '_' + locationContext]
                        }
                    }).success(function (data) {
                        deferred.resolve(data);
                    }).error(function(data, status) {
                        $log.error('error getting GeoRegion: ' + status + ' ' );
                        deferred.reject(data.error);
                    });
                    return deferred.promise;
                }
            }

            /**
             * Gets the geo position using the navigator.geolocation (only works in https)
             * @private
             */
            function _getPosition(callback) {
                if (navigator.geolocation) {
                    navigator.geolocation.getCurrentPosition(function (position){
                        _getGeoRegion(position).then(function(data){
                            callback(data);
                        });
                    });
                } else {
                    $log.error('Geolocation is not supported by this browser.');
                }
            }

            /**
             * Initializes the _getRegionScheduler polling
             * @returns {*}
             * @private
             */
            function _initializeGetRegionPolling(callback){
                if (!_getRegionScheduler) {
                    _getRegionScheduler = new PollingScheduler(GET_REGION_INTERVAL_MS, function () {
                        _getPosition(function (data){
                            callback(data);
                        });
                    });
                }
                _getRegionScheduler.start();
            }

            return {
                getGeoPacket: _getGeoPacket,
                getGeoClient: _getGeoClient,
                initializeGetRegionPolling: _initializeGetRegionPolling,
                getPosition: _getPosition,
                setupGeoComply: _setUpGeoComply
            };

        }

        GeoComplySvc.$inject = [
            '$window',
            '$log',
            '$q',
            '$http',
            'RequestContextHeaders',
            'ConfigurationFac'
        ];

        return GeoComplySvc;
    }
)
;

modules/Security/securityMod.js
'use strict';

define(
    'Security',[
        'SecuritySvc',
        'UserSessionSvc',
        'GeoComplyLoginSvc',
        'GeoComplySvc',
        'GTMMod'
    ],

    function (SecuritySvc, UserSessionSvc, GeoComplyLoginSvc, GeoComplySvc) {

        angular.module('TVG.Security', [
            'TVG.Common.GTM',
            'TVG.FavoriteTracks'
        ])

            .factory('SecuritySvc', SecuritySvc)
            .service('UserSessionSvc', UserSessionSvc)
            .service('GeoComplyLoginSvc', GeoComplyLoginSvc)
            .service('GeoComplySvc', GeoComplySvc)
            .constant('RequestContextHeaders', {
                tvg4_nj: 'tvg4-4njbets',
                tvg4_pa: 'tvg4-pabets',
                tvg4_all: 'tvg4-tvg',
                tvg4_ia: 'tvg4-iowa',
                touch2_nj: 'touch2-4njbets',
                touch2_pa: 'touch2-pabets',
                touch2_all: 'touch2-tvg',
                touch2_ia: 'touch2-iowa'
            });
    }
);

modules/Preferences/entities/preferencesEntity.js
'use strict';

define('PreferencesEntity',[],function () {

    function preferencesEntity(description, metadata, hash){

        this.description = description;
        this.metadata = metadata;
        this.hash = hash;

    }

    return preferencesEntity;

});


modules/Preferences/builders/preferencesEntityBuilder.js
'use strict';

define('PreferencesEntityBuilder',['PreferencesEntity'], function (PreferencesEntity) {

    function builder(){
        var preferences = new PreferencesEntity();

        return {
            withDescription: function (description) {
                preferences.description = description;
                return this;
            },
            withMetadata: function (metadata) {
                preferences.metadata = metadata;
                return this;
            },
            withHash: function (hash) {
                preferences.hash = hash;
                return this;
            },
            build: function () {
                return preferences;
            }
        };
    }

    return builder;

});


modules/UserProfile/providers/services/userProfileSvc.js
'use strict';

define('UserProfileSvc',[ 'lodash', 'PreferencesEntityBuilder' ], function (_, PreferencesEntityBuilder) {

    function UserProfileSvc(
        $http,
        $q,
        $rootScope,
        poller,
        $filter,
        ConfigurationFac,
        PreferencesCookieFac,
        PreferencesFac
    ) {

        var balancePoller = null;

        var BalanceFac = {
            pollBalance: function (forceUpdate) {

                if(!balancePoller || forceUpdate) {
                    balancePoller = poller.get(BalanceFac, {
                        action: 'getAccountBalance',
                        delay: 120000,
                        argumentsArray: [
                            {}
                        ]
                    });
                }

                return balancePoller;
            },

            stopPollingBalance: function (deferred) {
                if (balancePoller) {
                    balancePoller.removeDeferred(deferred);
                    balancePoller = null;
                }
            },

            getAccountBalance: function (accountNumber) {
                if (!accountNumber) {
                    return this.getAccountNumber().then(function (data) {
                        return this.getAccountBalanceData(data.accountNumber);
                    }.bind(this));
                } else {
                    return this.getAccountBalanceData(accountNumber);
                }
            },

            getAccountBalanceData: function  (accountNumber) {
                var deferred = $q.defer();
                var url = ConfigurationFac.getBaseServiceUrl() + '/uwt/v1/users/'+ accountNumber +'/balance';

                $http.get(url, {
                    headers: {
                        'Cache-Control': 'no-cache',
                        'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
                        'Pragma': 'no-cache'
                    }
                }).success(function (response) {
                    deferred.resolve(response);
                }).error(function (response) {
                    deferred.reject(response);
                });

                return deferred.promise;
            },


            getAccountNumber: function () {
                var deferred = $q.defer();
                var url = ConfigurationFac.getBaseServiceUrl() + '/usa/v2/session/context';

                $http.get(url, {
                    headers: {
                        'Cache-Control': 'no-cache',
                        'If-Modified-Since': 'Mon, 26 Jul 1997 05:00:00 GMT',
                        'Pragma': 'no-cache'
                    }
                }).success(function (response) {
                    deferred.resolve(response);
                }).error(function (response) {
                    deferred.reject(response);
                });

                return deferred.promise;
            },

            getVideoCountInfo: function () {
                var deferred = $q.defer();
                var url = '/ajax/video/id/user';

                $http.get(url).success(function (response) {
                    deferred.resolve(response);
                }).error(function (response) {
                    deferred.reject(response);
                });

                return deferred.promise;
            },

            updateAccountBalance: function() {
                var deferred = $q.defer();

                this.getAccountBalance($rootScope && $rootScope.user && $rootScope.user.accountNumber).then(function (response) {

                    if ((response && response.balance === 0) || (response && response.balance && !isNaN(response.balance))) {
                        $rootScope.accountBalanceNumber = response.balance;
                        $rootScope.accountBalance = $filter("currency")(response.balance, "$");
                        $rootScope.$broadcast("accountBalance_changed");
                    }

                    deferred.resolve(response);
                }, function (response) {
                    deferred.reject(response);
                });

                return deferred.promise;
            }
        };

        var CommunicationsPreferencesFac = {
            _getApiUrl: function (contextName, serviceEndpoint) {
                return "/" + contextName + "/api/v1.0/" + serviceEndpoint;
            },

            _getCommunicationsPreferences: function() {
                var url = CommunicationsPreferencesFac._getApiUrl('deposit', "subscriptionsPreferences");
                var deferred = $q.defer();
                var context = JSON.stringify(ConfigurationFac.getApplicationContext());

                $http.get(url, {
                        headers: {
                            'x-tvgcontext': context
                        }
                    }
                ).then(function (response) {
                        if (response.data && response.data.status === 'success') {
                            deferred.resolve(response.data);
                        } else {
                            deferred.reject(response.data);
                        }
                    }, function (e) {
                        deferred.reject(e.data);
                    });

                return deferred.promise;
            },

            _getSubscriptions: function() {
                var deferred = $q.defer();
                var url = [ConfigurationFac.getServiceApiUrl('uam'), '/subscriptions/email'].join('');

                $http.get(url, {})
                    .success(function (response) {
                        deferred.resolve(response);
                    })
                    .error(function (response) {
                        deferred.reject(response);
                    });

                return deferred.promise;
            },

            _setSubscriptions: function (email, postData) {
                var deferred = $q.defer();
                var url = [ConfigurationFac.getServiceApiUrl('uam'), '/subscriptions/email/', email].join('');

                $http.put(url, postData, {})
                    .success(function (response) {
                        deferred.resolve(response);
                    })
                    .error(function (response) {
                        deferred.reject(response);
                    });

                return deferred.promise;
            },

            _changeCommunicationsPreferences: function(emailAddress, item) {
                var url = CommunicationsPreferencesFac._getApiUrl('deposit', "subscriptionsPreferences");
                var deferred = $q.defer();
                var context = JSON.stringify(ConfigurationFac.getApplicationContext());

                var postData = {
                    emailAddress: emailAddress,
                    publicationId: item.ID,
                    enabled: item.Enabled
                };

                $http.post(url, postData, {
                        headers: {
                            'x-tvgcontext': context
                        }
                    }
                ).then(function (response) {
                        if (response.data && response.data.status === 'success') {
                            deferred.resolve(response.data);
                        } else {
                            deferred.reject(response.data);
                        }
                    }, function (e) {
                        deferred.reject(e.data);
                    });

                return deferred.promise;
            }
        };

        var userPreferencesFac = {
             setRequestBetConfirmation: function (isConfirmed) {
                var deferred = $q.defer();

                if (_.isBoolean(isConfirmed) === false) {
                    deferred.reject('Error: isConfirmed must be a boolean value.');
                } else {

                    var betConfirm = (isConfirmed == true) ? 1 : 0;

                    if($rootScope.activeFeatures.useUamPreferencesBetslip) {
                        var preference = PreferencesEntityBuilder()
                            .withDescription('show_bet_confirm')
                            .withMetadata(betConfirm)
                            .build();

                        PreferencesFac.updatePreferences(preference).then(function() {
                            deferred.resolve();
                        }, function() {
                            deferred.reject('Error: failed to updatePreferences.');
                        });

                    } else {
                        var prefObj = PreferencesCookieFac.getPreferences();
                        prefObj.show_bet_confirm = betConfirm;
                        PreferencesCookieFac.updatePreferences(prefObj)
                            .then(function(isConfirmed) {
                                deferred.resolve(isConfirmed);
                            }, function() {
                                deferred.reject('Error: failed to updatePreferences.');
                            });
                    }
                }

                return deferred.promise;
        }
    };

        return {
            pollBalance: BalanceFac.pollBalance,
            stopPollingBalance: BalanceFac.stopPollingBalance,
            getAccountBalance: BalanceFac.getAccountBalance,
            getAccountNumber: BalanceFac.getAccountNumber,
            getAccountBalanceData: BalanceFac.getAccountBalanceData,
            getVideoCountInfo: BalanceFac.getVideoCountInfo,
            updateAccountBalance: BalanceFac.updateAccountBalance,
            getCommunicationsPreferences: CommunicationsPreferencesFac._getCommunicationsPreferences,
            changeCommunicationsPreferences: CommunicationsPreferencesFac._changeCommunicationsPreferences,
            setRequestBetConfirmationPreference: userPreferencesFac.setRequestBetConfirmation,
            getSubscriptions: CommunicationsPreferencesFac._getSubscriptions,
            setSubscriptions: CommunicationsPreferencesFac._setSubscriptions
        };
    }

    UserProfileSvc.$inject = [
        '$http',
        '$q',
        '$rootScope',
        'poller',
        '$filter',
        'ConfigurationFac',
        'PreferencesCookieFac',
        'PreferencesFac'
    ];

    return UserProfileSvc;
});

modules/UserProfile/controllers/quickDepositCtrl.js
'use strict';

define(
        'QuickDepositCtrl',[
        ],
        function () {

            function QuickDepositCtrl($scope, $rootScope, $location, $uibModal) {

                $scope.depositSuccessData = null;
                $scope.isOpen = true;

                $scope.dismissNotification = function () {
                    $scope.msgHidden = true;
                };

                $scope.notify = function (type, message) {
                    $scope.msgType = type;
                    $scope.msgText = message;
                    $scope.msgHidden = false;
                };

                $scope.$on('logout', function () {
                    if ($scope.isOpen) {
                        $scope.isOpen = false;
                        $scope.$close();
                    }
                });

                $scope.dismissNotification();

                $scope.$on('onDepositSuccess', function (event, depositData) {
                    $scope.depositSuccessData = depositData;
                    if ($rootScope.hasOwnProperty('user') && $rootScope.user.hasOwnProperty('accountNumber')) {
                        $scope.depositSuccessData.accountNum = $rootScope.user.accountNumber;
                    }
                    $rootScope.$broadcast("accountBalance_update");
                });

                $scope.$on('onDepositError', function (event, errorMessageObj) {
                    $scope.depositSuccessData = null;
                    $scope.notify("error", errorMessageObj);
                });

                $scope.$on('onCloseSuccessWindow', function () {
                    $scope.isOpen = false;
                    $scope.$close();
                });

                var unbind = $rootScope.$on('onBinValidationFail', function(){
                    $scope.isOpen = false;
                    $scope.$close();

                    if($rootScope.productContext === "touch2") {
                        var depositTemplate = 'js/mobile/modules/Account/templates/account-deposit.html';
                        _openDepositOnTouch(depositTemplate, 'Deposit');
                    } else {
                        $location.path('/my-funds/deposit');
                    }

                });

                function _openDepositOnTouch(rootUrl, title) {
                    $uibModal.open({
                        windowClass: 'account',
                        backdropClass: 'tvgmodal-backdrop',
                        windowTemplateUrl: 'js/modules/Utilities/templates/modal-window.html',
                        template: '<stack-view data-root-url="' +
                        rootUrl + '" data-root-title="' + title + '"></stack-view>'
                    });
                }

                $scope.$on('$destroy',function(){
                   unbind();
                });

                $scope.events = {
                    close: function close(event) {
                        $scope.isOpen = false;
                        $scope.$close(event);
                    }
                };
            }

            QuickDepositCtrl.$inject = [
                '$scope',
                '$rootScope',
                '$location',
                '$uibModal'
            ];

            return QuickDepositCtrl;
        }
);

modules/UserProfile/providers/services/userBalanceSvc.js
'use strict';

define('UserBalanceSvc',[],function () {

    function UserBalanceSvc($rootScope, UserProfileSvc, $filter) {
        $rootScope.$on('accountBalance_update', _updateAccountBalance);
        $rootScope.$on('accountBalance_force_update', _forceBalaceUpdate);

        var balancePollerDeferred = null;

        function _forceBalaceUpdate($event, data) {
            _responseHandle(data);
        }

        function _startBalancePoller(){
            if (!balancePollerDeferred) {
                balancePollerDeferred = UserProfileSvc.pollBalance(false).then(null, function () {
                    _resetShowedBalance();
                }, function (response) {
                    _responseHandle(response);
                });
            }
        }

        function _stopBalancePoller(){
            if (balancePollerDeferred) {
                UserProfileSvc.stopPollingBalance(balancePollerDeferred);
                balancePollerDeferred = null;
            }
        }

        function _updateAccountBalance() {
            UserProfileSvc.getAccountBalance().then(function (response) {
                _responseHandle(response);
            }, function () {
                _resetShowedBalance();
            });
        }


        function _responseHandle(response) {
            if ((response && response.balance === 0) || (response && response.balance && !isNaN(response.balance))) {
                $rootScope.accountBalanceNumber = response.balance;
                $rootScope.accountBalance = $filter('currency')(response.balance, '$');
                $rootScope.$broadcast('accountBalance_changed');
            } else {
                _resetShowedBalance();
            }
        }

        function _resetShowedBalance() {
            $rootScope.accountBalanceNumber = null;
            $rootScope.accountBalance = null;
        }

    }

    UserBalanceSvc.$inject = [
        '$rootScope',
        'UserProfileSvc',
        '$filter'
    ];

    return UserBalanceSvc;
});

modules/UserProfile/userProfileMod.js
'use strict';

define(
    'UserProfile',[
        'UserProfileSvc',
        'QuickDepositCtrl',
        'UserBalanceSvc'
    ],

    function (UserProfileSvc,
              QuickDepositCtrl,
              UserBalanceSvc) {

        angular.module('TVG.UserProfile', ['TVG.Security'])

            .service('UserProfileSvc', UserProfileSvc)

            .service('UserBalanceSvc', UserBalanceSvc)

            .controller('QuickDepositCtrl', QuickDepositCtrl)

            .filter('trust', function ($sce) {
                return $sce.trustAsHtml;
            })

            .filter('startFrom', function () {
                return function (input, start) {
                    start = +start;
                    return input.slice(start);
                };
            });
    }
);

modules/Utilities/providers/factories/cookieFac.js
'use strict';

define('CookieFac',[
        'angularCookies',
        'angularUTF8Base64'
    ],
    function () {
        function CookieFac(base64, ipCookie, $window) {

            //'ipCookie',

            // this factory will take in a cookie name, and decode it and return the cookie object... too this factory will need to be able to set / update params on these cookies
            function _getCookie(cookieName) {
                var value = ipCookie(cookieName);
                if (!angular.isDefined(value)) {
                    return null;
                }
                return value;
            }

            function _setCookie(cookieName, cookieString, options) {
                return ipCookie(cookieName, cookieString, options);
            }

            function _removeCookie(key, options) {
                return ipCookie.remove(key, options);
            }

            function _getTVGFormatCookie(cookieName) {
                var returnData = {},
                    cookie = _getCookie(cookieName),
                    cookieData = cookie ? base64.decode(cookie).split(';') : [];

                angular.forEach(cookieData, function (key) {
                    var tmp = key.split('=');
                    if (tmp[0] != undefined && tmp[0]) {
                        returnData[tmp[0]] = tmp[1];
                    }
                });

                return returnData;
            }

            // Set values to null to remove them from the cookie
            function _setTVGFormatCookieValue(cookieName, keyValueObject) {
                var cookieData = _getTVGFormatCookie(cookieName);

                if (keyValueObject === null || keyValueObject === undefined || !angular.isObject(keyValueObject) || typeof keyValueObject !== 'object') {
                    return false;
                }

                angular.extend(cookieData, keyValueObject);

                var newString = _convertCookieData(cookieData);

                return _setCookie(cookieName, base64.encode(newString), {path: '/'});
            }

            function _convertCookieData(keyValueObject) {
                var tmp = '';
                angular.forEach(keyValueObject, function (value, key) {
                    tmp += key + '=' + value + ';';
                });

                return tmp;
            }

            function _setEncodedCookie(cookieName, value, options) {
                var encodedValue = base64.encode(value);
                _setCookie(cookieName, encodedValue, options);
            }

            function _getEncodedCookie(cookieName) {
                var value = _getCookie(cookieName);
                if (value) {
                    return base64.decode(value);
                }
                return value;
            }

            /**
             * Calculate the correct domain for cookies, so it matches with the value
             * set by the server in Tvg\Util\Cookie::getDomain().
             * If we fail to set the correct domain, we will end up with repeated
             * cookies with different domains (causing some bugs in QA and other envs)
             *
             * 1) betfair domains -> get all parts except the first
             * 2) others -> get the last two domain parts
             *
             * see more:
             * /tvg3/library/Tvg/Util/Cookie.php
             *
             * @param {String}  [hostname] Current hostname
             * @return {String}            Cookie's domain
             */
            function _extractDomain(hostname) {
                var host = hostname || $window.location.hostname || '';
                var isBetfair = !!host.match(/betfair\./);
                var domain = '';

                if (isBetfair) {
                    domain = host.split('.').splice(1).join('.');
                } else {
                    domain = host.split('.').splice(-2, 2).join('.');
                }

                return domain;
            }

            return {
                getCookie: _getCookie,
                setCookie: _setCookie,
                removeCookie: _removeCookie,
                getTVGFormatCookie: _getTVGFormatCookie,
                setTVGFormatCookieValue: _setTVGFormatCookieValue,
                getEncodedCookie: _getEncodedCookie,
                setEncodedCookie: _setEncodedCookie,
                extractDomain: _extractDomain
            };
        }

        CookieFac.$inject = [
            'base64',
            'ipCookie',
            '$window'

        ];

        return CookieFac;
    });

modules/Utilities/providers/factories/localStorageFac.js
'use strict';

/**
 * A simple angular factory to interact with native html5 localStorage service.
 */
define('LocalStorageFac',[
        'angularUTF8Base64'
    ],
    function () {
        function LocalStorageFac(base64) {
            function _getItem(key) {
                var value;

                try {
                    value = localStorage.getItem(key);
                } catch(e) {
                    return null;
                }

                if (!value) {
                    return null;
                }

                return value;
            }

            function _setItem(key, value) {
                try {
                    localStorage.setItem(key, value);
                } catch (e) {
                    return false;
                }
            }

            function _removeItem(key) {
                return localStorage.removeItem(key);
            }

            function _setEncodedItem(key, value) {
                var encodedValue = base64.encode(value);
                _setItem(key, encodedValue);
            }

            function _getEncodedItem(key) {
                var value = _getItem(key);

                if (value) {
                    return base64.decode(value);
                }

                return null;
            }

            return {
                getItem: _getItem,
                setItem: _setItem,
                removeItem: _removeItem,
                getEncodedItem: _getEncodedItem,
                setEncodedItem: _setEncodedItem
            };
        }

        LocalStorageFac.$inject = [
            'base64'
        ];

        return LocalStorageFac;
    });

modules/Utilities/providers/factories/statePersistenceFac.js
'use strict';

define('StatePersistenceFac',[],
    function () {
        function StatePersistenceFac($rootScope, $location) {

            var _state = {},
                _sessionState = {},
                _prevLocation = $location.path();

            $rootScope.$on('$viewContentLoaded', function () {
                if (_prevLocation != $location.path()) {
                    _state = {};

                    if ($rootScope.raceInfoModal) {
                        $rootScope.raceInfoModal.close();
                        $rootScope.raceInfoModal = null;
                    }
                }
                _prevLocation = $location.path();
            });

            function saveState(key, value, session) {
                if (session) {
                    _sessionState[key] = value;
                } else {
                    _state[key] = value;
                }
            }

            function loadState(key, session) {
                if (session) {
                    return _sessionState[key];
                } else {
                    return _state[key];
                }
            }

            function resetState(key, session) {
                if (session) {
                    _sessionState[key] = null;
                } else {
                    _state[key] = null;
                }
            }

            return {
                saveState: saveState,
                loadState: loadState,
                resetState: resetState
            };
        }

        StatePersistenceFac.$inject = ['$rootScope', '$location'];

        return StatePersistenceFac;
    }
);
modules/Utilities/providers/factories/preferencesCookieFac.js
'use strict';

define('PreferencesCookieFac',[],
    function () {
        function PreferencesCookieFac(CookieFac, $http, $q, $rootScope, $cookies, LoginBehaviourConst, PreferencesFac) {
            var cookieName = 'TVGPrefs',
                prefsCookie;

            $rootScope.$watch(function () {
                return $cookies.get('TVGPrefs');
            }, function (newValue, oldValue) {
                if (angular.equals(newValue, oldValue)) {
                    return;
                }

                prefsCookie = null;
                _getPreferences();

                $rootScope.$broadcast('preferencesUpdated', prefsCookie);
            });

            function _getPreferences() {
                if (angular.isObject(prefsCookie)) {
                    return prefsCookie;
                }

                prefsCookie = {
                    rewards_updated: '',
                    balance_updated: '',
                    userVideo_updated: '',

                    balance_is_shown: 0,
                    bet_amount: 2.0,  //Full Bet Ticket
                    bet_type: 10,    //Full Bet Ticket
                    bet_amount_quick: 2.0, //Quick Bet Ticket
                    bet_type_quick: 10,   //Quick Bet Ticket
                    show_bet_confirm: 1,
                    home_show_races_by: 'featured',
                    home_sort_runners_by: 'odds',
                    bet_prefs: {
                        defaultBetType: "10",
                        default_bet_amount:{
                            10: "0.00",
                            20: "0.00",
                            30: "0.00",
                            110: "0.00",
                            160: "0.00",
                            210: "0.00",
                            260: "0.00",
                            "P": "0.00"
                        },
                        useCustomBetAmount: false,
                        useMinimumBetAmount: true
                    },
                    betTicketWidth: '',
                    betTicketHeight: '',
                    classic_bt: '',
                    qdAmount: '',
                    qdPayment: '',
                    wager_status: '',
                    user_id: '',
                    user_email: '',
                    state: '',
                    signal_provider: '',
                    transport_id: '',
                    loginType: '',
                    authed_cachebust: '',
                    lastActivity: '',
                    currentTrack: '',
                    currentRace: '',
                    currentPerf: '',
                    ppTimerSync: '',
                    homepageLoginBehaviour: LoginBehaviourConst.HOMEPAGE,

                    fav_filter: '',
                    us_filter: '',
                    thoroughbred_filter: '',
                    harness_filter: ''
                };

                var tmpCookie = CookieFac.getTVGFormatCookie(cookieName);

                angular.extend(prefsCookie, tmpCookie);

                if (prefsCookie.bet_type == '' || isNaN(prefsCookie.bet_type)) {
                    prefsCookie.bet_type = 10; //Default to Win.
                } else {
                    prefsCookie.bet_type = Number(prefsCookie.bet_type);
                }

                if (prefsCookie.bet_amount === '' || isNaN(prefsCookie.bet_amount)) {
                    prefsCookie.bet_amount = 2.0; //Default to $2.
                } else {
                    prefsCookie.bet_amount = Number(prefsCookie.bet_amount);
                }

                if (prefsCookie.bet_type_quick === '' || isNaN(prefsCookie.bet_type_quick)) {
                    prefsCookie.bet_type_quick = 10; //Default to Win.
                } else {
                    prefsCookie.bet_type_quick = Number(prefsCookie.bet_type_quick);
                }

                if (prefsCookie.bet_amount_quick === '' || isNaN(prefsCookie.bet_amount_quick)) {
                    prefsCookie.bet_amount_quick = 2.0; //Default to $2.
                } else {
                    prefsCookie.bet_amount_quick = Number(prefsCookie.bet_amount_quick);
                }

                if (prefsCookie.home_sort_runners_by === '' ||
                    (prefsCookie.home_sort_runners_by.toLowerCase() != 'odds' && prefsCookie.home_sort_runners_by.toLowerCase() != 'number')) {
                    prefsCookie.home_sort_runners_by = 'odds';
                }

                if (prefsCookie.home_show_races_by === '' ||
                    (prefsCookie.home_show_races_by.toLowerCase() != 'featured' && prefsCookie.home_show_races_by.toLowerCase() != 'favorites' && prefsCookie.home_show_races_by.toLowerCase() != 'all')) {
                    prefsCookie.home_show_races_by = 'featured';
                }

                if (prefsCookie.show_bet_confirm === '' || isNaN(prefsCookie.show_bet_confirm)) {
                    prefsCookie.show_bet_confirm = 1;
                } else {
                    prefsCookie.show_bet_confirm = Number(prefsCookie.show_bet_confirm);
                }

                if (prefsCookie.balance_is_shown === '' || isNaN(prefsCookie.balance_is_shown)) {
                    prefsCookie.balance_is_shown = 1;
                } else {
                    prefsCookie.balance_is_shown = Number(prefsCookie.balance_is_shown);
                }

                prefsCookie.fav_filter = (prefsCookie.fav_filter === '' || isNaN(prefsCookie.fav_filter)) ? 0 : Number(prefsCookie.fav_filter);
                prefsCookie.us_filter = (prefsCookie.us_filter === '' || isNaN(prefsCookie.us_filter)) ? 0 : Number(prefsCookie.us_filter);
                prefsCookie.thoroughbred_filter = (prefsCookie.thoroughbred_filter === '' || isNaN(prefsCookie.thoroughbred_filter)) ? 0 : Number(prefsCookie.thoroughbred_filter);
                prefsCookie.harness_filter = (prefsCookie.harness_filter === '' || isNaN(prefsCookie.harness_filter)) ? 0 : Number(prefsCookie.harness_filter);

                return prefsCookie;
            }

            function _updatePreferences(keyValueObject) {
                var deferred = $q.defer();

                CookieFac.setTVGFormatCookieValue(cookieName, keyValueObject);

                $http({
                    method: 'GET',
                    url: "/ajax/preferences/update/preferencesdata"
                }).success(function (response) {
                    deferred.resolve(response);
                }).error(function (response) {
                    deferred.reject(response);
                });

                return deferred.promise;
            }


            function _getBetAmounts() {
                return [
                    {name: "$0.10", value: 0.1},
                    {name: "$0.20", value: 0.2},
                    {name: "$1.00", value: 1.0},
                    {name: "$2.00", value: 2.0},
                    {name: "$3.00", value: 3.0},
                    {name: "$4.00", value: 4.0},
                    {name: "$5.00", value: 5.0},
                    {name: "$10.00", value: 10.0},
                    {name: "$15.00", value: 15.0},
                    {name: "$20.00", value: 20.0},
                    {name: "$25.00", value: 25.0},
                    {name: "$50.00", value: 50.0},
                    {name: "$100.00", value: 100.0},
                    {name: "$150.00", value: 150.0},
                    {name: "$200.00", value: 200.0},
                    {name: "$250.00", value: 250.0},
                    {name: "$500.00", value: 500.0},
                    {name: "$1,000.00", value: 1000.0}
                ];
            }

            function _getShowRacesBy() {
                return ["Featured", "Favorites", "All"];
            }

            function _getSortRacesBy() {
                return ["Odds", "Number"];
            }

            function _getBetAmount() {
                return _getPreferences().bet_amount;
            }

            function _getBetType() {
                return _getPreferences().bet_type;
            }

            PreferencesCookieFac.$inject = [
                'CookieFac',
                '$http',
                '$q',
                '$rootScope',
                '$cookies',
                'LoginBehaviourConst'
            ];

            return {
                getPreferences: _getPreferences,
                updatePreferences: _updatePreferences,
                getBetAmounts: _getBetAmounts,
                getShowRacesBy: _getShowRacesBy,
                getSortRacesBy: _getSortRacesBy,
                getBetAmount: _getBetAmount,
                getBetType: _getBetType
            };
        }

        return PreferencesCookieFac;
    });

modules/Utilities/tools/raceMtpDisplay.js
'use strict';
//TODO we need to select only one way to handle times and dates
define('RaceMtpDisplay',[], function () {

    return function () {
        return {
            calcMtpDisplay: function (postTime, raceMtp) {
                var mtp = raceMtp;

                function timeText() {
                    if (mtp <= 120) {
                        return mtp + ' MTP';
                    }
                    return moment(postTime).format('hh:mm A');
                }

                function getMtpStatus() {
                    var mtpStatusValues = ['near', 'med', 'far', 'time-format'];
                    if (mtp <= 5) {
                        return mtpStatusValues[0];
                    } else if (mtp <= 15) {
                        return mtpStatusValues[1];
                    } else if (mtp <= 120) {
                        return mtpStatusValues[2];
                    }

                    return mtpStatusValues[3];
                }

                return {
                    mtpStatus: getMtpStatus(),
                    timeText: timeText()
                };
            }
        };

    };
});

modules/Utilities/providers/factories/favoriteCookieFac.js
'use strict';

define('FavoriteCookieFac',[
        'CookieFac'
    ],
    function () {
        function FavoriteCookieFac(
                base64,
                CookieFac,
                $http,
                $q,
                $window
            ) {
            var COOKIE_NAME = 'TVG_favorite_tracks';

            function _getFavoriteTrackList() {
                var favCookie = {
                    track_abrev_list: []
                };

                var tmpCookie = CookieFac.getCookie(COOKIE_NAME);

                if (tmpCookie) {
                    try {
                        var decodedFavList = base64.decode(tmpCookie);
                        favCookie.track_abrev_list = decodedFavList.split(',');
                    }
                    catch (e) {
                        favCookie.track_abrev_list = [];
                    }
                }
                return favCookie;
            }

            /**
             * Convert the favorites tracks abbreviations array into a
             * base 64 encoded list string (separated by commas).
             *
             * @example
             * _updateFavoriteTrackList(['HKG', 'LKJ']) -> 'SEtHLExLSg=='
             *
             * @param {Array}  newFavTrackAbrevList  Array of favorites tracks abbreviations
             * @param {Object}                       Cookie key, name and options
             */
            function _updateFavoriteTrackList(newFavTrackAbrevList) {
                var decoded = (newFavTrackAbrevList || []).filter(function (fav) {
                    return (fav && fav !== 'undefined');
                }).join(',');

                var key = COOKIE_NAME;
                var value = base64.encode(decoded);

                return CookieFac.setCookie(key, value, {
                    path: '/',
                    domain: CookieFac.extractDomain($window.location.hostname),
                    Session: true
                });
            }

            function _storeFavoriteTrackList() {
                var deferred = $q.defer();

                $http({
                    method: 'GET',
                    url: "/ajax/preferences/update/favoriteData"
                }).success(function (response) {
                    deferred.resolve(response);
                }).error(function (response) {
                    deferred.reject(response);
                });

                return deferred.promise;
            }

            return {
                getFavoriteTrackList: _getFavoriteTrackList,
                updateFavoriteTrackList: _updateFavoriteTrackList,
                storeFavoriteTrackList: _storeFavoriteTrackList
            };
        }

        FavoriteCookieFac.$inject = [
            'base64',
            'CookieFac',
            '$http',
            '$q',
            '$window'
        ];

        return FavoriteCookieFac;
    });

modules/Utilities/providers/service/featuresHandlerSvc.js
"use strict";

define('FeaturesHandlerSvc',[],function () {

        function FeaturesHandlerSvc(FeaturesFac, UserPropertiesSvc, $rootScope) {

            var self = this;
            self.features = {
                activeFeatures: undefined
            };

            function _setActiveFeatures() {
                var userProperties = UserPropertiesSvc.getUserProperties();
                self.features.activeFeatures = FeaturesFac.getFeatures(userProperties);
                $rootScope.featureOverridesEnabled = FeaturesFac.areOverridesEnabled();
                $rootScope.activeFeatures = self.features.activeFeatures;
            }

            function _overrideFeatures() {
                FeaturesFac.setFeatures(self.features.activeFeatures);
                $rootScope.activeFeatures = self.features.activeFeatures;
            }

            function _changeFeatureState(featureName, featureState) {
                self.features.activeFeatures[featureName] = featureState;
            }

            function _getFeatures() {
                return self.features;
            }

            //listeners
            $rootScope.$on("logout", function () {
                _setActiveFeatures();
            });
            $rootScope.$on("user", function () {
                _setActiveFeatures();
            });
            // when user logs in or he already has a valid session
            $rootScope.$on("invalidSession", function () {
                _setActiveFeatures();
            });

            //public members
            this.overrideFeatures = _overrideFeatures;
            this.changeFeatureState = _changeFeatureState;
            this.getFeatures = _getFeatures;
            this.init = _setActiveFeatures;
        }

        FeaturesHandlerSvc.$inject = [
            'FeaturesFac',
            'UserPropertiesSvc',
            '$rootScope'
        ];

        return FeaturesHandlerSvc;

    }
);

modules/Utilities/providers/service/userPropertiesSvc.js
'use strict';

define('UserPropertiesSvc',[],function() {
        function UserPropertiesSvc ($routeParams, $rootScope, $document) {

            // User properties builder

            var userPropertiesBuilder = function() {
                var userProperties = {};
                var gears = [];

                return {
                    build: function () {
                        gears.forEach(function (propertyBuilder) {
                            propertyBuilder(userProperties);
                        });
                        return userProperties;
                    },

                    addPropertyGear: function (propertyBuilder) {
                        gears.push(propertyBuilder);
                        return this;
                    }
                };
            };

            function isUserDefined(user) {
                return user != undefined;
            }

            function isUserHomeAddressDefined(user) {
                return isUserDefined(user) && user.homeAddress != undefined;
            }

            // Properties gears

            function referrerGear(userProperties) {
                var parser = document.createElement('a');
                parser.href = $document.referrer;
                userProperties.referrer = parser.hostname;
            }

            function accountIdGear(userProperties) {
                if (isUserDefined($rootScope.user)) {
                    userProperties.accountId = $rootScope.user.accountNumber;
                }
            }

            function stateGear(userProperties) {
                if (isUserHomeAddressDefined($rootScope.user)) {
                    userProperties.residence = $rootScope.user.homeAddress.StateAbbr;
                }
            }

            function promotionGear(userProperties) {
                var promoCode = _.get($routeParams, 'promoCode');
                if (!_.isUndefined(promoCode)) {
                    userProperties.promoCode = promoCode;
                }
            }

            this.getUserProperties = function () {
                return userPropertiesBuilder()
                    .addPropertyGear(referrerGear)
                    .addPropertyGear(accountIdGear)
                    .addPropertyGear(stateGear)
                    .addPropertyGear(promotionGear)
                    .build();
            };

        }

        UserPropertiesSvc.$inject = [
            '$routeParams',
            '$rootScope',
            '$document'
        ];

        return UserPropertiesSvc;
    });
modules/Utilities/providers/factories/wagerProfileFac.js
'use strict';

define('WagerProfileFac',['lodash'], function (_) {

        /**
         * Wager profile factory, used to get/set the wager profile,
         * using user's cookies and hostname information.
         *
         * NOTE: The wager profiles in .net API seem to be missing NJ,
         * PA and IA...
         *
         * Wager profiles form .net API:
         * (Tvg.Api/Tvg.Api.Entities/UserProfile.cs)
         *
         * PORT-Generic
         * PORT-CA
         * PORT-LA
         * PORT-MD
         * PORT-NM
         * PORT-OK
         * PORT-MA
         * PORT-NY
         * PORT-VA
         * PORT-FL
         * PORT-MT
         * PORT-NH
         * PORT-IL
         * PORT-AllTracks
         *
         */
        function WagerProfileFac($rootScope, $location, TvgHostsFac, CookieFac) {

            var WP_COOKIE = 'wp';
            var PROFILES = {
                TVG: 'PORT-Generic',
                NJ: 'PORT-NJ',
                IA: 'PORT-IA',
                PA: 'PORT-PA',
                ALL_TRACKS: 'PORT-AllTracks' // used before user logs in
            };


            /**
             * Get user's wager profile (from cookies).
             * If there's no wp in coookies, a default wager profile will
             * be returned (according hostname or opts.defaultWagerProfile,
             * if set).
             *
             * @param {Object} [opts]                      Options
             * @param {String} [opts.authentication]       Must be logged in to use the WP from cookies
             * @param {String} [opts.defaultWagerProfile]  Fallback default wager profile
             *
             * @type {String} Wager profile
             */
            function getWagerProfile(opts) {
                opts = opts || {};

                var wp = CookieFac.getCookie(WP_COOKIE);

                // fallback to default wager profile (set by user or from host)
                return wp || opts.defaultWagerProfile || getWagerProfileFromHost();
            }

            /**
             * Get wager profile from cookies, if the session has already
             * started. Fallbacks to "AllTracks" wager profile.
             *
             * @return {String} Wager profile
             */
            function getSessionOrAllTracksProfile() {
                return getWagerProfile({
                    authentication: true,
                    defaultWagerProfile: PROFILES.ALL_TRACKS
                });
            }

            /**
             * Get wager profile from cookies, if the session has already
             * started. Fallbacks to "PORT-Generic" wager profile.
             *
             * @return {String} Wager profile
             */
            function getSessionOrGenericProfile() {
                return getWagerProfile({
                    authentication: true,
                    defaultWagerProfile: PROFILES.TVG
                });
            }

            /**
             * Get default wager profile accoring to the hostname
             * @type {String} Default wager profile
             */
            function getWagerProfileFromHost() {
                var host = $location.host();
                var profiles = [
                    { equalsHost: TvgHostsFac.isNJ,  value: PROFILES.NJ },
                    { equalsHost: TvgHostsFac.isPA,  value: PROFILES.PA },
                    { equalsHost: TvgHostsFac.isIA,  value: PROFILES.IA },
                    { equalsHost: TvgHostsFac.isTVG, value: PROFILES.TVG }
                ];
                var profile = _.find(profiles, function (profile) {
                    var isOk = profile.equalsHost(host);
                    return isOk;
                });

                return profile ?
                    profile.value : PROFILES.TVG;
            }

            /**
             * Set user's wager profile (in cookies)
             * @param {String} wp  New wager profile
             */
            function setWagerProfile(wp) {
                CookieFac.setCookie(WP_COOKIE, wp);
                return;
            }

            /**
             * Clear user's wager profile (from cookies)
             */
            function clearWagerProfile() {
                CookieFac.removeCookie(WP_COOKIE);
                return;
            }


            // exports
            return {
                PROFILES: PROFILES,
                getWagerProfile: getWagerProfile,
                getSessionOrAllTracksProfile: getSessionOrAllTracksProfile,
                getSessionOrGenericProfile: getSessionOrGenericProfile,
                getWagerProfileFromHost: getWagerProfileFromHost,
                setWagerProfile: setWagerProfile,
                clearWagerProfile: clearWagerProfile
            };
        }

        WagerProfileFac.$inject = [
            '$rootScope',
            '$location',
            'TvgHostsFac',
            'CookieFac'
        ];

        return WagerProfileFac;
    });

modules/Utilities/providers/factories/tvgHostsFac.js
'use strict';

define('TvgHostsFac',['lodash'], function (_) {

        /**
         * @TODO move this to configuration repository!
         *
         * Factory to check if a hostname matches any of TVG products
         */
        function TvgHostsFac() {

            /**
             * Is the host from NJ?
             *
             * NOTE: if your local development host is different,
             * this may not work properly!
             *
             * @param  {String}  host  Host to check
             * @return {Boolean}       Is a NJ host
             */
            function isNJ(host) {

                return _containsHost(host, [
                    '4njbets.dev.tvg.com',
                    '4njbets.qa.us.betfair.local',
                    '4njbets-qa.us.betfair.local',
                    '4njbets-qa.us.betfair.com',
                    '4njbets.stage.us.betfair.local',
                    '4njbets-staging.us.betfair.local',
                    '4njbets-staging.us.betfair.com',
                    '4njbets.us.betfair.com'
                ]);
            }

            /**
             * Is the host from PA?
             *
             * NOTE: if your local development host is different,
             * this may not work properly!
             *
             * @param  {String}  host  Host to check
             * @return {Boolean}       Is a PA host
             */
            function isPA(host) {

                return _containsHost(host, [
                    'pabets.dev.tvg.com',
                    'pabets.qa.tvg.com',
                    'pabets-qa.tvg.com',
                    'pabets.stage.tvg.com',
                    'pabets-staging.tvg.com',
                    'pabets.tvg.com'
                ]);
            }

            /**
             * Is the host from IA?
             *
             * NOTE: if your local development host is different,
             * this may not work properly!
             *
             * @param  {String}  host  Host to check
             * @return {Boolean}       Is a IA host
             */
            function isIA(host) {

                return _containsHost(host, [
                    'ia.dev.tvg.com',
                    'ia.qa.tvg.com',
                    'ia-qa.tvg.com',
                    'ia.stage.tvg.com',
                    'ia-staging.tvg.com',
                    'ia.tvg.com'
                ]);
            }

            /**
             * Is the host from generic TVG?
             *
             * NOTE: if your local development host is different,
             * this may not work properly!
             *
             * @param  {String}  host  Host to check
             * @return {Boolean}       Is a TVG host
             */
            function isTVG(host) {

                return _containsHost(host, [
                    'tvg4.dev.tvg.com',
                    'touch.dev.tvg.com',
                    'spl.dev.tvg.com',
                    'spl.qa.tvg.com',
                    'stage.tvg.com',
                    'touch.tvg.com',
                    'us.tvg.com',
                    'www-qa.tvg.com',
                    'www-staging.tvg.com',
                    'www.tvg.com'
                ]);
            }

            /**
             * Check if a host is inside a list of hosts
             * (doesn't have to be an exact match!)
             *
             * @param  {String} host  Host to find
             * @param  {List}   list  List of hosts to look into
             * @return {Boolean}      Is the host in the list?
             */
            function _containsHost(host, list) {
                host = (host || '').toLowerCase();
                list = list || [];

                return !!_.find(list, function (tvgHost) {
                    tvgHost = (tvgHost || '').toLowerCase();
                    return host.indexOf(tvgHost) != -1;
                });
            }


            // exports
            return {
                isNJ: isNJ,
                isPA: isPA,
                isIA: isIA,
                isTVG: isTVG,
                _containsHost: _containsHost
            };
        }

        // TvgHostsFac.$inject = [];

        return TvgHostsFac;
    });

modules/Utilities/providers/factories/newWindowGridFac.js
'use strict';

define('NewWindowGridFac',[],
    function () {
        function NewWindowGridFac() {
            var windowID = 0;
            var windowWidth = 470; // default value plus some margin
            var windowHeight = 870; // default value plus some margin

            function _generateWindowID() {
                return ++windowID + "";
            }

            // run on new child init
            function _onChildInit(window, newWindow) {
                window.referenceWindow.addNewWindow(newWindow);
            }

            //handle events received by reference window
            function _referenceWindowEvent(referenceWindow) {
                var eventType = referenceWindow.addEventListener ? "addEventListener" : "attachEvent";
                var addEvent = referenceWindow[eventType];
                addEvent("message", function (e) {
                    if (e.origin === referenceWindow.location.origin) {
                        if (referenceWindow.newWindowColumnIndex < referenceWindow.numberOFWindowsPerRow && referenceWindow.newWindowColumnIndex > 0) {
                            referenceWindow.newWindowColumnIndex--;
                        }
                        _.remove(referenceWindow.childWindows, function (windowInstance) {
                            return (windowInstance.ID === e.data.substring(17, e.data.length) || windowInstance.window === null);
                        });
                    }
                }, false);
            }

            //add new child to reference window list
            function _addNewWindow(window) {
                return function (windowRef) {
                    window.childWindows.push(windowRef);
                };
            }

            //close event for child windows
            function _onCloseEvent(window) {
                return function () {
                    window.referenceWindow.postMessage("destroy-message: " + window.ID, window.location.origin);
                };
            }

            //inject function on reference window
            function _referenceWindowFunctions(window) {
                window.referenceWindow = window;
                window.generateID = _generateWindowID;
                window.childWindows = [];
                window.addNewWindow = _addNewWindow(window);
                _referenceWindowEvent(window);
            }

            //inject function on child window
            function _childWindowFunctions(window) {
                window.referenceWindow = window.opener.referenceWindow;
                window.ID = window.referenceWindow.generateID();
                window.addEventListener('unload', _onCloseEvent(window));
            }

            //identify the type of window
            function _windowFunction(window) {
                try {
                    if (window.opener && window.opener.referenceWindow) {
                        _childWindowFunctions(window);
                    } else {
                        throw "cannot access window";
                    }
                } catch (e) {
                    _referenceWindowFunctions(window);
                    _calculateGrid(window);
                }
            }

            //calculate grid of the screen
            function _calculateGrid(referenceWindow) {
                referenceWindow.numberOFWindowsPerRow = Math.floor(referenceWindow.screen.width / windowWidth);
                referenceWindow.numberOFWindowsPerColumn = Math.floor(referenceWindow.screen.height / windowHeight);
                referenceWindow.newWindowRowIndex = 0;
                referenceWindow.newWindowColumnIndex = 0;
                referenceWindow.topScreenValue = referenceWindow.screen.availTop;
                referenceWindow.leftScreenValue = referenceWindow.screen.availLeft;
                referenceWindow.widthScreenValue = referenceWindow.screen.width;
                referenceWindow.heightScreenValue = referenceWindow.screen.height;
            }

            // select reference window and return open coordinates
            function _getOpenCoordinates(window) {
                return _getCoordinates(window.referenceWindow);
            }

            // get coordinates based on master window
            function _getCoordinates(referenceWindow) {
                if (referenceWindow.topScreenValue != referenceWindow.screen.availTop ||
                    referenceWindow.leftScreenValue != referenceWindow.screen.availLeft ||
                    referenceWindow.widthScreenValue != referenceWindow.screen.width ||
                    referenceWindow.heightScreenValue != referenceWindow.screen.height) {
                    _calculateGrid(referenceWindow);
                }

                var coordinates = {top: referenceWindow.topScreenValue, left: referenceWindow.leftScreenValue};

                if (referenceWindow.newWindowColumnIndex < referenceWindow.numberOFWindowsPerRow) {
                    coordinates = _coordinates(referenceWindow);
                    referenceWindow.newWindowColumnIndex++;
                } else if (referenceWindow.newWindowRowIndex + 1 < referenceWindow.numberOFWindowsPerColumn) {
                    referenceWindow.newWindowColumnIndex = 0;
                    referenceWindow.newWindowRowIndex++;
                    coordinates = _coordinates(referenceWindow);
                    referenceWindow.newWindowColumnIndex++;
                } else {
                    referenceWindow.newWindowColumnIndex = 0;
                    referenceWindow.newWindowRowIndex = 0;
                    coordinates = _coordinates(referenceWindow);
                    referenceWindow.newWindowColumnIndex++;
                }

                return coordinates;
            }

            function _getTopCoordinates(referenceWindow) {
                if (referenceWindow.topScreenValue != referenceWindow.screen.availTop ||
                    referenceWindow.leftScreenValue != referenceWindow.screen.availLeft ||
                    referenceWindow.widthScreenValue != referenceWindow.screen.width ||
                    referenceWindow.heightScreenValue != referenceWindow.screen.height) {
                    _calculateGrid(referenceWindow);
                }

                var coordinates = {top: referenceWindow.topScreenValue, left: referenceWindow.leftScreenValue};
                coordinates = _coordinates(referenceWindow);

                return coordinates;

            }

            // set coordinates
            function _coordinates(referenceWindow) {
                var coordinates = {};
                coordinates.top = referenceWindow.topScreenValue + referenceWindow.newWindowRowIndex * windowHeight;
                coordinates.left = referenceWindow.leftScreenValue + referenceWindow.newWindowColumnIndex * windowWidth;
                return coordinates;
            }

            //setter for height
            function _setBetSlipWindowHeight(value) {
                if (value) {
                    windowHeight = value;
                }
            }

            //setter for width
            function _setBetSlipWindowWidth(value) {
                if (value) {
                    windowWidth = value;
                }
            }

            return {
                windowFunctions: _windowFunction,
                onChildInit: _onChildInit,
                calculateGrid: _calculateGrid,
                getOpenCoordinates: _getOpenCoordinates,
                getTopCoordinates: _getTopCoordinates,
                setBetSlipWindowHeight: _setBetSlipWindowHeight,
                setBetSlipWindowWidth: _setBetSlipWindowWidth
            };
        }

        return NewWindowGridFac;
    });

modules/Utilities/providers/factories/amountOptionsFac.js
'use strict';

define('AmountOptionsFac',['lodash'],
    function (_) {
        function AmountOptionsFac(METADATA, trackSvc) {

            function _removeOtherAmountOptionForHKRaces(currentRace) {
                return function (item) {
                    var allTracks = METADATA.allTracks || [];
                    var trackAbbr = currentRace.trackAbbr;

                    /**
                     *  Due to some inconsistencies on METADATA, we need to guarantee that these tracks abbreviations
                     *  do not have otherAmount displayed for the users even if it they are not present on METADATA
                     */
                    var isHK = _.isUndefined(allTracks[trackAbbr]) ? trackSvc.isHongKongRace(trackAbbr) : trackSvc.isTrackFromHongKong(allTracks[trackAbbr]);

                    return !(isHK && (item.amountString === 'other' || item.amount === null));
                };
            }

            function _roundAmountToTwoDecimalPlaces(amount) {
                return amount % 1 ? (Math.round(amount * 100) / 100) : amount;
            }

            /**
             * @returns {number} 0 if both values are equal. <0 if first value is lesser than the second or >0 if the first value is greater than second value.
             */
            function _compareAmounts(firstAmount, secondAmount) {
                return (typeof firstAmount === 'string' ? parseFloat(firstAmount) : firstAmount) -
                    (typeof secondAmount === 'string' ? parseFloat(secondAmount) : secondAmount);
            }

            /**
             * Given an upward sorted array and an index check the index value and the index's siblings to see
             * which one is equal or is the closest to the provided element.
             *
             * If the difference between two indexes and the value is the same,
             * e.g. idx1 = 1.3, idx2 = 2.6, value = 1.95, then we return the index of the sibling with the
             * highest value, e.g. idx2.
             *
             * @param {Array} array An upward sorted list of elements that contain a property (propertyName) with
             * the value to compare.
             * @param {Object} element The element that contains a property (propertyName) with the value to compare.
             * @param {Number} idx The index of the array where to start the comparison.
             * @param {String} propertyName The name of the property that contains the value to compare.
             * @returns {Number} The index of the array that has the same value of the element or the index with
             * the closest value. Returns -1 if, at least, one of the parameters is not valid.
             */
            function _getIdxOfTheClosestOrEqualElement(array, element, idx, propertyName) {
                var compareResult;

                if (!array.length || !array[idx] || !element || isNaN(parseInt(idx, 10)) || idx < 0 ||
                    idx >= array.length || typeof propertyName !== 'string' || !propertyName.length) {
                    return -1;
                }

                compareResult = _compareAmounts(array[idx][propertyName], element[propertyName]);
                if (compareResult > 0) {
                    if (idx === 0) {
                        return idx;
                    }
                    // Check the previous index
                    // In case of a subtraction that returns a decimal value between 0 and 1 we need this arithmetic processing
                    // to get these decimal values with just two places.
                    // This is used to avoid the problem with the subtraction between floating point values.
                    if (_roundAmountToTwoDecimalPlaces(element[propertyName] - array[idx - 1][propertyName]) <
                        _roundAmountToTwoDecimalPlaces(array[idx][propertyName] - element[propertyName])) {
                        return (idx - 1);
                    }
                    return idx;
                }
                if (compareResult < 0) {
                    if (idx === (array.length - 1)) {
                        return idx;
                    }
                    // Check the following index
                    // In case of a subtraction that returns a decimal value between 0 and 1 we need this arithmetic processing
                    // to get these decimal values with just two houses.
                    // This is used to avoid the problem with the subtraction between floating point values.
                    if (_roundAmountToTwoDecimalPlaces(array[idx + 1][propertyName] - element[propertyName]) <
                        _roundAmountToTwoDecimalPlaces(element[propertyName] - array[idx][propertyName])) {
                        return (idx + 1);
                    }
                    return idx;
                }

                return idx;
            }

            /**
             * Gets the object from the array that is the closest, or equal, to the one provided.
             * The value to be compared/found is extracted from the objects using the value of the
             * "propertyName" parameter.
             * A binary search is used to find the provided value in the upward sorted array.
             *
             * @param {Object} amount The object that contains the "propertyName" property.
             * The value of this property should be a Number or a String that contains a number.
             * @param {Array} amounts An upward sorted array of objects that contain the "propertyName" property.
             * The value of this property should be a Number or a String that contains a number.
             * @param {String} propertyName The name of the property that contains the value to compare.
             * @return {Object} the found amount object or null if, at least, one of the parameters is not valid.
             */
            function _getClosestOrEqualAmountObject(amount, amounts, propertyName) {
                if (!Array.isArray(amounts) || !amounts.length || !amount || typeof propertyName !== 'string' ||
                    !propertyName.length || !amount[propertyName]) {
                    return null;
                }

                // Binary search
                // We pass the name of the property to use when comparing values.
                var idx = _.sortedIndexBy(amounts, amount, propertyName);

                // The function "_.sortedIndex" returns "... the lowest index at which value should be inserted into
                // array in order to maintain its sort order...". If the provided value is greater than any item
                // available in the array it returns the length of the array.
                // In this case, we need to decrease the index in one to be able to point to a correct array index.
                if (idx === amounts.length) {
                    idx -= 1;
                }

                return amounts[_getIdxOfTheClosestOrEqualElement(amounts, amount, idx, propertyName)];
            }

            return {
                compareAmounts: _compareAmounts,
                getClosestOrEqualAmountObject: _getClosestOrEqualAmountObject,
                getIdxOfTheClosestOrEqualElement: _getIdxOfTheClosestOrEqualElement,
                removeOtherAmountOptionForHKRaces: _removeOtherAmountOptionForHKRaces,
                roundAmountToTwoDecimalPlaces: _roundAmountToTwoDecimalPlaces
            };
        }

        AmountOptionsFac.$inject = [
            'METADATA',
            'trackSvc'
        ];

        return AmountOptionsFac;
    });

modules/Utilities/providers/factories/locationUnreloadFac.js
"use strict";

define('LocationUnreloadFac',[],function () {

        function LocationUnreloadFac($route, $rootScope, $location, $routeParams) {


            function _updateRouteParams(newParams) {
                angular.forEach(newParams, function (value, key) {
                    $route.current.pathParams[key] = value;
                    $route.current.params[key] = value;
                    $routeParams[key] = value;
                });
            }

            function _pathChange(path, keepPathInHistory, newParams, eventList) {
                if ($location.path() === path) return;
                if(eventList && !angular.isArray(eventList)) {
                    eventList = [eventList];
                }

                var routeToKeep = $route.current;
                var deRegister = $rootScope.$on('$locationChangeSuccess', function () {
                    if (routeToKeep) {
                        $route.current = routeToKeep;
                        routeToKeep = null;
                    }
                    _updateRouteParams(newParams);

                    if (eventList) {
                        eventList.forEach(function(event) {
                            $rootScope.$emit(event);
                        });
                    }

                    deRegister();
                });

                $location.path(path);

                if (!keepPathInHistory)
                    $location.replace();
            }

            return {
                pathChange: _pathChange
            };
        }

        LocationUnreloadFac.$inject = [
            '$route',
            '$rootScope',
            '$location',
            '$routeParams'
        ];

        return LocationUnreloadFac;

    }
);

modules/Utilities/filters/raceTypeIDFilter.js
'use strict';

define('RaceTypeIDFilter',[
        'Content'
    ],
    function () {
        function RaceTypeIDFilter(METADATA) {
            return function(raceTypeID) {
                return METADATA.raceTypes[raceTypeID];
            };
        }

        RaceTypeIDFilter.$inject = [
            'METADATA'
        ];

        return RaceTypeIDFilter;
    }
);

modules/Utilities/filters/mathAbsoluteValueFilter.js
'use strict';

define('MathAbsoluteValueFilter',[
        'Content'
    ],
    function () {
        function MathAbsoluteValueFilter() {
            return function(value) {
                return Math.abs(value);
            };
        }

        MathAbsoluteValueFilter.$inject = [];

        return MathAbsoluteValueFilter;
    }
);

modules/Utilities/filters/getNestedPropertyValueFilter.js
'use strict';

define('GetNestedPropertyValueFilter',[],
    function () {

        function _getNestedPropertyValue(propertyPath, obj, defaultVal) {
            if (!angular.isObject(obj)) {
                throw new Error("_getNestedProperty(): obj must be an object.");
            }
            if (!angular.isString(propertyPath)) {
                throw new Error("_getNestedProperty(): propertyPath must be a String.");
            }

            var value = obj;
            propertyPath.split(".").forEach(function (prop) {
                value = value[prop];
            });

            return value || defaultVal;
        }

        function GetNestedPropertyValueFilter(input, obj, defaultVal) {
            var value;
            try {
                value = _getNestedPropertyValue(input, obj, defaultVal);
            }
            catch (e) {
                value = defaultVal;
            }

            return value;
        }

        return function () {
            return GetNestedPropertyValueFilter;
        };

    });

modules/Utilities/filters/getRelativeDayBasedOnGivenDateFilter.js
'use strict';

define('GetRelativeDayBasedOnGivenDateFilter',['DateTimeFormatters'],
    function (DateTimeFormatters) {
        return function () {
            return DateTimeFormatters.getRelativeDayBasedOnGivenDate;
        };
    });
modules/Utilities/filters/roundAmountFilter.js
'use strict';

define('RoundAmountFilter',[],
    function () {
        function RoundAmountFilter(AmountOptionsFac) {
            return function(amount) {
                return AmountOptionsFac.roundAmountToTwoDecimalPlaces(amount);
            };
        }

        RoundAmountFilter.$inject = [
            'AmountOptionsFac'
        ];

        return RoundAmountFilter;
    }
);

modules/Utilities/filters/reverseFilter.js
'use strict';

define('ReverseFilter',[],
    function () {
        function ReverseFilter() {
            return function (values) {
                return values.slice().reverse();
            };
        }

        return ReverseFilter;
    }
);

modules/Utilities/directives/prevent-default-directive.js
'use strict';

define('PreventDefaultDir',[],function () {

    function PreventDefaultDir() {
        return {
            restrict: 'A',
            link: function (scope, element) {
                element.bind('click', function (event) {
                    if (event) {
                        event.preventDefault();
                    }
                });
            }
        };
    }

    return PreventDefaultDir;
});

modules/Utilities/utilitiesMod.js
'use strict';

define('Utilities',[
        'angularUTF8Base64',
        'angularCookie',
        'ngMd5',
        'CookieFac',
        'LocalStorageFac',
        'StatePersistenceFac',
        'PreferencesCookieFac',
        'RaceMtpDisplay',
        'FavoriteCookieFac',
        'FeaturesHandlerSvc',
        'UserPropertiesSvc',
        'WagerProfileFac',
        'TvgHostsFac',
        'NewWindowGridFac',
        'AmountOptionsFac',
        'LocationUnreloadFac',
        'RaceTypeIDFilter',
        'MathAbsoluteValueFilter',
        'GetNestedPropertyValueFilter',
        'GetRelativeDayBasedOnGivenDateFilter',
        'RoundAmountFilter',
        'ReverseFilter',
        'PreventDefaultDir',
        'TVGCommon'
    ],
    function (
        angularUTF8Base64,
        angularCookie,
        ngMd5,
        CookieFac,
        LocalStorageFac,
        StatePersistenceFac,
        PreferencesCookieFac,
        RaceMtpDisplay,
        FavoriteCookieFac,
        FeaturesHandlerSvc,
        UserPropertiesSvc,
        WagerProfileFac,
        TvgHostsFac,
        NewWindowGridFac,
        AmountOptionsFac,
        LocationUnreloadFac,
        RaceTypeIDFilter,
        MathAbsoluteValueFilter,
        GetNestedPropertyValueFilter,
        GetRelativeDayBasedOnGivenDateFilter,
        RoundAmountFilter,
        ReverseFilter,
        PreventDefaultDir,
        TVGCommon //eslint-disable-line no-unused-vars
    ) {
        angular.module('TVG.Utilities', [
            'ipCookie',
            'TVGCommon',
            'TVG.Track'
        ])
            .value('THROTTLE_MILLISECONDS', null)
            .factory('RaceMtpDisplay', RaceMtpDisplay)
            .factory('CookieFac', CookieFac)
            .factory('LocalStorageFac', LocalStorageFac)
            .factory('StatePersistenceFac', StatePersistenceFac)
            .factory('PreferencesCookieFac', PreferencesCookieFac)
            .factory('FavoriteCookieFac', FavoriteCookieFac)
            .factory('WagerProfileFac', WagerProfileFac)
            .service('FeaturesHandlerSvc', FeaturesHandlerSvc)
            .service('UserPropertiesSvc', UserPropertiesSvc)
            .factory('TvgHostsFac', TvgHostsFac)
            .factory('AmountOptionsFac', AmountOptionsFac)
            .factory('LocationUnreloadFac', LocationUnreloadFac)
            .factory('NewWindowGridFac', NewWindowGridFac)
            .filter('roundAmount', RoundAmountFilter)
            .filter('RaceTypeIDFilter', RaceTypeIDFilter)
            .filter('MathAbsoluteValueFilter', MathAbsoluteValueFilter)
            .filter('reverse',ReverseFilter)
            .directive('preventDefault', PreventDefaultDir)
            .directive('appTitle', function () {
                return {
                    restrict: 'E',
                    replace: true,
                    template: '<title>{{appTitle}}</title>',
                    scope: true
                };
            })
            .directive('removeClass', function () {
                return {
                    restrict: 'A',
                    link: function (scope, element, attrs) {
                        element.removeClass(attrs.removeClass);
                    }
                };
            })
            .filter('trust', function ($sce) {
                return $sce.trustAsHtml;
            })
            .filter('truncate', function () {
                return function (text, length, end) {
                    if (isNaN(length))
                        length = 10;

                    if (end === undefined)
                        end = "...";

                    if (text.length <= length || text.length - end.length <= length) {
                        return text;
                    }
                    else {
                        return String(text).substring(0, length - end.length) + end;
                    }

                };
            })
            .filter('getNestedPropertyValue', GetNestedPropertyValueFilter)
            .filter('getRelativeDayBasedOnGivenDate', GetRelativeDayBasedOnGivenDateFilter)
            .constant('LoginBehaviourConst', {
                HOMEPAGE: 'HOMEPAGE',
                FAVORITE: 'FAVORITE',
                CLOSEST: 'CLOSEST'
            });

            angular.module("template/modal/backdrop.html", []).run(["$templateCache", function ($templateCache) {
                $templateCache.put("template/modal/backdrop.html",
                    "<div class=\"tvgmodal-backdrop\" modal-in-class=\"in\" modal-animation-class=\"fade\" ng-style=\"{'z-index': 1040 + (index && 1 || 0) + index*10}\"></div>");
            }]);

            angular.module("template/modal/window.html", []).run(["$templateCache", function ($templateCache) {
                $templateCache.put("template/modal/window.html",
                    "<div tabindex=\"-1\" class=\"tvgmodal {{ windowClass }} fade\" modal-render=\"{{$isRendered}}\" modal-in-class=\"in\" modal-animation-class=\"fade\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\" >\n" +
                    "	<div class=\"tvgmodal-dismiss no-click-feedback\" ng-click=\"windowClass=='confirm-bet'||windowClass=='first-time-help'||windowClass=='quick-deposit'||close($event)\"></div>\n" +
                    "   <div class=\"tvgmodal-dialog\"><div class=\"tvgmodal-content\" ng-transclude></div></div>\n" +
                    "</div>");
            }]);
    }
);

modules/BetService/providers/betsSvcV2.js
'use strict';

define('BetsSvc',['lodash'],function (_) {

    function BetsSvc($http, $q, METADATA, $filter, $rootScope, GTMFac, stepSelectionsStringFilter, $cookies, ConfigurationFac, RequestContextHeaders, $timeout, $sce) {
        var wagerUUID = _generateUUID();
        var Bets = {
            transactionLog: function (msg) {
                var deferred = $q.defer();
                var wagerTransactionType = 158;

                var data = {
                    eventType: 'PlaceBet',
                    userId: $rootScope.user.accountNumber,
                    eventTime: (new Date()).toISOString(),
                    siteVersion: (($rootScope.layout === 'desktop') ? 'TVG4' : 'Touch') + ' - ' + window.location.hostname,
                    transactionType: wagerTransactionType,
                    msg: msg
                };

                $http({
                    method: 'POST',
                    url: ConfigurationFac.getServiceApiUrl('log'),
                    data: data,
                    headers: {
                        'Content-Type': 'application/json',
                        'x-tvg-context': RequestContextHeaders[clientApp + '_' + locationContext]
                    }
                }).success(function (response) {
                    deferred.resolve(response);
                }).error(function (response) {
                    deferred.reject(response);
                });

                return deferred.promise;
            },

            placeBet: function (betTotalResults, race) {
                var asyncPlaceWagerHandler = $rootScope.activeFeatures.asyncPlaceWagerHandler;
                var newWagerEndpointToggle = $rootScope.activeFeatures.newWagerEndpoint;

                if (newWagerEndpointToggle) {
                    var uuid = wagerUUID;
                    var csrfToken = _generateUUID();
                    var repeat = betTotalResults.repeat ? betTotalResults.repeat : 1;
                    var regionDetails = null;
                    var location = null;
                    var repeatQueryString = '';
                    var selections = [];
                    var userId= $rootScope.user.accountNumber;

                    if (betTotalResults.wagerCode == "TIW") {
                        betTotalResults.BIs[0].forEach(function (selected) {
                            selections.push([{
                                order: selected
                            }]);
                        });

                        selections.push(betTotalResults.BIs[1].map(function (selected) {
                            return {
                                order: selected
                            };
                        }));
                    } else {
                        for (var i = 0; i < betTotalResults.BIs.length; i++) {
                            var tempArray = [];
                            for (var j = 0; j < betTotalResults.BIs[i].length; j++) {
                                var bi = {
                                    order: betTotalResults.BIs[i][j]
                                };
                                tempArray.push(bi);
                            }
                            selections.push(tempArray);
                        }
                    }

                    if(typeof $rootScope.regions !== 'undefined'){
                        regionDetails = $rootScope.regions;
                        location = $rootScope.location;
                    }

                    var betToPlace = {
                        wagerReference: uuid,
                        track: race.trackAbbr,
                        race: race.raceNumber,
                        perf: race.perfAbbr,
                        amount: betTotalResults.betAmount,
                        price: parseFloat(betTotalResults.betCost),
                        type: betTotalResults.wagerCode,
                        selections: selections
                    };

                    var postData = {
                        wager: betToPlace,
                        regions: regionDetails,
                        location: location
                    };

                    if(repeat > 0){
                        repeatQueryString = '?wagersToBePlaced=' + repeat;
                    }

                    // Setting a cookie
                    $cookies.put('csrfToken', csrfToken);

                    var deferred = $q.defer();
                    var url = ConfigurationFac.getServiceApiUrl('wtx') + "/" + $rootScope.user.accountNumber + "/wagers" ;
                    var errorMessages = [];
                    try {
                        errorMessages = angular.fromJson($filter('CMSValue')('wtxErrorMessages'));
                    } catch (e) {};

                    if (envName && envName === 'dev') {
                        url = ConfigurationFac.getConfigParam('service', 'wtx');
                    }

                    $http({
                        method: 'POST',
                        url: url + repeatQueryString,
                        data: postData,
                        headers: {
                            'Content-Type': 'application/json',
                            'X-XSRF-TOKEN' : csrfToken,
                            'x-tvg-context': RequestContextHeaders[clientApp + '_' + locationContext]
                        }
                    }).then(function successCallback(response) {
                        if (response.status == 202 && asyncPlaceWagerHandler) {
                            if (response.headers('location') != null) {
                                var trustedResource = $sce.trustAsResourceUrl(response.headers('location'));
                                var checkUrl = $sce.valueOf(trustedResource);
                                _checkAsyncTimeout(checkUrl, $q.defer()).then(function () {
                                    wagerUUID = _generateUUID();
                                    deferred.resolve(betTotalResults);
                                });
                            } else {
                                // console.log("location header not set.");
                                wagerUUID = _generateUUID();
                                deferred.resolve(betTotalResults);
                            }
                        } else {
                            var errorCode = 0;
                            wagerUUID = _generateUUID();
                            var summary = _.get(response, 'data.summary');

                            // determine if it's a multiple bet and if there are failed bets
                            if(response.status === 207 && summary && summary.requested !== summary.fulfilled) {
                                var multiBet = false;
                                var errorTitle;

                                // set first error code if all requested bets failed
                                if(summary.requested === summary.failed) {
                                    errorCode = _.get(response, 'data.status[0].error.code');
                                } else {
                                    // get first error code from multi bet
                                    response.data.status.map(function(status) {
                                        if(parseInt(_.get(status, 'error.code')) > 0 && !errorCode) {
                                            errorCode = _.get(status, 'error.code');
                                        }
                                    });
                                    errorTitle = '<strong>We were only able to place ' + summary.fulfilled + ' of ' + summary.requested + ' bets.</strong><br>';
                                    multiBet = true;
                                }

                                //handle new endpoint errors
                                if (errorCode) {
                                    var error = {
                                        errorCode: errorCode,
                                        errorMessageKey: errorMessages[errorCode],
                                        message: errorTitle + errorMessages[errorCode],
                                        multiBet: multiBet
                                    };
                                    deferred.reject(error);
                                    return;
                                } else {
                                    deferred.resolve(betTotalResults);
                                }
                            } else {
                                betTotalResults.serialNumber = _.get(response, 'data.status[0].success.serialNumber', undefined);
                                deferred.resolve(betTotalResults);
                            }
                        }

                        if (response.data && response.data.userBalance) {
                            $rootScope.$broadcast("accountBalance_force_update", {balance: response.data.userBalance});
                        } else {
                            $rootScope.$broadcast("accountBalance_update");
                        }

                    }, function errorCallback(response) {
                        wagerUUID = _generateUUID();
                        var errorCode = _.get(response, 'data.code');

                        //handle new endpoint errors
                        if (errorCode) {
                          var errorBetMessage = errorMessages[errorCode];
                          if (errorCode === 136457) {

                            var errorMessage = _.get(response, "data.message", "");
                            var replaceObj = {
                              _betAmount: errorMessage
                                .split(":")
                                .pop()
                                .split("(")[0]
                                .trim(),
                              _minAmount: errorMessage
                                .split("=")
                                .pop()
                                .split(")")[0]
                                .trim()
                            };
                            errorBetMessage = $rootScope.activeFeatures.betErrorMessage ?
                              errorBetMessage.replace(
                                  /_betAmount|_minAmount/gi,
                                  function(matched){ return replaceObj[matched]; }
                                )
                              : errorMessages[errorCode+1];
                            // we increment the errorCode by 1 because the next message is exactly the same as the old message
                            // TODO FABIO - remove the toggle code when we don't need it
                          };
                            var error = {
                                errorCode: errorCode,
                                errorMessageKey: errorBetMessage,
                                message: errorMessages[errorCode] || $filter('CMSValue')('betTicketGenericErrorMessage')
                            };
                            deferred.reject(error);
                            return;
                        }

                        deferred.reject(_parseErrorMessage(0, "Default")); //return the default error message
                    });

                    return deferred.promise;

                } else {

                    var betToPlace = {
                        date: METADATA.raceDate,
                        perf: race.perfAbbr,
                        amount: betTotalResults.betAmount,
                        price: betTotalResults.betCost,
                        wageramount: betTotalResults.betAmount,
                        track: race.trackAbbr,
                        race: race.raceNumber,
                        type: betTotalResults.wagerId,
                        bi: betTotalResults.BIs,
                        otherAmt: "",
                        balance: "",
                        repeat: betTotalResults.repeat ? betTotalResults.repeat : 1
                    };

                    var deferred = $q.defer();

                    $http.get("/ajax/bet/betTicketInitData").then(function (response) {

                        if (response.data.csrf_token) {
                            betToPlace.token = response.data.csrf_token;
                        }
                        $http({
                            method: 'POST',
                            url: "/ajax/bet/wager/json",
                            data: betToPlace,
                            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                            transformRequest: _tranformPostData
                        }).success(function (response) {
                            var errorCode = !response ? 0 : response.code || (response.result && response.result.code) || response.ErrorCode || 0;
                            var errorName = !response ? "" : response.name || (response.result && response.result.name) || response.ErrorMessage || "";

                            if (response && (!response.result && response.status && response.status.match(/error/i) ||
                                response.result && response.result.status && response.result.status.match(/error/i) ||
                                response.ErrorCode)) {

                                deferred.reject(_parseErrorMessage(errorCode, errorName));
                            } else if (response && response.result && response.result !== "") {
                                deferred.resolve(betTotalResults);
                            } else {
                                deferred.reject(_parseErrorMessage(0, "")); //return the default error message
                            }
                        }).error(function () {
                            var errorCode = !response ? 0 : response.code || (response.result && response.result.code) || response.ErrorCode || 0;
                            var errorName = !response ? "" : response.name || (response.result && response.result.name) || response.ErrorMessage || "";

                            deferred.reject(_parseErrorMessage(errorCode, errorName)); //return the default error message
                        });
                    });

                    $cookies.remove('wagerRef');

                    return deferred.promise;

                }
            },

            calculateBetTotal: function (oAmount, oWagerType, BIs) {
                var result = {},
                    betCount;

                BIs = $filter('filter')(BIs, function (elem) {
                    return elem !== undefined;
                });

                if (!(oAmount > 0.0 && BIs && BIs.length > 0)) {
                    result.betCount = 0;
                    result.betCost = '0.00';
                    result.wagerName = oWagerType.name;
                    result.wagerId = oWagerType.id;
                    result.wagersString = "";
                    result.BIs = BIs;
                    return result;
                }

                if (oWagerType.abbreviation == "QN" || oWagerType.abbreviation == "OM") {

                    betCount = _calculateQuinellaTotalBets(BIs);

                } else if (oWagerType.abbreviation == "QNB" || oWagerType.abbreviation == "OMB") {

                    betCount = _calculateQuinellaBoxTotalBets(BIs);

                } else if (oWagerType.abbreviation == "QNW" || oWagerType.abbreviation == "OMW") {

                    betCount = _calculateQuinellaWheelTotalBets(BIs).length;

                } else if (oWagerType.abbreviation == "TI") {

                    betCount = _calculateTrioTotalBets(BIs);

                } else if (oWagerType.abbreviation == "TIB") {

                    betCount = _calculateTrioBoxTotalBets(BIs);

                } else if (oWagerType.abbreviation == "TIW") {

                    betCount = _calculateTrioWheelTotalBets(BIs);

                } else if (oWagerType.isKey) {

                    betCount = _calculateKeysTotalBets(BIs, oWagerType.positionCount, oWagerType.isBox);

                } else if (oWagerType.isBox) {

                    var numberOfPositions = _getMinBisPerStep(oWagerType);
                    betCount = _calculateFectaBoxTotalBets(BIs, numberOfPositions);

                } else if (oWagerType.columnCount > 1 && oWagerType.legCount == 1) {

                    if (oWagerType.isWheel) {
                        betCount = _calculateFectaWheelsTotalBets(BIs).length;
                    } else {
                        betCount = _calculateFectaTotalBets(BIs).length;
                    }

                } else {
                    var betTypeMultiplier = _getWagerTypeMultiplier(oWagerType);
                    betCount = _calculateStraightAndLegsTotalBets(BIs) * betTypeMultiplier;
                }

                result.betCount = betCount;
                result.betAmount = oAmount;
                result.betCost = (betCount * oAmount).toFixed(2);
                result.wagerName = oWagerType.name;
                result.wagerId = oWagerType.id;
                result.wagerCode = oWagerType.abbreviation;
                result.wagersString = _getWagerString(oWagerType, BIs);
                result.BIs = BIs;

                return result;
            },

            buildWagerType: function (rawData) {
                return new WagerType(rawData.BetAmounts, rawData.MaxBetAmount, rawData.MinBetAmount, rawData.WagerTypeID);
            },

            apiResponseWagerTypesTransformer: function (wagerTypes, fromGraph) {
                return wagerTypes.map(function (wagerType) {
                    // because we have many templates / controllers depending on the actual WagerType constructor, let's keep this logic for now
                    if (fromGraph) {
                        var wagerTypeTransformed = wagerType;

                        wagerTypeTransformed.id = wagerType.type ? wagerType.type.id || null : null;
                        wagerTypeTransformed.name = wagerType.type ? wagerType.type.name || "" : "";
                        wagerTypeTransformed.abbreviation = wagerType.type ? wagerType.type.code || "" : "";

                        wagerTypeTransformed.betAmounts = wagerType.wagerAmounts ? wagerType.wagerAmounts.map(_formatBetAmount) : [];
                        wagerTypeTransformed.maxBetAmount = parseFloat(wagerType.maxWagerAmount);
                        wagerTypeTransformed.minBetAmount = parseFloat(wagerType.minWagerAmount);

                        if (wagerTypeTransformed.betAmounts.length) {
                            wagerTypeTransformed.betAmounts.push({
                                amountString: 'other',
                                amount: null
                            });
                        }

                        // delete unnecessary fields that come from graph
                        delete wagerTypeTransformed.type;
                        delete wagerTypeTransformed.wagerAmounts;
                        delete wagerTypeTransformed.minWagerAmount;
                        delete wagerTypeTransformed.maxWagerAmount;

                        return wagerTypeTransformed;
                    } else {
                        return Bets.buildWagerType(wagerType);
                    }
                }).sort(function (a, b) {
                    return parseInt(a.id, 10) - parseInt(b.id, 10);
                });
            },
            cancelBet: function (bet) {
                var cancelBetWtx = $rootScope.activeFeatures.cancelBetWtx;
                var deferred = $q.defer();

                if (cancelBetWtx) {
                    var wagerReference = bet.wagerReference || '0';
                    var betId = bet.serialNumber || bet.id;
                    var queryString = '/' + wagerReference + '/' + betId;
                    var url = ConfigurationFac.getServiceApiUrl('wtx');

                    $http({
                        method: 'DELETE',
                        url: url + queryString,
                        headers: {
                            'Content-Type': 'application/json',
                            'x-tvg-context': RequestContextHeaders[clientApp + '_' + locationContext]
                        }
                    }).success(function () {
                        deferred.resolve("OK");
                        $rootScope.$broadcast("accountBalance_update");
                    }).error(function () {
                        deferred.reject($filter('CMSValue')('betTicketErrorCancelingWager'));
                    });

                    return deferred.promise;
                } else {
                    $http({
                        method: 'POST',
                        url: "/ajax/wager-history/report/wager/filter/",
                        data: {id: bet.id, date: bet.wagerDate},
                        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                        transformRequest: _tranformPostData
                    }).success(function (data) {
                        if (data && data.status.match(/success/i)) {
                            deferred.resolve(data);
                            $rootScope.$broadcast("accountBalance_update");
                        } else {
                            deferred.reject($filter('CMSValue')('betTicketErrorCancelingWager'));
                        }

                    }).error(function () {
                        deferred.reject($filter('CMSValue')('betTicketErrorCancelingWager'));
                    });

                    return deferred.promise;
                }
            }
        };



        function _checkAsyncTimeout(checkUrl, deferred){
            $timeout(function() {
                _checkAsyncWagers(checkUrl).then(function (){
                    deferred.resolve();
                }).catch(function(){
                    _checkAsyncTimeout(checkUrl, deferred);
                });
            }, (5000));

            return deferred.promise;
        }

        function _checkAsyncWagers(checkUrl){
            /*
             wagerStatus:
             PLACE_IN_PROGRESS
             PLACE_COMPLETED
             CANCEL_IN_PROGRESS
             CANCEL_COMPLETED
             */
            var deferred = $q.defer();

            $http({
                method: 'GET',
                url: checkUrl,
                headers: {
                    'Content-Type': 'application/json',
                    'x-tvg-context': RequestContextHeaders[clientApp + '_' + locationContext]
                }
            }).then(function successCallback(response) {
                if(response.data.wagerSummary && response.data.wagerSummary.wagerStatus == 'PLACE_COMPLETED'){
                    deferred.resolve();
                } else {
                    deferred.reject();
                }
            }, function errorCallback() {
                deferred.reject();
            });
            return deferred.promise;
        }

        function _generateUUID() {
            var d = new Date().getTime();
            if(window.performance && typeof window.performance.now === "function"){
                d += performance.now(); //use high-precision timer if available
            }
            var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = (d + Math.random()*16)%16 | 0;
                d = Math.floor(d/16);
                return (c=='x' ? r : (r&0x3|0x8)).toString(16);
            });
            return uuid;
        }

        function _cartesianProductOf(matrix) {
            return matrix.reduce(function (a, b) {
                var ret = [];
                a.forEach(function (a) {
                    b.forEach(function (b) {
                        if (a.indexOf(b) < 0) {
                            ret.push(a.concat([b]));
                        }
                    });
                });
                return ret;
            }, [[]]);
        }

        function _calculateFectaTotalBets(BIs) {
            return _cartesianProductOf(BIs);
        }

        function _calculateFectaWheelsTotalBets(BIs) {
            var res = [],
                firstCol = [],
                selectionsLength = 0,
                otherCols = [],
                i;

            for (i = 0; i < BIs.length; i++) {
                var col = BIs[i];
                if (i == 0) {
                    firstCol = col;
                    selectionsLength = firstCol.length;
                } else {
                    otherCols.push(col);
                }
            }

            for (i = 0; i < selectionsLength; i++) {
                var fc = [firstCol[i]];
                var matrix = otherCols.slice(0);
                matrix.unshift(fc);
                res = res.concat(_cartesianProductOf(matrix));
            }
            return res;
        }

        function _calculateFectaBoxTotalBets(BIs, numOfPositions) {
            var selections = BIs[0].length,
                res = 1;
            for (var i = 0; i < numOfPositions; i++) {
                res *= selections;
                --selections;
            }
            return res;
        }

        function _calculateQuinellaTotalBets(BIs) {
            var selections = BIs[0].length,
                res = 1;
            if (selections <= 2) {
                for (var i = 0; i < 2; i++) {
                    res *= selections;
                    --selections;
                }
            } else {
                res = 0;
            }

            res /= 2;
            return res;
        }

        function _calculateQuinellaBoxTotalBets(BIs) {
            var selections = BIs[0].length,
                res = 1;
            if (selections >= 2) {
                for (var i = 0; i < 2; i++) {
                    res *= selections;
                    --selections;
                }
            } else {
                res = 0;
            }

            res /= 2;
            return res;
        }

        function _calculateQuinellaWheelTotalBets(BIs) {
            var res = [],
                firstCol = BIs[0],
                firstColLength = firstCol.length,
                secCol = BIs[1].slice(0),
                secColLength = secCol.length,
                alreadyUsedKeys = [];

            for (var i = 0; i < firstColLength; i++) {
                var fc = [firstCol[i]];
                var matrix = [[]];

                for (var j = 0; j < secColLength; j++) {
                    var sColItem = secCol[j];
                    var keyPar = (BigInt(1) << BigInt(sColItem) ^ BigInt(1) << BigInt(fc));

                    if (sColItem != fc && alreadyUsedKeys.indexOf(keyPar) < 0) {
                        matrix[0].push(sColItem);
                    }
                    alreadyUsedKeys.push(keyPar);
                }

                matrix.unshift(fc);
                res = res.concat(_cartesianProductOf(matrix));
            }
            return res;
        }

        function _calculateTrioTotalBets(BIs) {
            return BIs[0].length === 3 ? 1 : 0;
        }

        function _calculateTrioBoxTotalBets(BIs) {
            var selections = BIs[0].length,
                res = 1;
            if (selections >= 4) {
                for (var i = 0; i < 3; i++) {
                    res *= selections;
                    --selections;
                }
            } else {
                res = 0;
            }

            res /= 6;
            return res;
        }

        function _calculateTrioWheelTotalBets(BIs) {
            var res = 1,
                firstCol = BIs[0],
                firstColLength = firstCol.length,
                secCol = BIs[1],
                secColLength = secCol.length;

            for (var i = 0; i < firstColLength; i++) {
                for (var l = 0; l < secColLength; l++) {
                    if (firstCol[i] === secCol[l]) {
                        secColLength--;
                    }
                }
            }

            if (firstColLength < 1 || firstColLength > 2 || firstColLength + secColLength < 3 ) {
                res = 0;
            } else if (firstColLength === 2) {
                res = secColLength;
            } else {
                for (var j = 0; j < 2; j++) {
                    res = res * (secColLength - j) / (j + 1);
                }
            }

            return res;
        }

        function _calculateKeysTotalBets(BIs, numOfPositions, isBox) {
            var selections = 0,
                res = 1;

            if (BIs[0].length && BIs[1] !== undefined && BIs[1].length) {
                selections = BIs[1].length;
                for (var i = 0; i < (numOfPositions - 1); i++) {
                    res *= selections;
                    --selections;
                }

                if (isBox) {
                    res *= numOfPositions;
                }
            } else {
                res = 0;
            }
            return res;
        }

        function _calculateStraightAndLegsTotalBets(BIs) {
            var res = 1;
            for (var i = 0; i < BIs.length; i++) {
                var legSelections = BIs[i].length;
                res *= legSelections;
            }
            return res;
        }

        function _getWagerTypeMultiplier(wt) {
            var multiplier = 1;

            switch (wt.abbreviation) {
                case 'WP':
                case 'WS':
                case 'PS':
                    multiplier = 2;
                    break;
                case 'WPS':
                    multiplier = 3;
                    break;
                default:
                    break;
            }

            return multiplier;
        }

        function _getMinBisPerStep(wt) {
            var biPerStep = 1;

            switch (wt.abbreviation) {
                case 'QN':
                    biPerStep = 2;
                    break;
                case 'QNB':
                    biPerStep = 2;
                    break;
                case 'EXB':/* maybe not needed see line 149 'if (oWagerType.isBox)'*/
                    biPerStep = 2;
                    break;
                case 'TRB':/* maybe not needed see line 149 'if (oWagerType.isBox)'*/
                    biPerStep = 3;
                    break;
                case 'SUB':/* maybe not needed see line 149 'if (oWagerType.isBox)'*/
                    biPerStep = 4;
                    break;
                case 'H5B':
                    biPerStep = 5;
                    break;
                default:
                    break;
            }

            return biPerStep;
        }

        function _getWagerString(wt, wagers) {
            var wagerString = "";

            for (var i = 0; i < wt.columnCount; i++) {
                if (i != 0) {
                    wagerString += " | ";
                }

                if (wagers && wagers[i] && wagers[i].length) {

                    wagerString += stepSelectionsStringFilter(wagers[i]);
                } else {
                    wagerString += "?";
                }
            }

            if ($rootScope.user) {
                $rootScope.user.wagerString = wagerString;
                GTMFac.setCurrentSelectionList(wagers);
            }

            return wagerString;
        }

        function _formatBetAmount(amount) {
            return {
                amountString: $filter('currency')(amount, "$"),
                amount: amount
            };
        }

        function WagerType(betAmounts, maxBetAmount, minBetAmount, wagerTypeID) {
            this.id = wagerTypeID;
            if (!!METADATA.wagerTypes[this.id]) {
                this.betAmounts = betAmounts ? betAmounts.map(_formatBetAmount) : [];
                this.maxBetAmount = parseFloat(maxBetAmount);
                this.minBetAmount = parseFloat(minBetAmount);

                this.name = METADATA.wagerTypes[this.id].Name;
                this.abbreviation = METADATA.wagerTypes[this.id].Abbreviation;
                this.columnCount = parseInt(METADATA.wagerTypes[this.id].ColumnCount, 10);
                this.columnType = METADATA.wagerTypes[this.id].ColumnType || "Runners";
                this.isBox = METADATA.wagerTypes[this.id].IsBox;
                this.isKey = METADATA.wagerTypes[this.id].IsKey;
                this.legCount = METADATA.wagerTypes[this.id].LegCount;
                this.maxBIsPerLeg = METADATA.wagerTypes[this.id].MaxBIsPerLeg;
                this.minBIsPerLeg = METADATA.wagerTypes[this.id].MinBIsPerLeg;
                this.poolsPerBI = METADATA.wagerTypes[this.id].PoolsPerBI;
                this.positionCount = METADATA.wagerTypes[this.id].PositionCount;
                this.isWheel = (
                    this.abbreviation == "QNW" ||
                    this.abbreviation == "EXW" ||
                    this.abbreviation == "TRW" ||
                    this.abbreviation == "SUW" ||
                    this.abbreviation == "H5W"
                );

                if (this.betAmounts.length) {
                    this.betAmounts.push({
                        amountString: "other",
                        amount: null
                    });
                }
            }
        }

        function _tranformPostData(obj) {
            var str = [];
            for (var key in obj) {
                if (obj[key] instanceof Array) {
                    for (var idx in obj[key]) {
                        var subObj = obj[key][idx];
                        for (var subKey in subObj) {
                            str.push(encodeURIComponent(key) + "[" + parseInt(parseInt(idx, 10) + 1, 10) + "][]=" + encodeURIComponent(subObj[subKey]));
                        }
                    }
                }
                else {
                    str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
                }
            }
            return str.join("&");
        }

        function _parseErrorMessage(errorCode, errorName, message) {
            var errorMessageKey;

            if (errorName === "InsufficientFunds") {
                errorMessageKey = $filter('CMSValue')('betTicketInsufficientFunds');
            } else if (errorName === "RaceClosed") {
                errorMessageKey = $filter('CMSValue')('betTicketRaceClosed');
            } else if (errorName === "ToteInvalidWagerAmount" || errorName === "ToteWagerAmountTooLarge" || errorName === "ToteWagerAmountTooSmall") {
                errorMessageKey = $filter('CMSValue')('betTicketToteInvalidWagerAmount');
            } else if (errorName === "WagerBadRunner") {
                errorMessageKey = $filter('CMSValue')('betTicketWagerBadRunner');
            } else if (errorName === "InvalidWagerType") {
                errorMessageKey = $filter('CMSValue')('betTicketInvalidWagerType');
            } else if (errorCode == 619) {
                errorMessageKey = $filter('CMSValue')('apiUserSessionInvalid');
            } else if(errorName === "INVALID_WAGER") {
                 if(message && message.indexOf('Invalid wager amount') !== -1){
                    errorMessageKey = $filter('CMSValue')('betTicketToteInvalidWagerAmount');
                 } else if(message && message.indexOf('RequestedBetAmountNotAllowed') !== -1) {
                     errorMessageKey = $filter('CMSValue')('betTicketToteInvalidWagerAmount');
                 } else {
                    errorMessageKey = $filter('CMSValue')('betTicketGenericErrorMessage');
                 }
            }
            else {
                errorMessageKey = $filter('CMSValue')('betTicketGenericErrorMessage');
            }

            return {
                errorCode: errorCode,
                errorMessageKey: errorMessageKey
            };
        }

        return Bets;
    }

    BetsSvc.$inject = [
        '$http',
        '$q',
        'METADATA',
        '$filter',
        '$rootScope',
        'GTMFac',
        'stepSelectionsStringFilter',
        '$cookies',
        'ConfigurationFac',
        'RequestContextHeaders',
        '$timeout',
        '$sce'
    ];

    return BetsSvc;
});

modules/BetService/filters/stepSelectionsStringFilter.js
'use strict';

define('StepSelectionsStringFilter',[],function() {
    var DEFAULT_SEPARATOR = ',';
    var CONSECUTIVE_SELECTIONS_SEPARATOR = '-';
    var consecutiveSelections;
    var currentSelection;

    function _getStringSeparator(currentSelection) {
        return currentSelection.length === 2 && currentSelection[1] - currentSelection[0] > 1 ?
            CONSECUTIVE_SELECTIONS_SEPARATOR : DEFAULT_SEPARATOR;
    }

    function _pushCurrentSelectionToConsecutiveSelections() {
        consecutiveSelections.push(
            currentSelection.join(
                _getStringSeparator(currentSelection)));
    }

    function _forEachSelectionCallback(selection) {
        if (currentSelection.length) {
            if (selection - currentSelection[currentSelection.length - 1] === 1) {
                if (currentSelection.length === 2) {
                    currentSelection[1] = selection;
                } else {
                    currentSelection.push(selection);
                }
            } else {
                _pushCurrentSelectionToConsecutiveSelections();
                currentSelection = [selection];
            }
        } else {
            currentSelection.push(selection);
        }
    }

    function _stepSelectionsStringFilter(selections) {
        // Reset state
        consecutiveSelections = [];
        currentSelection = [];

        if (!Array.isArray(selections)) {
            return selections;
        }

        selections = selections.sort(function(a, b) {
            return a - b;
        });

        selections.forEach(_forEachSelectionCallback);

        _pushCurrentSelectionToConsecutiveSelections();

        return consecutiveSelections.join(DEFAULT_SEPARATOR);
    }

    return function() {
        return _stepSelectionsStringFilter;
    };
});

modules/BetService/betServiceBase.js
'use strict';

define('BetService',[
        'BetsSvc',
        'StepSelectionsStringFilter',
        'GTMMod'
    ],
    function(BetsSvc, StepSelectionsStringFilter) {
        angular.module('TVG.BetService', [
            'TVG.Common.GTM'
        ])
            .factory('BetsSvc', BetsSvc)
            .filter('stepSelectionsString', StepSelectionsStringFilter);
    });

modules/BetSlipWindow/models/runnerSaddleModel.js
"use strict";

define('RunnerSaddleModel',[], function () {

    function RunnerSaddle(backColor, numColor, horseId, horseName, bettingInterestNumber) {
        this.backgroundColor = backColor;
        this.numberColor = numColor;
        this.horseId = horseId;
        this.horseName = horseName;
        this.bettingInterestNumber = bettingInterestNumber;
    }

    return RunnerSaddle;

});


modules/BetSlipWindow/controllers/betSlipWindowCtrl.js
'use strict';

define(
    'BetSlipWindowCtrl',[
        'RunnerSaddleModel',
        'BetsSvc',
        'StatePersistenceFac',
        'PreferencesCookieFac',
        'RaceStatusUtils'
    ],
    function (RunnerSaddleModel,
              _BetsSvc,
              _StatePersistenceFac,
              _PreferencesCookieFac,
              RaceStatusUtils) {

        function BetSlipWindowCtrl($scope,
                                   $rootScope,
                                   BetsSvc,
                                   StatePersistenceFac,
                                   $window,
                                   $uibModal,
                                   PreferencesCookieFac,
                                   $filter,
                                   $routeParams,
                                   GTMFac,
                                   UserProfileSvc,
                                   RaceInfoFac,
                                   $interval,
                                   AmountOptionsFac,
                                   trackSvc,
                                   betSlipWindowAlertsFac,
                                   GraphRaceRunners,
                                   WagerProfileFac,
                                   $log,
                                   $timeout,
                                   LocalStorageFac,
                                   PreferencesFac) {

            var resubmit = false,
                previousState = StatePersistenceFac.loadState("bt"),
                userPrefs = PreferencesCookieFac.getPreferences(),
                prefBetAmount = userPrefs.bet_amount,
                confirmDialog = null,
                parameters = $routeParams,
                readParameters = false,
                prefBetType,
                verifiedBetTypeWhenFromRunnerClick = false,
                trackDataCtrl = [],
                initialSetup = true,
                closeBetSlipReceiptBtn = false,
                onFirstTimeOpen = true,
                betsCanceled = false,
                betsSubmitted = false,
                sizeToggle = 1,
                loadFirstTime,
                initialFetchRetry = 3,
                fetchRetry = initialFetchRetry,
                subscribeEvent,
                nFectaWagerTypes = ['E6', 'E7', 'E8', 'E9', 'E10', 'E11', 'E12', 'E13', 'E14'],
                pickWagerType = [310, 330, 340, 350, 360, 370, 380, 390, 400, 510, 520, 530, 540, 550, 560, 570, 580, 690, 700, 710, 720, 730, 740, 750, 760],
                trifectaWagerType = [160, 170, 180, 190, 200],
                exactaWagerType = [110, 120, 130, 140, 150, 770],
                superfectaWagerType = [210, 220, 230, 240, 250],
                superhighfiveWagerType = [260, 270, 280, 290, 300];

            // GraphQL variables
            var graphSubscription;
            var graphPollerInterval = $filter('CMSLabels')('low', 'graphqlPollingRates') || 30000; // in ms

            $scope.data = {};

            $rootScope.isGreyhoundRace = !!parameters.greyhounds || false;
            $scope.isLoading = true;
            $scope.data.blockAnyBetting = false;
            $scope.data.closedForBettingMessage = $filter('CMSValue')('betTicketClosedCurrentRace') + ($rootScope.isIE ? '. ' + $filter('CMSValue')('betTicketChooseAnotherRace') : '');
            $scope.data.incorrectBetSize = $filter('CMSValue')('betTicketIncorrectBetSize');
            $scope.data.incorrectAmountValueMessage = $filter('CMSValue')('betSlipAmountEnteredIsIncorrect');
            $scope.data.minimumBetAmountMessage = $filter('CMSValue')('BetSlipMinimumAmountIs');
            $scope.data.maximumBetAmountMessage = $filter('CMSValue')('BetSlipMaximumAmountIs');
            $scope.data.nearestAmountsMessage = $filter('CMSValue')('BetSlipNearestAmounts');
            $scope.data.forbiddenBettingStates = angular.fromJson($filter('CMSValue')('forbiddenBettingStates'));
            $scope.data.otherAmountStep = 0.5;

            $scope.events = {
                betTypeChanged: _betTypeChanged,
                betAmountChanged: _betAmountChanged,
                otherAmountChanged: _otherAmountChanged,
                submitBet: _submitBet,
                pushRaceInfo: _pushRaceInfo,
                changeTab: _changeTab,
                closeRaceInfo: _closeRaceInfo,
                closeInfoMessage: _closeInfoMessage,
                checkIfResumit: _checkIfResumit,
                toggleSelection: _toggleSelection,
                toggleAll: _toggleAll,
                isSelected: _isSelected,
                isSelectedAll: _isSelectedAll,
                isSelectable: _isSelectable,
                isActiveTab: _isActiveTab,
                legHasRunner: _legHasRunner,
                toggleTab: _toggleTab,
                closeMessage: _closeMessage,
                closeBetslip: _closeBetslip,
                goBack: _goBack,
                confirmBet: _confirmBet,
                createSameBet: _createSameBet,
                createSameRace: _createSameRace,
                repeatBet: _repeatBet,
                validateRepeatValue: _validateRepeatValue,
                closeAlert: betSlipWindowAlertsFac.closeAlert,
                closeAlertForever: _closeAlertForever,
                filterAmountOptions: true,
                areAllRunnersScratched: _areAllRunnersScratched,
                isNewWagerType: _isNewWagerType,
                isScratchedHorseInList: _isScratchedHorseInList
            };

            $scope.data.layoutType = null;
            $scope.data.activeTab = 0;
            $scope.data.activeNavTab = 0;
            $scope.data.totalSelected = [];
            $scope.data.cols = [];
            $scope.data.legRaces = [];
            $scope.data.legRacesRunners = [];
            $scope.data.isLeg = false;
            $scope.data.isBetConfirmed = true;
            $scope.data.betButtonLabel = '';
            $scope.data.legColumnHeight = [];
            $scope.data.mtp = {
                time: 0,
                status: 'time-format'
            };

            var show = {
                viewBET: "bet",
                viewCONFIRMATION: "confirmation",
                viewRECEIPT: "receipt",
                messageSUCCESS: "success",
                messageERROR: "error",
                messageWARN: "warn",
                messageHIDE: ""
            };

            $scope.data.showConfirmWarn = true;
            $scope.data.showMessage = show.messageHIDE;
            $scope.data.showView = show.viewBET;

            $scope.alerts = betSlipWindowAlertsFac.alerts;

            $scope.existsScratchedHorse = false;

            if (!angular.isUndefined(userPrefs.show_bet_confirm) && userPrefs.show_bet_confirm == 0) {
                $scope.data.isBetConfirmed = false;
            }

            $scope.data.betSlipWindowParams = [
                '/betslip',
                $routeParams.trackAbbr,
                $routeParams.perfAbbr,
                $routeParams.raceNumber
            ].join('/');

            function _updateCurrentRaceAndCurrentRaceIndex(trackData, races, raceNumber) {
                var raceNumberInt = parseInt(raceNumber, 10);

                $scope.data.currentRace = _.find(trackData, function (race) {
                    return parseInt(race.raceNumber, 10) === raceNumberInt;
                });

                if ($scope.data.currentRace) {
                    $scope.data.currentRace.perfAbbr = $scope.data.currentRace.track ? $scope.data.currentRace.track.perfAbbr : '';

                    $scope.data.currentRaceIndex = _.findIndex(races, function (race) {
                        return race.id === $scope.data.currentRace.id;
                    });

                    $rootScope.appTitle = 'TVG Bet Ticket | ' + $scope.data.currentRace.trackName + ' - R' + $scope.data.currentRace.raceNumber;
                }
            }

            function _roundAmount(amount) {
                return $filter('roundAmount')(amount);
            }

            function _createSameBet() {
                _validateBet();

                var p = gtmDefaultBetSlipData();
                p.eventLabel = 'BetTicketReceipt-SameBet';
                p.gaEventAction = 'Bet Ticket Receipt Page Click';
                p.gaEventLabel = 'Create Same Bet';
                GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'siteClick', p);

                _resetRepeat();
                _goBack();
                betsCanceled = false;
            }

            function _createSameRace() {
                var p = gtmDefaultBetSlipData();
                p.eventLabel = 'BetTicketReceipt-SameRace';
                p.gaEventAction = 'Bet Ticket Receipt Page Click';
                p.gaEventLabel = 'Bet Same Race';
                GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'siteClick', p);

                _resetRepeat();
                _clearSelection($scope.data.selectedBetType);
                _resetCurrentBetOptions($scope.data.selectedBetType, true);

                $scope.data.betEnabled = false;

                _goBack();
                betsCanceled = false;
            }

            function _checkInteger(value) {
                return (typeof value === 'number') && isFinite(value) && Math.floor(value) === value;
            }

            function _validateRepeatValue() {
                $scope.data.repeatValid = false;
                if (_checkInteger($scope.data.repeatTimes) && $scope.data.repeatTimes <= 25) {
                    betSlipWindowAlertsFac.closeAlertByIdentifier('invalidRepeatTime');
                    if ($rootScope.accountBalanceNumber && angular.isNumber($rootScope.accountBalanceNumber)) {
                        $scope.data.repeatValid = $rootScope.accountBalanceNumber >= parseFloat($scope.data.betValidation.betCost * $scope.data.repeatTimes);
                    } else {
                        $scope.data.repeatValid = true;
                    }
                } else if (_checkInteger($scope.data.repeatTimes) && $scope.data.repeatTimes > 25) {
                    $scope.data.repeatValid = false;
                    betSlipWindowAlertsFac.addAlert({
                        id: 'invalidRepeatTime',
                        type: 'warning',
                        closeable: false,
                        message: 'Bets can be repeated a maximum of x25'
                    });
                }
            }

            function _repeatBet() {
                _validateBet();

                var p = gtmDefaultBetSlipData();
                p.gaEventLabel = 'Repeat bet';
                p.eventLabel = 'BetTicketReceipt-RepeatBet';
                p.gaEventAction = 'Bet Ticket Receipt Page Click';
                GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'siteClick', p);

                $scope.data.showView = show.viewCONFIRMATION;
                $scope.data.showConfirmWarn = false;
                $scope.data.repeatTimes = 1;
                $scope.data.maxRepeatTimes = 9999;
                $scope.data.repeatBet = true;
                $scope.data.repeatValid = true;
            }

            function _closeBetslip() {
                closeBetSlipReceiptBtn = true;

                $window.close();
            }

            function _goBack() {
                if ($scope.data.showView === show.viewCONFIRMATION) {
                    var p = gtmDefaultBetSlipData();

                    p.gaEventCategory = 'Bet';
                    p.gaEventAction = 'Bet Cancelled';
                    p.gaEventLabel = _talentPickHostValid() ? "Talent Pick Bet Cancelled | " + $window.opener.talentPickHost : 'Standard Bet Cancelled';
                    if (betsCanceled) {
                        p.customerStatus = 'Returning';
                    } else {
                        p.customerStatus = 'First Time';
                        betsCanceled = true;
                    }

                    GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'betStandardCancelled', p);
                }

                $scope.data.showView = show.viewBET;
                $rootScope.restartBetslipSubscribe = true;
            }

            function _closeMessage() {
                $scope.data.showMessage = show.messageHIDE;
                return false;
            }

            function _setBettingInfo(fromRaceChange) {

                if (!$scope.data.currentRace) return false;

                $scope.data.formExpanded = previousState ? previousState.data.formExpanded : false;
                $scope.data.raceOpenForBetting = RaceStatusUtils.isRaceOpenForBetting($scope.data.currentRace);
                $scope.data.raceOpenForLiveVideo = RaceStatusUtils.isRaceOpenForLiveVideo($scope.data.currentRace);

                if (!$scope.data.raceOpenForBetting) {
                    $scope.data.currentRace.closedForBetting = true;
                }

                $scope.data.runners = $scope.data.currentRace.bettingInterests;

                $scope.data.wagerTypes = $scope.data.currentRace.wagerTypes;
                _updateMtp($scope.data.currentRace.postTime);

                if (!$scope.data.raceOpenForBetting) {
                    betSlipWindowAlertsFac.addAlert({
                        id: 'closed',
                        type: 'error',
                        closeable: true,
                        message: 'This race is now closed for betting. Please select a new race.'
                    });
                } else {
                    betSlipWindowAlertsFac.closeAlertByIdentifier('closed');
                }

                if (initialSetup) {
                    var wagerType = $scope.data.wagerTypes[0];
                    $scope.data.colsChecked = [];
                    $scope.data.currentBetSelections = [[]];
                    $scope.data.otherAmountShown = false;

                    if (!$rootScope.activeFeatures.useUamPreferencesBetslip) {
                        userPrefs = PreferencesCookieFac.getPreferences();
                    }

                    _readBetslipParameters();

                    // any changes by user will override default values (prefBetAmount too)
                    if (wagerType || fromRaceChange) {
                        _restoreBetOptions(wagerType);
                    }

                    if ($scope.data.selectedBetType) {
                        wagerType = $scope.data.selectedBetType;
                    }

                    // check if prefBetAmount exists and if it is a valid bet amount for current wager type
                    if (prefBetAmount && ($rootScope.userSession || readParameters)) {
                        if (wagerType && angular.isArray(wagerType.betAmounts)) {
                            if (userPrefs && userPrefs.bet_prefs && userPrefs.bet_prefs.useCustomBetAmount && wagerType.id === Number(userPrefs.bet_prefs.defaultBetType)) {
                                var size = wagerType.betAmounts.length;

                                $scope.data.betAmount = prefBetAmount;

                                for (var i = 0; i < size; ++i) {
                                    if (wagerType.betAmounts[i].amount == prefBetAmount) {
                                        $scope.data.betAmount = wagerType.betAmounts[i].amount;
                                        $scope.data.selectedBetAmount = wagerType.betAmounts[i];
                                        break;
                                    }
                                }

                                if (wagerType.id !== Number(userPrefs.bet_prefs.defaultBetType)) {
                                    $scope.data.betAmount = wagerType.betAmounts[i].amount;
                                    $scope.data.selectedBetAmount = wagerType.betAmounts[i];
                                }
                            } else if (userPrefs && userPrefs.bet_prefs && userPrefs.bet_prefs.useCustomBetAmount && wagerType.id !== Number(userPrefs.bet_prefs.defaultBetType) && userPrefs.bet_prefs.default_bet_amount[wagerType.id]) {
                                var amount = wagerType.betAmounts.find(
                                    function (betAmount) {
                                        return betAmount.amount == userPrefs.bet_prefs.default_bet_amount[wagerType.id];
                                    });
                                if (!amount) {
                                    $scope.data.betAmount = userPrefs.bet_prefs.default_bet_amount[wagerType.id];
                                    $scope.data.selectedBetAmount = wagerType.betAmounts[wagerType.betAmounts.length - 1];
                                    $scope.data.otherAmountShown = true;
                                } else {
                                    $scope.data.betAmount = amount.amount;
                                    $scope.data.selectedBetAmount = amount;
                                }
                            } else {
                                $scope.data.betAmount = wagerType.betAmounts[0].amount;
                                $scope.data.selectedBetAmount = wagerType.betAmounts[0];
                            }
                            $scope.data.selectedBetAmounts = wagerType.betAmounts;

                        }

                        // This is to guarantee that we have a value that matches one of these wager amounts.
                        // For some races, e.g. Hong-Kong, the preferred bet amount is not one of the values presented in
                        // the wager amounts list.
                        if (!$scope.data.betAmount || !$scope.data.selectedBetAmount) {
                            var betAmountObj = AmountOptionsFac.getClosestOrEqualAmountObject({amount: prefBetAmount},
                                (wagerType || {}).betAmounts, 'amount');
                            if(betAmountObj && typeof betAmountObj === 'object'){
                                $scope.data.betAmount = betAmountObj.amount;
                                $scope.data.selectedBetAmount = betAmountObj;
                                $scope.data.otherAmount = parseFloat(betAmountObj.amount);
                            }
                        }
                    }

                    if (parameters && parameters.betamount) {
                        var parameterBetAmount = parseFloat(parameters.betamount);
                        var betAmount = wagerType.betAmounts.find(
                            function (betAmount) {
                                return betAmount.amount === parameterBetAmount;
                            });
                        $scope.data.betAmount = parameterBetAmount;
                        $scope.data.selectedBetAmount = betAmount || $scope.data.selectedBetAmounts[$scope.data.selectedBetAmounts.length - 1];
                        $scope.data.otherAmount = parameterBetAmount;
                        $scope.data.otherAmountShown = !betAmount;

                    }

                    readParameters = false;
                    $scope.data.previousSelectedBeType = $scope.data.selectedBetType;
                    initialSetup = false;
                    _validateBet();
                }
            }

            function _getPrefBetType(id) {
                for (var i = 0; i < $scope.data.wagerTypes.length; ++i) {
                    if ($scope.data.wagerTypes[i].id == id) {
                        return $scope.data.wagerTypes[i];
                    }
                }
                return null;
            }

            function _restoreBetOptions(wagerType) {
                var currentBetType = null;

                if (previousState
                    && previousState.data.currentRace
                    && previousState.data.currentRace.id == $scope.data.currentRace.id) {
                    currentBetType = previousState.data.selectedBetType;
                } else {
                    if (prefBetType && ($rootScope.userSession || readParameters)) {
                        currentBetType = prefBetType;
                    } else {
                        currentBetType = wagerType;
                    }
                }

                var validBetOption = _betTypeInCurrentBets(currentBetType);
                if (validBetOption) {
                    $scope.data.selectedBetType = validBetOption;
                    _resetCurrentBetOptions(validBetOption);
                } else {
                    _resetCurrentBetOptions(wagerType);
                }
            }

            function _betTypeInCurrentBets(currentBetType) {
                var isInCurrentBets = null;

                for (var i = 0; i < $scope.data.wagerTypes.length; i++) {
                    if (angular.equals($scope.data.wagerTypes[i], currentBetType)) {
                        isInCurrentBets = $scope.data.wagerTypes[i];
                        break;
                    }
                }

                return isInCurrentBets;
            }

            function _restoreState() {
                if (previousState
                    && previousState.data.currentRace
                    && previousState.data.currentRace.id == $scope.data.currentRace.id) {

                    $scope.data.currentSelectedCol = previousState.data.currentSelectedCol;
                    $scope.data.colsChecked = previousState.data.colsChecked;
                    $scope.data.currentBetSelections = previousState.data.currentBetSelections;

                    if (previousState.data.selectedBetAmounts) {
                        $scope.data.selectedBetAmounts = previousState.data.selectedBetAmounts;
                    }
                    if (previousState.data.selectedBetAmount) {
                        $scope.data.selectedBetAmount = previousState.data.selectedBetAmount;
                    }
                    if (previousState.data.betAmount) {
                        $scope.data.betAmount = previousState.data.betAmount;
                    }
                    if (previousState.data.otherAmount) {
                        $scope.data.otherAmount = previousState.data.otherAmount;
                    }
                    if (previousState.data.minBetAmount) {
                        $scope.data.minBetAmount = previousState.data.minBetAmount;
                    }

                    $scope.data.otherAmountShown = previousState.data.otherAmountShown;
                }
                previousState = null;
                StatePersistenceFac.resetState("bt");
            }

            function _setRunnersSaddles() {

                var runnersSaddlesByLeg = [];

                if (_.isUndefined($scope.data) || _.isUndefined($scope.data.currentBetSelections)) {
                    return;
                }

                $scope.data.currentBetSelections.forEach(function (leg, index) {
                    var selectedRunners = leg; //array of numbers
                    //convert selectedRunners array of numbers of array of strings
                    selectedRunners = selectedRunners.map(function (selectedRunner) {
                        return selectedRunner.toString();
                    });

                    var runners = $scope.data.isLeg ? $scope.data.legRacesRunners[index] : $scope.data.runners;

                    //intersect selectedRunners with list of runners
                    var auxSelectedRunnersSaddle = runners.filter(function (runner) {
                        var selectedRunnerId = runner.horseID.replace(/[^\d.]/g, '');
                        return selectedRunners.indexOf(runner.horseID) !== -1 ||
                            selectedRunners.indexOf(selectedRunnerId) !== -1;
                    });

                    //map runners to runnerSaddles
                    auxSelectedRunnersSaddle = auxSelectedRunnersSaddle.map(function (runner) {
                        return new RunnerSaddleModel(
                            runner.saddleColor,
                            runner.numberColor,
                            runner.horseID,
                            runner.horseName,
                            runner.bettingInterestNumber
                        );
                    });
                    runnersSaddlesByLeg.push(auxSelectedRunnersSaddle);
                });

                $scope.data.selectedSaddle = runnersSaddlesByLeg;
            }

            function _getTempBetAmount() {
                var tempBetAmount = $scope.data.betValidation && $scope.data.betValidation.betCost ? $scope.data.betValidation.betCost : $scope.data.betAmount;

                return _roundAmount(tempBetAmount);
            }

            function _sendGTMBetSuccess(placedBetData) {
                var p = gtmDefaultBetSlipData();
                p.gaEventCategory = 'Bet';
                p.gaEventAction = 'Bet Success';
                p.gaEventLabel = (placedBetData && placedBetData.serialNumber) ? placedBetData.serialNumber : undefined;
                p.betAmount = _getTempBetAmount();
                p.customerStatus = 'First Time';
                p.runnerAmount = $scope.data.betAmount;
                GTMFac.GTMEvent().send($rootScope, 'bet', p);
            }

            function _sendGTMBetRepeat() {
                var p = gtmDefaultBetSlipData();
                p.gaEventLabel = 'Repeat bet | ' + $scope.data.repeatTimes;
                p.eventLabel = 'BetTicket-RepeatBet';
                GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'siteClick', p);
            }

            function _sendGTMBetError(errorCode) {
                var trackName = $scope.data.currentRace && $scope.data.currentRace.trackName ? $scope.data.currentRace.trackName : '';
                var amount = $scope.data.selectedBetAmount && $scope.data.selectedBetAmount.amount ? _roundAmount($scope.data.selectedBetAmount.amount) : '';
                var raceNumber = $scope.data.currentRace && $scope.data.currentRace.raceNumber ? $scope.data.currentRace.raceNumber : '';
                var betType = $scope.data.selectedBetType && $scope.data.selectedBetType.name ? $scope.data.selectedBetType.name : '';
                var sectionName = 'Bet Ticket | Bet Ticket Page';
                if ($scope.data.showView === show.viewCONFIRMATION) {
                    sectionName = 'Bet Ticket | Bet Ticket Confirmation Page';
                } else if ($scope.data.showView === show.viewRECEIPT) {
                    sectionName = 'Bet Ticket | Bet Ticket Receipt Page';
                }

                var event = {
                    event: "bet",
                    gaEventCategory: "Bet",
                    gaEventAction: "Bet Error",
                    gaEventLabel: errorCode,
                    module: sectionName,
                    tag: $scope.data.currentBetSelections.join(", "),
                    trackName: trackName,
                    raceNumber: raceNumber,
                    betId: undefined,
                    betAmount: amount,
                    betType: betType,
                    sport: $rootScope.isGreyhoundRace ? "Greyhounds Racing" : "Horse Racing",
                    repeatBet: $scope.data.repeatBet,
                    runnerAmount: $scope.data.betAmount
                };

                GTMFac.GTMEvent().send($rootScope, 'betStandardError', event);
            }

            function _createApptentiveConversation(user) {
                if (typeof window !== "undefined" && window.ApptentiveSDK) {
                    window.ApptentiveSDK.createConversation({
                        app_release: {
                            version: "1.0.0"
                        },
                        person: {
                            custom_data: {
                                account_id: user.accountNumber,
                                first_name: user.firstName,
                                last_name: user.lastName,
                                email: user.emailAddress,
                                day_of_birthday: "",
                                home_city: user.homeAddress
                                ? user.homeAddress.City : "",
                                gender: "",
                                country: "",
                                phone: "",
                                full_home_address: "",
                                key_account_yn: false,
                                value_band: ""
                            }
                        },
                        device: {
                            custom_data: {
                                flash: true,
                                es6: false
                            }
                        }
                    });
                }

            }

            function _placeBet() {
                $scope.isPlacingBet = true;

                var repeatBet = (($rootScope.activeFeatures.betSlipRepeatBet ? $rootScope.activeFeatures.betSlipRepeatBet : false) && $scope.data.repeatBet);

                $scope.data.betValidation.repeat = 1;

                if (repeatBet) {
                    $scope.data.betValidation.repeat = $scope.data.repeatTimes;
                    $scope.data.repeatValid = true;
                    _sendGTMBetRepeat();
                }

                //TODO need to pass my selection instead of using betValidation.wagers
                BetsSvc.placeBet($scope.data.betValidation, $scope.data.currentRace).then(
                    function (placedBetData) {
                        _sendGTMBetSuccess(placedBetData);

                        $scope.data.showMessage = show.messageSUCCESS;
                        $scope.data.showView = show.viewRECEIPT;

                        $rootScope.$emit('bet_placed', $scope.data.currentRace);

                        $scope.isPlacingBet = false;
                        betsSubmitted = false;

                        // Apptentive event
                        _createApptentiveConversation($rootScope.user);
                        if (typeof window !== "undefined" && window.ApptentiveSDK) {
                            window.ApptentiveSDK.engage("Places bet");
                        }
                    },
                    function (betError) {
                        $scope.data.errorMessage = betError.errorMessageKey;
                        _sendGTMBetError(betError.errorCode);

                        if (betError.multiBet) {
                            $scope.isPlacingBet = false;
                            $scope.isPlacingBet = false;
                            _showErrorMessage('multipleBetError', betError.message, 'warning');
                            $rootScope.$emit('bet_placed', $scope.data.currentRace);
                            betsSubmitted = false;
                            _sendGTMBetSuccess();
                            return;
                        }

                        // if error inSufficient balance allow user to go back
                        if (betError.errorCode === "136518") {
                            _disableBet();
                            $scope.isPlacingBet = false;
                            $scope.data.infoMessage = betError.message;
                            $scope.data.infoTitle = 'Insuficient Funds';
                            _showErrorMessage('insuficientFunds', betError.message);
                            return;
                        }

                        $scope.data.showMessage = show.messageERROR;
                        $scope.data.showView = show.viewRECEIPT;

                        $scope.isPlacingBet = false;
                        betsSubmitted = false;
                    }
                );
            }

            function _talentPickHostValid() {
                return $window.opener && $window.opener.talentPickHost && $window.opener.talentPickHost !== "";
            }

            function _confirmBet() {
                $scope.data.isBetConfirmed = !$scope.data.isBetConfirmed;
                userPrefs.show_bet_confirm = $scope.data.isBetConfirmed ? 1 : 0;

                UserProfileSvc.setRequestBetConfirmationPreference($scope.data.isBetConfirmed)
                    .then(function () {
                            var p = gtmDefaultBetSlipData();
                            p.gaEventLabel = $scope.data.isBetConfirmed ? 'Uncheck No Confirmation Window' : 'No Confirmation Window';
                            p.eventLabel = 'BetTicket-Confirmation';
                            GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'siteClick', p);
                        },
                        function () {
                            //error
                        });
            }

            function _submitBet() {
                if($scope.data.blockAnyBetting){
                    return null;
                }
                _validateBet();

                if (($scope.data.showView === show.viewBET && !$scope.data.isBetConfirmed) || $scope.data.showView === show.viewCONFIRMATION) {
                    var p = gtmDefaultBetSlipData();

                    p.gaEventCategory = 'Bet';
                    p.gaEventAction = 'Bet Submit';
                    p.gaEventLabel = _talentPickHostValid() ? "Talent Pick Bet Submitted | " + $window.opener.talentPickHost : 'Standard Bet Submitted';
                    p.betAmount = _getTempBetAmount();
                    if (betsSubmitted) {
                        p.customerStatus = 'Returning';
                    } else {
                        p.customerStatus = 'First Time';
                        betsSubmitted = true;
                    }

                    GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, "betStandardSubmit", p);
                }

                if (!$rootScope.userSession) {
                    //Message placeholder, until is returned from cms
                    $scope.data.infoMessage = 'Please login in order to bet';
                    $scope.data.infoTitle = 'Login Required';

                    _disableBet();
                    betSlipWindowAlertsFac.addAlert(
                        {
                            id: 'noSession',
                            type: 'error',
                            closeable: true,
                            message: $scope.data.infoMessage
                        }
                    );

                } else {
                    _finaliseBet();
                }
            }

            /*
             * param id: String
             * param message: String
             * param type: String error | warning
             * Show error message and disable bet
             */
            function _showErrorMessage(id, message, type) {
                type = typeof type !== 'undefined' ? type : 'error';
                betSlipWindowAlertsFac.addAlert({
                    id: id,
                    type: type,
                    message: message,
                    closeable: false
                });
            }


            /*
             * after all checks place bet and send gtm event
             */
            function _finaliseBet() {
                _setRunnersSaddles();

                if ($scope.data.showView === show.viewBET && $scope.data.isBetConfirmed) {
                    var gtmEvent = gtmDefaultBetSlipData();
                    gtmEvent.gaEventCategory = 'Bet';
                    gtmEvent.gaEventAction = 'Bet Start';
                    gtmEvent.gaEventLabel = _talentPickHostValid() ? "Talent Pick Bet Start | " + $window.opener.talentPickHost : 'Standard Bet Start';
                    gtmEvent.customerStatus = betsCanceled ? 'Returning' : 'First Time';
                    GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'betStandardStart', gtmEvent);

                    $scope.data.showView = show.viewCONFIRMATION;
                } else {
                    _placeBet();
                }
            }

            function _disableBet() {
                $scope.data.betEnabled = false;
            }

            function _enableBet() {
                $scope.data.betEnabled = true;
            }

            function _betTypeChanged(wager) {
                betSlipWindowAlertsFac.clearAlertsExcept("bettingForbidden");
                _resetCurrentBetOptions(wager);
                _adjustSizeFixRender();
            }

            function _clearSelection(wager) {
                var i = null;
                $scope.data.currentSelectedCol = null;
                $scope.data.colsChecked = [];

                if (parameters.fromRunnerClick === "true"
                    && angular.isArray($scope.data.currentBetSelections)
                    && verifiedBetTypeWhenFromRunnerClick == false
                    && $scope.data.currentBetSelections.length < wager.columnCount && !readParameters) {

                    for (i = 0; i < wager.columnCount; i++) {
                        $scope.data.currentBetSelections[i] = [];
                    }
                    verifiedBetTypeWhenFromRunnerClick = true;
                } else if (!readParameters || !angular.isArray($scope.data.currentBetSelections)) {
                    $scope.data.currentBetSelections = [];

                    for (i = 0; i < wager.columnCount; i++) {
                        $scope.data.currentBetSelections.push([]);
                    }
                } else if (angular.isArray($scope.data.currentBetSelections) && $scope.data.currentBetSelections.length < wager.columnCount) {
                    for (i = 0; i < wager.columnCount; i++) {
                        if (!$scope.data.currentBetSelections[i]) {
                            $scope.data.currentBetSelections[i] = [];
                        }
                    }
                }
            }

            function _resetCurrentBetOptions(wager, usePreviousChosenBetAmount) {
                var previousWager = $scope.data.previousSelectedBeType;
                var previousBetAmount = $scope.data.betAmount;

                if (wager) {
                    if (previousWager && previousWager.id > 71) {
                        _clearSelection(wager);
                    } else if (wager.id > 71) {
                        _clearSelection(wager);
                    } else if (!previousWager) {
                        _clearSelection(wager);
                    }

                    $scope.data.previousSelectedBeType = $scope.data.selectedBetType;

                    $scope.data.selectedBetAmounts = wager.betAmounts;

                    $scope.data.minBetAmount = wager.minBetAmount;

                    $scope.data.runners = $scope.data.currentRace.bettingInterests;

                    $scope.data.otherAmountShown = false;

                    if (angular.isArray(wager.betAmounts) && wager.betAmounts.length && !usePreviousChosenBetAmount) {
                        if (userPrefs && userPrefs.bet_prefs) {
                            var defaultBetAmount = Number(userPrefs.bet_prefs.default_bet_amount[wager.id]);
                            if (pickWagerType.includes(wager.id)) {
                                defaultBetAmount = Number(userPrefs.bet_prefs.default_bet_amount.P);
                            } else if (trifectaWagerType.includes(wager.id)) {
                                defaultBetAmount = Number(userPrefs.bet_prefs.default_bet_amount["160"]);
                            } else if (exactaWagerType.includes(wager.id)) {
                                defaultBetAmount = Number(userPrefs.bet_prefs.default_bet_amount["110"]);
                            } else if (superfectaWagerType.includes(wager.id)) {
                                defaultBetAmount = Number(userPrefs.bet_prefs.default_bet_amount["210"]);
                            } else if (superhighfiveWagerType.includes(wager.id)) {
                                defaultBetAmount = Number(userPrefs.bet_prefs.default_bet_amount["260"]);
                            }

                            // If a customer’s betting preference is higher than the maximum allowed wager amount,
                            // the bet ticket should default to the maximum allowed wager amount
                            if(defaultBetAmount > wager.maxBetAmount){
                                defaultBetAmount = wager.maxBetAmount;
                                prefBetAmount = wager.maxBetAmount;
                            }

                            if (userPrefs.bet_prefs.useCustomBetAmount && defaultBetAmount) {
                                var amount = wager.betAmounts.find(
                                    function (betAmount) {
                                        return betAmount.amount === defaultBetAmount;
                                    });
                                $scope.data.betAmount = defaultBetAmount;
                                $scope.data.selectedBetAmount = amount;
                                $scope.data.otherAmount = defaultBetAmount;
                                $scope.data.otherAmountShown = !amount;

                                if (!amount) {
                                    $scope.data.selectedBetAmount = $scope.data.selectedBetAmounts[$scope.data.selectedBetAmounts.length - 1];
                                }
                            } else {
                                $scope.data.betAmount = wager.betAmounts[0].amount;
                                $scope.data.selectedBetAmount = wager.betAmounts[0];
                                $scope.data.otherAmount = wager.betAmounts[0].amount;
                            }
                        } else if (!$scope.data.betAmount && !$scope.data.selectedBetAmount) {
                            // Reaching here means that the preferred bet amount wasn't found in the list of bet
                            // amounts of the first wager type (see "_setBettingInfo" code after "if(initialSetup)")
                            // This is to guarantee that we have a value that matches one of these wager amounts.
                            // For some races, e.g. Hong-Kong, the preferred bet amount is not one of the values presented in
                            // the wager amounts list.
                            var betAmountObj = AmountOptionsFac.getClosestOrEqualAmountObject({amount: prefBetAmount},
                                wager.betAmounts, 'amount');
                            $scope.data.betAmount = betAmountObj.amount;
                            $scope.data.selectedBetAmount = betAmountObj;
                            $scope.data.otherAmount = parseFloat(betAmountObj.amount);
                        } else {
                            var wagerHasAmount = wagerContainsBetAmount($scope.data.betAmount || 0);
                            var selectedAmountIsDefault = wagerContainsDefaultAmout(wager.betAmounts, $scope.data.betAmount || 0);

                            if (!wagerHasAmount || (!!wagerHasAmount && !selectedAmountIsDefault)) {
                                $scope.data.betAmount = wager.betAmounts[0].amount;
                                $scope.data.selectedBetAmount = wager.betAmounts[0];
                            }
                        }
                    } else {
                        var amountt = wager.betAmounts.find(
                            function (betAmount) {
                                return betAmount.amount === previousBetAmount;
                            });
                        $scope.data.betAmount = previousBetAmount;
                        $scope.data.selectedBetAmount = amountt;
                        $scope.data.otherAmount = previousBetAmount;
                        $scope.data.otherAmountShown = !amountt;

                        if (!amountt) {
                            $scope.data.selectedBetAmount = $scope.data.selectedBetAmounts[$scope.data.selectedBetAmounts.length - 1];
                        }
                    }

                    _restoreState();
                    _validateBet();
                }
            }

            function wagerContainsBetAmount(amount) {
                if (amount < 1 && $scope.data.minBetAmount < 1 && _isMultipleOfMinBetAmount(amount)) {
                    return true;
                }

                if (amount >= $scope.data.minBetAmount && amount >= 1) {
                    return true;
                }

                $scope.data.selectedBetAmount = $scope.data.selectedBetAmounts[0];
                $scope.data.betAmount = $scope.data.selectedBetAmount.amount;
                $scope.data.otherAmount = parseFloat($scope.data.selectedBetAmount.amount);
                $scope.data.otherAmountShown = false;

                return false;
            }

            function wagerContainsDefaultAmout(betAmounts, amount) {
                return !!_.find(betAmounts, function (betAmount) {
                    return betAmount.amount && betAmount.amount === amount;
                });
            }

            function _filterAmountOptions() {
                return AmountOptionsFac.removeOtherAmountOptionForHKRaces($scope.data.currentRace);
            }

            function _betAmountChanged() {
                betSlipWindowAlertsFac.closeAlertByIdentifier('incorrectBetSize');
                $scope.data.otherAmount = $scope.data.selectedBetAmount.amount ? parseFloat($scope.data.selectedBetAmount.amount) : null;

                var p = gtmDefaultBetSlipData();
                p.eventLabel = $scope.data.otherAmount === null ? 'BetTicket-OtherAmount' : 'BetTicket-DefaultAmount';
                p.gaEventLabel = $scope.data.otherAmount === null ? 'Select Other Amount' : 'Select Default Amount';
                GTMFac.GTMEvent().send($rootScope, 'siteClick', p);

                if (!$scope.data.otherAmount) {
                    $scope.data.betAmount = 0;
                    $scope.data.otherAmountShown = true;
                } else {
                    $scope.data.betAmount = $scope.data.otherAmount;
                    $scope.data.otherAmountShown = false;
                }
                _validateBet();
            }

            function _isMultipleOfMinBetAmount(value) {
                var intPart = parseInt(value, 10),
                    decPart = parseInt((value - Math.floor(value)) * 100, 10),
                    minimumAmount = $scope.data.minBetAmount,
                    minDecPart = parseInt((minimumAmount - Math.floor(minimumAmount)) * 100, 10),
                    isMultiple = minDecPart == 0 ? true : decPart % minDecPart == 0,
                    remainder = null,
                    correctValue;

                if (!isMultiple) {
                    remainder = (decPart % minDecPart);
                    if (remainder <= (minDecPart / 2) && decPart - remainder > 0) {
                        decPart = decPart - remainder;
                    } else {
                        decPart = decPart + minDecPart - remainder;
                    }
                }

                correctValue = intPart + (decPart / 100);

                return correctValue === value;
            }

            function _otherAmountChanged(value, valid, isBlur) {

                if (isBlur) {
                    betSlipWindowAlertsFac.closeAlertByIdentifier('incorrectBetSize');
                    _enableBet();
                }

                $scope.data.otherAmountStep = value < 1 && $scope.data.minBetAmount < 1 && value > 0 ? $scope.data.minBetAmount : 1;

                $scope.data.betAmount = 0;

                if (!value && !valid) {
                    if (isBlur) {
                        _showInfoMessage($scope.data.incorrectAmountValueMessage);
                    }
                } else if (value < $scope.data.minBetAmount) {
                    if (isBlur) {
                        _showInfoMessage($scope.data.minimumBetAmountMessage + ' ' + $filter('currency')($scope.data.minBetAmount, "$"));
                    }
                } else {
                    if (value > 0 && value < 1 && $scope.data.minBetAmount < 1 && !_isMultipleOfMinBetAmount(value)) {
                        if (isBlur) {
                            _showInfoMessage($scope.data.nearestAmountsMessage + ' ' + _getsNearestDecimalValues(value)[0] + ' and ' + _getsNearestDecimalValues(value)[1]);
                        }
                    } else if (value > 1 && (value % 1 != 0)) {
                        if (isBlur) {
                            _showInfoMessage($scope.data.nearestAmountsMessage + ' ' + Math.floor(value) + ' and ' + (Math.floor(value) + 1));
                        }
                    } else {
                        $scope.data.betAmount = value;
                    }
                }

                _validateBet();
            }

            function _getsNearestDecimalValues(value) {
                var decPart = parseInt((value - Math.floor(value)) * 100, 10);
                var minDecPart = parseInt(($scope.data.minBetAmount - Math.floor($scope.data.minBetAmount)) * 100, 10);
                var remainder = (decPart % minDecPart);
                return [(Math.floor((decPart - remainder) / 10) / 10).toFixed(1), ((Math.floor((decPart - remainder) / 10) / 10) + $scope.data.minBetAmount).toFixed(1)];
            }

            function _countRunners() {
                var runners = $scope.data.legRacesRunners.length === 0 ? $scope.data.runners : $scope.data.legRacesRunners[$scope.data.activeTab],
                    array = [];

                runners = runners.filter(function (runner) {
                    var invalid = false;

                    if (array.indexOf(runner.bettingInterestNumber) >= 0 || runner.currentOdds.Numerator == "Scr") {
                        invalid = true;
                    }

                    array.push(runner.bettingInterestNumber);

                    if (invalid) {
                        return null;
                    }
                    return runner;
                });

                return runners.length;
            }

            function _validateBet() {
                $scope.data.betValidation = BetsSvc.calculateBetTotal(
                    $scope.data.betAmount,
                    $scope.data.selectedBetType,
                    $scope.data.currentBetSelections
                );

                $scope.data.betEnabled = false;
                if ($scope.data.betValidation.betCost > 0) {
                    if ($scope.data.selectedBetType.isKey || (!$scope.data.betValidation.errorResultsStr)) {
                        $scope.data.betEnabled = true;
                        betSlipWindowAlertsFac.closeAlertByIdentifier('insuficientFunds');
                    }
                }
            }

            function _checkIfResumit() {
                if (resubmit) {
                    resubmit = false;
                    $scope.events.submitBet();
                }
            }

            function _pushRaceInfo() {
                $rootScope.raceInfoModal = $uibModal.open({
                    backdropClass: 'tvgmodal-backdrop',
                    windowTemplateUrl: 'js/modules/Utilities/templates/modal-window.html',
                    windowClass: 'race-info',
                    template: '<div class="race-info-header">Race Info</div><button class="close-btn" ng-click="events.closeRaceInfo()"></button><raceinfo></raceinfo>',
                    scope: $scope
                });
            }

            function _changeTab(tabName) {
                $scope.raceInfoSelectedTab = tabName;
                var obj = {
                    RIT_H: 'Free Handicapping',
                    RIT_P: 'Probables',
                    RIT_C: 'Changes',
                    RIT_PLS: 'Pools',
                    RIT_W: 'Will Pays'
                };

                var p = {};
                p.screenName = 'Bet Ticket Page';
                p.sectionName = 'Races | ' + obj[tabName];

                if (typeof ga !== 'undefined') {
                    ga('send', 'pageview', {
                        title: p.sectionName
                    });
                }

                if (tabName && obj[tabName]) {
                    GTMFac.sendGTMEvent($scope, p.event, p);
                }
            }

            function _closeRaceInfo() {
                if ($rootScope.raceInfoModal) {
                    $rootScope.raceInfoModal.close();
                    $rootScope.raceInfoModal = null;
                }
            }

            function _showInfoMessage(message) {
                betSlipWindowAlertsFac.clearAlertsExcept("bettingForbidden");
                $scope.data.infoMessage = message;

                _disableBet();
                betSlipWindowAlertsFac.addAlert(
                    {
                        id: 'incorrectBetSize',
                        type: 'warning',
                        closeable: false,
                        message: $scope.data.infoMessage
                    }
                );
            }

            function _closeInfoMessage() {

                if (confirmDialog) {
                    confirmDialog.close();
                    confirmDialog = null;
                }
            }

            function _reloadUserPreferencesAfterLoggingIn() {
                //if it is a resubmit we should not be updating the controller with the user preferences
                if (!resubmit) {
                    previousState = null;
                    onFirstTimeOpen = true;
                    initialSetup = true;
                    if ($rootScope.activeFeatures.useUamPreferencesBetslip) {
                        PreferencesFac.getUserPreferences().then(function (preferences) {
                            userPrefs = preferences;
                        }).finally(_setBettingInfo);
                    } else {
                        userPrefs = PreferencesCookieFac.getPreferences();
                        _setBettingInfo();
                    }
                }
            }

            function _isScratchedHorseInList() {
                var runners = $scope.data.legRacesRunners.length === 0 ? $scope.data.runners : $scope.data.legRacesRunners[$scope.data.activeTab];

                if (!Array.isArray(runners)) {
                    return false;
                }
                return runners.some(function (runner) {
                    return runner.scratched;
                });
            }

            function _removeScratchedHorsesFromSelection() {
                var removedScratched = false;
                var runners = $scope.data.legRacesRunners.length === 0 ? _getRunnersArray($scope.data.runners, $scope.data.selectedBetType.columnCount) : $scope.data.legRacesRunners;
                if (!Array.isArray(runners)) {
                    return;
                }
                runners.forEach(function (runnerLeg, runnerLegKey) {

                    if (!Array.isArray(runnerLeg)) {
                        return;
                    }

                    var betSelections = $scope.data.currentBetSelections[runnerLegKey];

                    if (!Array.isArray(betSelections)) {
                        return;
                    }

                    betSelections.forEach(function (betSelection, betSelectionKey) {
                        var validRunner = _.filter(runnerLeg, function (runner) {
                            if (betSelection === runner.bettingInterestNumber && _areAllRunnersScratched(runner)) {
                                //if there is a scratchet horse in the bet selection, recalculate bet cost
                                removedScratched = true;
                            }
                            return (betSelection === runner.bettingInterestNumber && !_areAllRunnersScratched(runner));
                        });
                        if (validRunner.length === 0) {
                            $scope.data.currentBetSelections[runnerLegKey].splice(betSelectionKey, 1);
                        }
                    });
                });

                if (removedScratched) {
                    //if there is a scratchet horse in the bet selection, recalculate bet cost
                    _validateBet();
                }
            }

            function _getRunnersArray(runners, times) {
                var runnersArray = [];
                for (var i = 0; i < times; i++) {
                    runnersArray.push(runners);
                }
                return runnersArray;
            }

            function _toggleSelection(betInterest, dsIndex) {
                if ($scope.data.currentRace.closedForBetting) {
                    return;
                }
                var colOfSelections = $scope.data.currentBetSelections[dsIndex],
                    selectionIndex = colOfSelections.indexOf(betInterest);

                if ($scope.data.selectedBetType.isKey) {
                    if (dsIndex == 0) {
                        if (selectionIndex < 0 && !$scope.data.colsChecked[1]) {
                            colOfSelections = [betInterest];

                            var secondColOfSelections = $scope.data.currentBetSelections[1],
                                selectionIndexOnSecondCol = secondColOfSelections.indexOf(betInterest);

                            if (selectionIndexOnSecondCol >= 0) {
                                secondColOfSelections[selectionIndexOnSecondCol] = null;
                                secondColOfSelections = secondColOfSelections.filter(function (item) {
                                    return item !== null;
                                });
                                $scope.data.currentBetSelections[1] = secondColOfSelections;
                                $scope.data.colsChecked[1] = false;
                            }
                        } else if (selectionIndex < 0 && $scope.data.colsChecked[1]) {
                            colOfSelections = [betInterest];
                            $scope.data.currentBetSelections[dsIndex] = [betInterest];
                            _toggleAll(false, 1);
                        } else {
                            colOfSelections = [];
                            $scope.data.colsChecked[dsIndex] = false;
                        }
                    } else if (dsIndex == 1) {
                        if (selectionIndex < 0) {
                            colOfSelections.push(betInterest);
                            var firstColOfSelections = $scope.data.currentBetSelections[0],
                                selectionIndexOnFirstCol = firstColOfSelections.indexOf(betInterest);

                            if (selectionIndexOnFirstCol >= 0) {
                                firstColOfSelections[selectionIndexOnFirstCol] = null;
                                firstColOfSelections = firstColOfSelections.filter(function (item) {
                                    return item !== null;
                                });
                                $scope.data.currentBetSelections[0] = firstColOfSelections;
                            }
                        } else {
                            colOfSelections[selectionIndex] = null;
                            $scope.data.colsChecked[dsIndex] = false;
                        }
                    }
                } else {
                    if (selectionIndex < 0) {
                        colOfSelections.push(betInterest);
                    } else {
                        colOfSelections[selectionIndex] = null;
                        $scope.data.colsChecked[dsIndex] = false;
                    }
                }

                colOfSelections = colOfSelections.filter(function (item) {
                    return item !== null;
                });

                $rootScope.$emit('runnerSelectionsChanged',
                    $scope.data.currentRace,
                    $scope.data.selectedBetType.columnCount,
                    dsIndex,
                    colOfSelections
                );

                $scope.data.currentBetSelections[dsIndex] = colOfSelections;

                if ($scope.data.selectedBetType.isKey) {
                    var i = (dsIndex > 0 ? dsIndex : dsIndex + 1);
                    $scope.data.colsChecked[i] = _countRunners() == ($scope.data.currentBetSelections[0].length + $scope.data.currentBetSelections[i].length);
                } else {
                    $scope.data.colsChecked[dsIndex] = _countRunners() == $scope.data.currentBetSelections[dsIndex].length;
                }

                _validateBet();
            }

            function _toggleAll(checked, dsIndex) {
                if ($scope.data.currentRace.closedForBetting) {
                    return;
                }

                var runners = $scope.data.isLeg ? $scope.data.legRacesRunners[dsIndex] : $scope.data.runners;

                var colOfSelections = $scope.data.currentBetSelections[dsIndex],
                    keyBI = null,
                    alreadyUsed = {};

                checked = typeof checked == 'undefined' ? false : checked;

                if (!checked) {
                    $scope.data.colsChecked[dsIndex] = true;

                    if ($scope.data.selectedBetType.isKey) {
                        keyBI = $scope.data.currentBetSelections[0][0];
                    }

                    // select all runners that are not scratched and not a key
                    // bet, without repeating ids
                    colOfSelections = runners.filter(function (runner) {
                        var isScratched = _areAllRunnersScratched(runner);
                        var isKeyBI = (runner.bettingInterestNumber === keyBI);
                        var isUnique = !alreadyUsed[runner.bettingInterestNumber];
                        var isValid = isUnique && !isScratched && !isKeyBI;

                        if (isValid) {
                            alreadyUsed[runner.bettingInterestNumber] = true;
                        }

                        return isValid;
                    }).map(function (runner) {
                        return runner.bettingInterestNumber;
                    });
                } else {
                    $scope.data.colsChecked[dsIndex] = false;
                    colOfSelections = [];
                }
                $scope.data.currentBetSelections[dsIndex] = colOfSelections;

                _validateBet();

                var p = gtmDefaultBetSlipData();
                p.gaEventLabel = !checked ? 'Select All Horses' : 'UnSelect All Horses';
                p.eventLabel = !checked ? 'BetTicket-SelectAll' : 'BetTicket-UnSelectAll';
                GTMFac.GTMEvent().send($rootScope, 'siteClick', p);
            }

            function _toggleTab(tab) {
                $scope.data.activeTab = tab - 1;
            }

            function _isSelected(betInterest, dsIndex) {
                return angular.isArray($scope.data.currentBetSelections) && $scope.data.currentBetSelections.length > 0 ? $scope.data.currentBetSelections[dsIndex].indexOf(betInterest) >= 0 : false;
            }

            function _isSelectedAll(dsIndex) {
                return $scope.data.colsChecked[dsIndex];
            }

            function _isActiveTab(tab) {
                return tab - 1 == $scope.data.activeTab;
            }

            function _isSelectable(betInterest, dsIndex) {
                if ($scope.data.selectedBetType.isKey && !_isSelected(betInterest, dsIndex)) {
                    var col = (dsIndex == 0 ? 1 : 0);
                    return !_isSelected(betInterest, col);
                }
                return true;
            }

            function _legHasRunner(row, col) {
                return angular.isDefined($scope.data.legRacesRunners[col][row]);
            }

            function betSlipCloseEvent() {
                var p = gtmDefaultBetSlipData();

                if (closeBetSlipReceiptBtn) {
                    p.customerStatus = 'First Time';
                    p.gaEventLabel = 'Close Bet Ticket';
                    p.eventLabel = 'BetTicketReceipt-Close';
                    p.gaEventAction = 'Bet Ticket Receipt Page Click';

                    GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'siteClick', p);

                } else {
                    p.customerStatus = 'First Time';
                    p.gaEventLabel = 'Close Bet Ticket';
                    p.eventLabel = 'BetTicket-Close';
                    p.gaEventAction = 'Bet Ticket Page Click';

                    GTMFac.GTMEvent().when($rootScope.userSession).send($rootScope, 'siteClick', p);
                }
            }

            function gtmDefaultBetSlipData() {
                var trackAbbr = $scope.data.currentRace && $scope.data.currentRace.trackAbbr ? $scope.data.currentRace.trackAbbr : '';
                var amount = $scope.data.selectedBetAmount && $scope.data.selectedBetAmount.amount ? _roundAmount($scope.data.selectedBetAmount.amount) : '';
                var raceNumber = $scope.data.currentRace && $scope.data.currentRace.raceNumber ? $scope.data.currentRace.raceNumber : '';
                var betType = $scope.data.selectedBetType && $scope.data.selectedBetType.abbreviation ? $scope.data.selectedBetType.abbreviation : '';
                var sectionName = 'Bet Ticket | Bet Ticket Page';
                if ($scope.data.showView === show.viewCONFIRMATION) {
                    sectionName = 'Bet Ticket | Bet Ticket Confirmation Page';
                } else if ($scope.data.showView === show.viewRECEIPT) {
                    sectionName = 'Bet Ticket | Bet Ticket Receipt Page';
                }

                var runnerList = $rootScope.user && $rootScope.user.wagerString ? $rootScope.user.wagerString : '';

                return GTMFac.EventBuilder()
                    .withScreenName('Bet Ticket Page')
                    .withSectionName(sectionName)
                    .withBetName(betType + ' | ' + trackAbbr + ' | R' + raceNumber + ' | ' + amount + ' | ' + runnerList)
                    .withBetAmount(amount)
                    .withBetType(betType)
                    .withGaEventCategory('Site Click')
                    .withGaEventAction('Bet Ticket Page Click')
                    .withRaceNumber(raceNumber)
                    .withTrackName($scope.data.currentRace && $scope.data.currentRace.trackName ? $scope.data.currentRace.trackName : '')
                    .withRunnerSelectionList(runnerList)
                    .build();
            }

            function _initBetSlipPoller() {
                _getGraphData();
            }

            function _processTrackData(trackData) {
                trackDataCtrl = trackData;
                $scope.data.races = trackData;
                if (!trackData.length) {
                    $scope.data.currentRace = null;
                    $scope.isLoading = false;
                } else {
                    _updateCurrentRaceAndCurrentRaceIndex(trackData, $scope.data.races, $routeParams.raceNumber);

                    if ($scope.data.currentRace) {
                        _setBettingInfo();
                        _setBetSlipLoaded();
                    }
                }
            }

            function _adjustSizeFixRender() {
                //SE-513 - Do not remove this piece of code (seems useless but solves the reported bug)
                $window.resizeBy( sizeToggle,0);
                sizeToggle *= -1;
            }

            function _setBetSlipLoaded() {
                $scope.isLoading = false;
                _adjustSizeFixRender();
            }

            function _onDataRefresh(graphData) {

                // update all future races because this race can have a pick 2/3/4/5/6 bet option
                // and its legs need to be updated
                $scope.data.races.forEach(function (race) {
                    graphData.races.forEach(function (graphRace) {
                        var raceNumber = parseInt(graphRace.raceNumber, 10);

                        if (parseInt(race.raceNumber, 10) === raceNumber) {
                            RaceInfoFac.setLowestOdd(graphRace.bettingInterests);
                            var isFavoriteBIScratched = RaceInfoFac.isFavoriteBIScratched(graphRace.bettingInterests);

                            race.bettingInterests.forEach(function (raceRunner) {
                                graphRace.bettingInterests.forEach(function (graphRaceRunner) {
                                    if (raceRunner.bettingInterestNumber === graphRaceRunner.biNumber) {
                                        graphRaceRunner.runners.forEach(function (graphRaceRunnerHorse) {
                                            if (raceRunner.horseID === graphRaceRunnerHorse.runnerId) {
                                                raceRunner.scratched = graphRaceRunnerHorse.scratched;
                                            }
                                        });

                                        var bi = _treatBettingInterestRunnersOdds(graphRaceRunner, isFavoriteBIScratched);
                                        var biRunner = bi.runners[0];


                                        raceRunner.currentOdds.denominator = biRunner.currentOdds ?  biRunner.currentOdds.denominator: 0;
                                        raceRunner.currentOdds.numerator = biRunner.currentOdds? biRunner.currentOdds.numerator: 99;
                                        raceRunner.currentOddsString = biRunner.currentOddsString;
                                        raceRunner.favorite = biRunner.favorite;


                                        for (var i = 1; i < bi.runners.length; i++) {
                                            var runner = bi.runners[i];

                                            if (!runner.scratched) {
                                                // only update odds string if other runners are not scratched
                                                // else, the odds string will be determined by the first runner
                                                if(runner.currentOdds){
                                                    raceRunner.currentOddsString = runner.currentOddsString;
                                                    raceRunner.currentOdds.numerator = runner.currentOdds.numerator;
                                                    raceRunner.favorite = runner.favorite;
                                                }
                                            }
                                        }
                                    }
                                });
                            });

                            //Update the current race data
                            if (graphRace.trackAbbr == $scope.data.currentRace.trackAbbr && raceNumber === parseInt($scope.data.currentRace.raceNumber, 10)) {
                                $scope.data.currentRace = race;
                                $scope.data.currentRace.status = graphRace.status.code;
                                $scope.data.currentRace.perfAbbr = graphRace.track.perfAbbr;
                                $scope.data.currentRace.trackName = graphRace.track.name;

                                $scope.data.raceOpenForBetting = RaceStatusUtils.isRaceOpenForBetting($scope.data.currentRace);
                                $scope.data.raceOpenForLiveVideo = RaceStatusUtils.isRaceOpenForLiveVideo($scope.data.currentRace);

                                if (!$scope.data.raceOpenForBetting) {
                                    $scope.data.currentRace.closedForBetting = true;
                                } else {
                                    $scope.data.currentRace.closedForBetting = false;
                                }
                            }
                        }
                    });
                });

                _removeScratchedHorsesFromSelection();
                _setBettingInfo();
            }

            function _onDataRefreshError(response) {
                $log.error('Error getting data for this race via graph: ', response);
            }

            function _subscribeGraphData() {
                var queryParams = {
                    trackAbbr: $routeParams.trackAbbr,
                    wagerProfile: WagerProfileFac.getWagerProfile()
                };

                if (subscribeEvent) {
                    $timeout.cancel(subscribeEvent);
                }

                subscribeEvent = $timeout(function () {
                    graphSubscription = GraphRaceRunners.subscribe(
                        queryParams,
                        {success: _onDataRefresh, fail: _onDataRefreshError},
                        graphPollerInterval,
                        true
                    );
                }, graphPollerInterval);
            }

            function _treatBettingInterestRunnersOdds(bettingInterest, isFavoriteBIScratched) {
                bettingInterest.runners.forEach(function (runner) {
                    runner.currentOdds = {};
                    runner.currentOdds.denominator = bettingInterest.currentOdds? bettingInterest.currentOdds.denominator: 0;
                    runner.currentOdds.numerator = bettingInterest.currentOdds? bettingInterest.currentOdds.numerator: 99;
                    if(bettingInterest.currentOdds){
                        runner.currentOddsString = bettingInterest.currentOdds.numerator != null ?
                            bettingInterest.currentOdds.numerator + (bettingInterest.currentOdds.denominator ? '/' + bettingInterest.currentOdds.denominator : '') : 'N/A';
                        runner.favorite = isFavoriteBIScratched ? RaceInfoFac.isFavoriteOdd(bettingInterest) : bettingInterest.favorite;
                    }else{
                        runner.currentOddsString = "99";
                        runner.favorite = false;
                    }


                    if (_areAllRunnersScratched(runner)) {
                        runner.currentOddsString = 'Src';
                        runner.currentOdds.numerator = 'Src';
                    }
                });

                return bettingInterest;
            }

            function _getGraphData() {
                var options = {
                    trackAbbr: $routeParams.trackAbbr,
                    wagerProfile: WagerProfileFac.getWagerProfile()
                };

                if (graphSubscription && GraphRaceRunners.isSubscribed()) {
                    GraphRaceRunners.unsubscribe(graphSubscription);
                }

                GraphRaceRunners.get(options).then(function (response) {
                    var graphData = angular.copy(response);

                    graphData.races.forEach(function (graphRace) {
                        graphRace.id = graphRace.trackAbbr + '_' + graphRace.track.perfAbbr + '_' + graphRace.raceNumber;
                        graphRace.status = graphRace.status.code;
                        graphRace.trackName = graphRace.track.name;
                        graphRace.postTime = new Date(graphRace.postTime);

                        var runnersArray = [];
                        var isFavoriteBIScratched = RaceInfoFac.isFavoriteBIScratched(graphRace.bettingInterests);

                        RaceInfoFac.setLowestOdd(graphRace.bettingInterests);
                        graphRace.bettingInterests.forEach(function (bettingInterest) {
                            var mainRunner = bettingInterest.runners[0];
                            mainRunner.saddleColor = bettingInterest.saddleColor;
                            mainRunner.numberColor = bettingInterest.numberColor;
                            mainRunner.horseID = mainRunner.runnerId;
                            mainRunner.bettingInterestNumber = bettingInterest.biNumber;

                            if (bettingInterest.runners.length > 1) {
                                // means this betting interest has coupled runners (ie. 1 / 1A)
                                mainRunner.coupledRunners = [];

                                for (var i = 1; i < bettingInterest.runners.length; i++) {
                                    var coupledRunner = bettingInterest.runners[i];
                                    mainRunner.coupledRunners.push(coupledRunner);
                                }
                            }

                            bettingInterest.runners[0] = mainRunner;
                            var bi = _treatBettingInterestRunnersOdds(bettingInterest, isFavoriteBIScratched);

                            mainRunner = bi.runners[0];
                            runnersArray.push(mainRunner);
                        });

                        graphRace.bettingInterests = runnersArray;
                        var wagerTypesArray = [];
                        graphRace.wagerTypes.forEach(function (wagerType) {
                            var wagerTypeObj = {};

                            var betAmounts = [];
                            wagerType.wagerAmounts.forEach(function (wagerAmount) {
                                var betAmount = {
                                    amountString: $filter('currency')(wagerAmount, "$"),
                                    amount: wagerAmount
                                };
                                betAmounts.push(betAmount);
                            });
                            betAmounts.push({
                                amountString: 'other',
                                amount: null
                            });
                            wagerTypeObj.id = wagerType.type.id;
                            wagerTypeObj.betAmounts = betAmounts;
                            wagerTypeObj.maxBetAmount = wagerType.maxWagerAmount;
                            wagerTypeObj.minBetAmount = wagerType.minWagerAmount;
                            wagerTypeObj.name = wagerType.type.name;
                            wagerTypeObj.abbreviation = wagerType.type.code;
                            wagerTypeObj.columnCount = wagerType.columnCount;
                            wagerTypeObj.columnType = wagerType.columnType;
                            wagerTypeObj.isBox = wagerType.isBox;
                            wagerTypeObj.isKey = wagerType.isKey;
                            wagerTypeObj.legCount = wagerType.legCount;
                            wagerTypeObj.maxBIsPerLeg = wagerType.maxBIsPerLeg;
                            wagerTypeObj.minBIsPerLeg = wagerType.minBIsPerLeg;
                            wagerTypeObj.poolsPerBI = wagerType.poolsPerBI;
                            wagerTypeObj.positionCount = wagerType.positionCount;
                            wagerTypeObj.isWheel = wagerType.isWheel;

                            wagerTypesArray.push(wagerTypeObj);
                        });
                        graphRace.wagerTypes = wagerTypesArray;
                    });

                    $scope.data.races = graphData.races;
                    fetchRetry = initialFetchRetry;

                    _processTrackData(graphData.races);
                    _subscribeGraphData();
                }).catch(function (err) {
                    // Retry request on error
                    if (fetchRetry > 0) {
                        $timeout(function () {
                            _getGraphData();
                            fetchRetry--;
                        }, (6000 / fetchRetry));
                    } else {
                        $scope.isLoading = false;
                        $scope.data.currentRace = null;
                        $log.error(err.message);
                    }
                });
            }


            $scope.$watch('data.selectedBetType', function (currWager) {
                if (currWager && angular.isDefined(currWager)) {
                    $scope.data.betEnabled = false;
                    $scope.data.activeTab = 0;
                    $scope.data.layoutType = currWager.columnCount > 1 ? 'multiple' : 'single';
                    $scope.data.cols = _.range(1, currWager.columnCount + 1);
                    $scope.data.legColumnHeight = [];

                    /*<!-- Grand Slam message -->*/
                    if ($scope.data.selectedBetType.abbreviation == 'GS' && !$scope.hasSeenGrandSlamInfo && $rootScope.activeFeatures.showGrandSlamInfo) {
                        betSlipWindowAlertsFac.addAlert({
                            id: 'grandslam',
                            type: 'warning',
                            closeable: true,
                            message: $filter('CMSValue')('grandSlamInfoMessage'),
                            closeForever: true
                        });
                    }

                    if (nFectaWagerTypes.indexOf($scope.data.selectedBetType.abbreviation) > -1 && !$scope.hasSeenNfectaInfo) {
                        betSlipWindowAlertsFac.addAlert({
                            id: 'nfecta',
                            type: 'warning',
                            closeable: true,
                            message: $filter('CMSValue')('nfectaInfoMessage'),
                            closeForever: true
                        });
                    }

                    if (currWager.legCount > 1) {
                        $scope.data.legRaces = $scope.data.races.slice($scope.data.currentRaceIndex, $scope.data.currentRaceIndex + currWager.columnCount);
                        $scope.data.legRacesRunners = [];
                        $scope.data.isLeg = true;
                        var legHeight = 0,
                            colRunners = [],
                            legRace;

                        for (var i = 0; i < currWager.columnCount; i++) {
                            colRunners = [];
                            legRace = i < $scope.data.legRaces.length ? $scope.data.legRaces[i] : null;
                            colRunners = legRace ? legRace.bettingInterests : [];
                            $scope.data.legRacesRunners.push(colRunners);

                            legHeight = colRunners.length > legHeight ? colRunners.length : legHeight;
                        }

                        $scope.data.legColumnHeight = _.range(1, legHeight + 1);
                    } else {
                        $scope.data.legRaces = [];
                        $scope.data.legRacesRunners = [];
                        $scope.data.isLeg = false;
                    }

                    _removeScratchedHorsesFromSelection();
                    _validateBet();
                }
            });

            function _closeAlertForever(index) {
                if ($scope.data.selectedBetType.abbreviation == 'GS') {
                    LocalStorageFac.setItem("hasSeenGrandSlamInfo", true);
                    $scope.hasSeenGrandSlamInfo = true;
                    betSlipWindowAlertsFac.closeAlert(index);
                }

                if (nFectaWagerTypes.indexOf($scope.data.selectedBetType.abbreviation) > -1) {
                    LocalStorageFac.setItem('hasSeenNfectaInfo', true);
                    $scope.hasSeenNfectaInfo = true;
                    betSlipWindowAlertsFac.closeAlert(index);
                }
            }

            function _readBetslipParameters() {
                if (parameters && parameters.betselections && onFirstTimeOpen) {
                    $scope.data.currentBetSelections = _parseBetSelectionsString(parameters.betselections);
                }

                if (parameters && parameters.betamount && !isNaN(parameters.betamount) && onFirstTimeOpen) {
                    prefBetAmount = _roundAmount(parameters.betamount);
                } else if (userPrefs && userPrefs.bet_prefs && parameters && parameters.bettype) {
                    prefBetAmount = _roundAmount(userPrefs.bet_prefs.default_bet_amount[parameters.bettype]);
                } else if (userPrefs && userPrefs.bet_prefs && !parameters.bettype) {
                    prefBetAmount = _roundAmount(userPrefs.bet_prefs.default_bet_amount[userPrefs.bet_prefs.defaultBetType]);
                } else {
                    prefBetAmount = _roundAmount($scope.data.wagerTypes[0].betAmounts[0].amount);
                }

                $scope.data.otherAmount = prefBetAmount;

                if (parameters && parameters.bettype && !isNaN(parameters.bettype) && onFirstTimeOpen) {
                    prefBetType = _getPrefBetType(parameters.bettype);
                } else if (userPrefs && userPrefs.bet_prefs) {
                    prefBetType = _getPrefBetType(userPrefs.bet_prefs.defaultBetType);
                } else {
                    prefBetType = _getPrefBetType(userPrefs.bet_type);
                }

                if (onFirstTimeOpen) {
                    onFirstTimeOpen = false;
                }

                if (!angular.isUndefined(userPrefs.show_bet_confirm)) {
                    $scope.data.isBetConfirmed = !!userPrefs.show_bet_confirm;
                }

                readParameters = true;
            }

            function _resetRepeat() {
                $scope.data.repeatBet = false;
                $scope.data.repeatTimes = 1;
                $scope.data.maxRepeatTimes = 9999;
                $scope.data.repeatValid = true;
            }

            function _updateMtp(postTime) {
                $scope.data.mtp.status = 'time-format';
                $scope.data.mtp.time = $filter('raceMtp')(postTime);
                var mtp = (typeof $scope.data.mtp.time === 'string') ? $scope.data.mtp.time.split(' ') : [];
                if (mtp[1] === 'MTP') {
                    var time = parseInt(mtp[0]);
                    if (time <= 5) {
                        $scope.data.mtp.status = 'near';
                    } else if (time <= 15) {
                        $scope.data.mtp.status = 'med';
                    } else {
                        $scope.data.mtp.status = 'far';
                    }
                }
            }

            function _areAllRunnersScratched(bi) {
                if (!bi) {
                    return false;
                }

                if (bi.coupledRunners) {
                    var coupledRunnersScratched = _.filter(bi.coupledRunners, function (cr) {
                        return cr.scratched === true;
                    });

                    // to be true, the main BI runner has to be scratched, as well as all the bi coupled runners
                    return coupledRunnersScratched.length === bi.coupledRunners.length && bi.scratched;
                } else {
                    return !!bi.scratched;
                }
            }

            function _isNewWagerType(abbr) {
                return !!(abbr === 'GS' || nFectaWagerTypes.indexOf(abbr) > -1);
            }

            /**
             * Transform each selection leg String into an array of integers of selections.
             *
             * @param {String} betSelectionsString The bet selections string.
             * Expected to have the following regexp format: ([\d]\,*\;*)
             * @returns {*} the received parameter if not a valid String or an array of array(s) of integer(s).
             * @private
             */
            function _parseBetSelectionsString(betSelectionsString) {
                if (!betSelectionsString || typeof betSelectionsString !== 'string') {
                    return betSelectionsString;
                }

                return betSelectionsString.split(';')
                    .map(function (currentSelectionLeg) {
                        return _.reduce(currentSelectionLeg.split(','), function (result, currentSplitSelection) {
                            // parse String to integer
                            currentSplitSelection = parseInt(currentSplitSelection, 10);
                            if (!isNaN(currentSplitSelection) && !_.includes(result, currentSplitSelection)) {
                                result.push(parseInt(currentSplitSelection, 10));
                            }
                            return result;
                        }, [])
                            // Using Boolean as a function to convert a non-boolean value to a boolean value.
                            // This removes any selection that could not be parsed.
                            .filter(Boolean);
                    });
            }

            function _blockBettingBecauseOfState() {
                if (
                    $rootScope.activeFeatures.bettingBlockedByUserState &&
                    !$scope.data.blockAnyBetting &&
                    $rootScope.user &&
                    $rootScope.user.homeAddress != undefined &&
                    typeof $rootScope.user.homeAddress.State === "string"
                ) {
                    $scope.data.blockAnyBetting =
                        _.findIndex(
                            _.get(
                                $scope.data,
                                "forbiddenBettingStates.blockedStates",
                                ["AZ"]
                            ),
                            function (state) {
                                return (
                                    state.toLowerCase() ===
                                    $rootScope.user.homeAddress.State.toLowerCase()
                                );
                            }
                        ) !== -1;
                }

                if (
                    $rootScope.activeFeatures.bettingBlockedByUserState &&
                    !$scope.isLoading &&
                    $scope.data.blockAnyBetting
                ) {
                    betSlipWindowAlertsFac.addAlert({
                        id: "bettingForbidden",
                        type: "error",
                        closeable: false,
                        message: _.get(
                            $scope.data,
                            "forbiddenBettingStates.errorMessage",
                            "For legal reasons, we cannot accept wagers from your state on a computer. Try again on a mobile device using the app or mobile website"
                        ),
                    });
                }
            }

            (function init() {
                $scope.$watch("isLoading", _blockBettingBecauseOfState);
                $rootScope.$watch("user", _blockBettingBecauseOfState);

                $scope.$on('$destroy', function () {
                    var stateToSave = previousState || {
                        data: $scope.data
                    };

                    StatePersistenceFac.saveState('bt', stateToSave);

                    if (graphSubscription && GraphRaceRunners.isSubscribed()) {
                        GraphRaceRunners.unsubscribe(graphSubscription);
                    }
                });

                $scope.$on('login', _reloadUserPreferencesAfterLoggingIn);
                $scope.$on('session', _reloadUserPreferencesAfterLoggingIn);

                $scope.$on('sessionInvalid', function () {
                    $scope.sessionInvalid = true;
                });

                $scope.$on('BetSlip::RaceChanged', function (event, trackChanged) {
                    $scope.isLoading = true;
                    initialSetup = true;
                    if (trackChanged) {
                        betSlipWindowAlertsFac.clearAlertsExcept("bettingForbidden");
                        _initBetSlipPoller(initialSetup);
                    } else {
                        _updateCurrentRaceAndCurrentRaceIndex(trackDataCtrl, $scope.data.races, $routeParams.raceNumber);
                        $scope.isLoading = false;
                        betSlipWindowAlertsFac.clearAlertsExcept("bettingForbidden");
                        _adjustSizeFixRender();
                        _setBettingInfo(true);
                    }
                });

                $scope.$on('accountBalance_update', function () {
                    $scope.data.betEnabled = true; //Enable bet button when user deposits funds. Even if the funds after deposit are not enough, click on the button will proceed to bet validation.
                    betSlipWindowAlertsFac.closeAlertByIdentifier('insuficientFunds'); //Remove only the alert of insufficient funds
                });

                _getGraphData();

                $interval(function () {
                    _updateMtp($scope.data.currentRace.postTime);
                }, 15000);

                loadFirstTime = true;
                $rootScope.hideDepositOptions = true;
                $scope.hasSeenGrandSlamInfo = LocalStorageFac.getItem("hasSeenGrandSlamInfo");
                $scope.hasSeenNfectaInfo = LocalStorageFac.getItem("hasSeenNfectaInfo");
                _resetRepeat();
                window.addEventListener('unload', function () {
                    betSlipCloseEvent();
                });
            }());
        }

        BetSlipWindowCtrl.$inject = [
            '$scope',
            '$rootScope',
            'BetsSvc',
            'StatePersistenceFac',
            '$window',
            '$uibModal',
            'PreferencesCookieFac',
            '$filter',
            '$routeParams',
            'GTMFac',
            'UserProfileSvc',
            'RaceInfoFac',
            '$interval',
            'AmountOptionsFac',
            'trackSvc',
            'betSlipWindowAlertsFac',
            'GraphRaceRunners',
            'WagerProfileFac',
            '$log',
            '$timeout',
            'LocalStorageFac',
            'PreferencesFac'
        ];
        return BetSlipWindowCtrl;
    }
);

modules/BetSlipWindow/directives/betslip-window-directive.js
'use strict';

define(
    'BetSlipWindowDir',[],function () {
        function BetSlipWindowDir($window, $timeout) {
            return {
                restrict: 'E',
                templateUrl: 'js/modules/BetSlipWindow/templates/betslip-window.html',
                controller: 'BetSlipWindowCtrl',
                scope: true,
                link: function ($scope) {
                    $scope.$watch('data.selectedBetType', function () {
                        $timeout(function() {
                            var newSize = parseInt(($scope.data.cols.length * 50) + 350);
                            newSize = newSize < 535 ? 535 : newSize;
                            $window.resizeBy( newSize - $window.outerWidth,0);
                        }, 100);
                    });

                    angular.element(document.querySelectorAll("layout")[0]).css({
                        'width': '100%',
                        'min-width': 0,
                        'height': '100%',
                        'margin': '0 auto',
                        'position': 'absolute'
                    });
                }
            };
        }

        BetSlipWindowDir.$inject = [
            '$window',
            '$timeout'
        ];
        return BetSlipWindowDir;
    }
);

modules/BetSlipWindow/controllers/trackSelectorWindowCtrl.js
'use strict';

define('TrackSelectorWindowCtrl',[],
    function () {
            function TrackSelectorWindowCtrl($scope, $rootScope, $routeParams, LocationUnreloadFac, GTMFac) {
                $scope.data = {
                    loading: true,
                    tracks: [],
                    error: null,
                    trackAbbr: $routeParams.trackAbbr,
                    raceNumber: $routeParams.raceNumber,
                    racesLoading: true
                };

                function _processRaceList(tracks) {
                    $scope.data.tracks = tracks;

                    var trackSelected = _.find($scope.data.tracks, function (track) {
                        return track.trackAbbr === $scope.data.trackAbbr;
                    });

                    $scope.data.trackSelected = {
                        name: trackSelected.name,
                        trackAbbr: trackSelected.trackAbbr,
                        perfAbbr: trackSelected.perfAbbr
                    };

                    $scope.data.races = trackSelected.races;
                    $scope.data.currentRace = _.find($scope.data.races, function (o) {
                        return o.raceNumber === parseInt($scope.data.raceNumber, 10);
                    });

                    if ($scope.data.trackSelected) {
                        $scope.data.oldTrackSelected = $scope.data.trackSelected;
                        $scope.data.racesLoading = false;
                        $scope.data.loading = false;
                    }
                }

                function _onTrackChangedForNewTrackSelector(track){
                    $scope.data.loading = true;
                    $scope.data.trackSelected = track;
                    $scope.data.trackSelected.name = track.trackName;
                    LocationUnreloadFac.pathChange.apply(this, _buildLocationPathParams(track.trackAbbr, track.perfAbbr, track.raceNumber));
                }

                function _raceChanged() {
                    var raceNumber = $scope.data.currentRace.raceNumber;
                    var trackAbbr = $scope.data.trackSelected.trackAbbr;
                    var perfAbbr = $scope.data.trackSelected.perfAbbr;
                    LocationUnreloadFac.pathChange.apply(this, _buildLocationPathParams(trackAbbr, perfAbbr, raceNumber));

                    if($rootScope.isBetslipApp) {
                        var p = {};
                        p.eventLabel = 'BetTicket-RaceDropDown';
                        p.gaEventCategory = 'Site Click';
                        p.gaEventAction = 'Bet Ticket Page Click';
                        p.gaEventLabel = 'Races Changes';
                        p.screenName = 'Bet Ticket Page';
                        p.sectionName = 'Bet Ticket | Bet Ticket Page';
                        p.raceNumber = "R" + $scope.data.currentRace.raceNumber;
                        p.trackName = $scope.data.currentRace.trackName;
                        GTMFac.GTMEvent().send($rootScope, 'siteClick', p);
                    }
                }

                function _buildNextTrackPath(trackAbbr, perfAbbr, raceNumber){
                    return "/betslip/_trackAbbr_/_perfAbbr_/_raceNumber_"
                        .replace("_trackAbbr_", trackAbbr)
                        .replace("_perfAbbr_", perfAbbr)
                        .replace("_raceNumber_", raceNumber);
                }

                var unbind = [];

                unbind.push($rootScope.$on('trackListReady', function (event, data) {
                    _processRaceList(data);
                }));

                unbind.push($rootScope.$on('race:Changed', function () {
                    $scope.data.loading = true;
                    if ($routeParams.trackAbbr !== $scope.data.trackAbbr) {
                        $scope.data.trackAbbr = $routeParams.trackAbbr;
                        $scope.data.raceNumber = $routeParams.raceNumber;
                        _processRaceList($scope.data.tracks);
                        $scope.data.loading = false;
                        $scope.$emit("BetSlip::RaceChanged", true);
                    } else {
                        $scope.data.raceNumber = $routeParams.raceNumber;
                        $scope.data.loading = false;
                        $scope.$emit("BetSlip::RaceChanged", false);
                    }
                }));

                unbind.push($rootScope.$on('raceListReady', function (event, races, trackAb){
                    $scope.data.tracks.forEach(function (track) {
                        if(track.trackAbbr == trackAb) {
                            track.races = races;
                        }
                    });
                }));

                function _buildLocationPathParams(trackAbbr, perfAbbr, raceNumber) {
                    var args = [];
                    args.push(_buildNextTrackPath(trackAbbr, perfAbbr, raceNumber));
                    args.push(false);
                    args.push({trackAbbr: trackAbbr, perfAbbr: perfAbbr, raceNumber: raceNumber});
                    args.push('race:Changed');
                    return args;
                }

                $scope.events = {
                    raceChanged: _raceChanged,
                    onTrackChangedForNewTrackSelector: _onTrackChangedForNewTrackSelector
                };
            }

            TrackSelectorWindowCtrl.$inject = [
                '$scope',
                '$rootScope',
                '$routeParams',
                'LocationUnreloadFac',
                'GTMFac'
            ];

            return TrackSelectorWindowCtrl;
        }
);

modules/BetSlipWindow/directives/track-selector-window-directive.js
'use strict';

define(
	'TrackSelectorWindowDir',[],function () {
		function TrackSelectorWindowDir() {
			return {
				restrict: 'E',
				templateUrl: 'js/modules/BetSlipWindow/templates/track-selector-window.html',
				controller: 'TrackSelectorWindowCtrl',
				scope: true
			};
		}
		return TrackSelectorWindowDir;
	}
);

modules/BetSlipWindow/directives/betslip-account-info-directive.js
'use strict';

define(
	'BetSlipAccountInfoDir',[],function () {
		function BetSlipAccountInfoDir() {
			return {
				restrict: 'E',
				templateUrl: 'js/modules/BetSlipWindow/templates/betslip-account-info.html',
				controller: 'BetSlipAccountInfoCtrl',
				scope: true
			};
		}
		return BetSlipAccountInfoDir;
	}
);

modules/BetSlipWindow/controllers/betSlipAccountInfoCtrl.js
'use strict';

define(
        'BetSlipAccountInfoCtrl',[],
        function () {

            function BetSlipAccountInfoCtrl($scope, $rootScope, $uibModal, $filter, PreferencesCookieFac, $interval, GTMFac, ContentFac, PreferencesFac) {
                var userPrefs = PreferencesCookieFac.getPreferences();

                var updateBalance = _.throttle(_updateBalanceThrottle, 4000, { trailing: false });

                if (!$rootScope.accountBalance) {
                    $rootScope.$broadcast('accountBalance_update');
                }

                $scope.$on('accountBalance_changed', function () {
                    $scope.data.accountBalance = $filter('currency')($rootScope.accountBalanceNumber, '$');
                    $scope.data.updatingBalance = false;
                });

                $scope.data = {
                    showBalance: userPrefs.balance_is_shown,
                    updatingBalance: false
                };

                try {
                    var balance_is_show = localStorage.getItem('balance_is_shown');
                    userPrefs.balance_is_shown = balance_is_show !== null ? balance_is_show : userPrefs.balance_is_shown;
                    $scope.data.showBalance = parseInt(userPrefs.balance_is_shown);
                } catch(e) { }

                $interval( function() {
                    try {
                        var balance_is_show = localStorage.getItem('balance_is_shown');
                        userPrefs.balance_is_shown = balance_is_show !== null ? balance_is_show : userPrefs.balance_is_shown;
                    } catch(e) { }
                }, 1000);

                function _updateBalanceThrottle() {
                    $scope.data.updatingBalance = true;
                    $rootScope.$emit('accountBalance_update');

                    var eventData = GTMFac.gaEventBuilder()
                        .withGaEventAction(GTMFac.Tvg4ScreenName() + ' Page Click')
                        .withGaEventCategory('Site Click')
                        .withGaEventLabel('Balance Refresh Button')
                        .withEventLabel('BetTicket-BalanceRefresh')
                        .build();

                    var genericEvent = GTMFac.genericEvent(eventData);

                    GTMFac.GTMEvent().send($rootScope, 'siteClick', genericEvent);
                }

                function _openQuickDeposit() {

                    var eventData = GTMFac.gaEventBuilder()
                        .withGaEventAction(GTMFac.Tvg4ScreenName() + ' Page Click')
                        .withGaEventCategory('Site Click')
                        .withGaEventLabel('Deposit Button')
                        .withEventLabel('BetTicket-Deposit')
                        .build();

                    var genericEvent = GTMFac.genericEvent(eventData);

                    GTMFac.GTMEvent().send($rootScope, 'siteClick', genericEvent);

                    ContentFac.fetchAllDataFromCMS(['Global', 'Deposits', 'Funds'])
                        .then(function () {
                            $scope.quickDepositModal = $uibModal.open({
                                windowClass: 'quick-deposit new-quick-deposit betslip-quick-deposit',
                                backdropClass: 'tvgmodal-backdrop',
                                windowTemplateUrl: 'js/modules/Utilities/templates/modal-window.html',
                                templateUrl: 'js/modules/UserProfile/templates/quick-deposit.html',
                                controller: 'QuickDepositCtrl'
                            });
                        });
                }

                $scope.events = {
                    openQuickDeposit: _openQuickDeposit,
                    updateBalance: updateBalance
                };

            }

            BetSlipAccountInfoCtrl.$inject = [
                '$scope',
                '$rootScope',
                '$uibModal',
                '$filter',
                'PreferencesCookieFac',
                '$interval',
                'GTMFac',
                'ContentFac',
                'PreferencesFac'
            ];

            return BetSlipAccountInfoCtrl;
        }
);

modules/BetSlipWindow/directives/betslip-alert-banner-directive.js
'use strict';

define('BetSlipAlertBannerDir',[],function() {

    /**
     * Available types:
     *  - warning (yellow background)
     *  - error (red background)
     *  - success (green background)
     *  - info (blue background)
     *  - neutral (default, yellowish background)
     *
     * @example
     *   <betslip-alert-banner
     *     type='warning'
     *     closeable='true'
     *     close='closeBanner()'>Lorem ipsum dolor sit amet, consectetur adipisicing elit
     *   </betslip-alert-banner>
     */
    return function BetSlipAlertBanner() {
        return {
            restrict: 'E',
            scope: {
                close: '&',
                type: '@',
                closeable: '@',
                message: '@'
            },
            templateUrl: 'js/modules/BetSlipWindow/templates/betslip-alert-banner.html',
            link: function(scope, element, attrs) {
                attrs.$observe('closeable', function() {
                    scope.closeable = scope.$eval(attrs.closeable);
                });
            }
        };
    };
});

modules/BetSlipWindow/providers/betSlipWindowAlertsFac.js
'use strict';

define('BetSlipWindowAlertsFac',[
        'lodash'
    ],
    function (_) {

        function betSlipWindowAlertsFac() {
            var alerts = [];

            /**
             * Add alert banner.
             * If an id is given, it will ensure that only one error with the
             * same id is displayed
             *
             * @param {Object} options
             * @param {String} [options.id] identifier
             * @param {String} options.type
             * @param {Boolean} options.closeable
             * @param {String} options.message
             *
             * @returns {Number} index of the alert in the array
             */
            function _addAlert(options) {
                if (options.id) {
                    _closeAlertByIdentifier(options.id);
                }

                return alerts.push(options) - 1;
            }

            /**
             * Removes the alert from the array at the given index.
             * @param  {Number} index index of the alert in the array
             */
            function _closeAlert(index) {
                if (index >= 0) {
                    alerts.splice(index, 1);
                }
            }

            /**
             * Removes the alert that matches the given identifier.
             * @param  {String} id identifier
             */
            function _closeAlertByIdentifier(id) {
                var index = _.findIndex(alerts, function(alert) {
                    return alert.id === id;
                });

                _closeAlert(index);
            }

            function _clearAlerts() {
                // This instead of alerts = [] because we don't want to lose the reference.
                // The alerts variable is being returned and referenced outside this factory.
                alerts.splice(0, alerts.length);
            }

            function _clearAlertsExcept(idToKeep) {
                _.remove(alerts, function (alert) {
                    return alert.id !== idToKeep;
                });
            }

            return {
                alerts                      : alerts,
                addAlert                    : _addAlert,
                closeAlert                  : _closeAlert,
                closeAlertByIdentifier      : _closeAlertByIdentifier,
                clearAlerts                 : _clearAlerts,
                clearAlertsExcept           : _clearAlertsExcept
            };
        }

        return betSlipWindowAlertsFac;
    }
);

modules/Track/providers/trackSvc.js
'use strict';

define('TrackSvc',[],function () {

    function TrackSvc() {

        function _isTrackFromHongKong(track) {
            return (track.CountryName === 'CHN' && track.State === 'HK');
        }

        function _isHongKongRace(trackAbbr) {
            return (trackAbbr === 'HK1'
                || trackAbbr === 'HK2'
                || trackAbbr === 'HKH'
                || trackAbbr === 'HKS');
        }

        return {
            isTrackFromHongKong: _isTrackFromHongKong,
            isHongKongRace: _isHongKongRace
        };
    }

    return TrackSvc;
});
modules/Track/trackMod.js
'use strict';

define('Track',[
        'TrackSvc'
    ], function (TrackSvc) {

        angular.module('TVG.Track', [])
            .factory('trackSvc', TrackSvc);
    }
);

modules/BetSlipWindow/betSlipWindowMod.js
'use strict';

define(
    'BetSlipWindow',[
        'BetSlipWindowCtrl',
        'BetSlipWindowDir',
        'TrackSelectorWindowCtrl',
        'TrackSelectorWindowDir',
        'BetSlipAccountInfoDir',
        'BetSlipAccountInfoCtrl',
        'BetSlipAlertBannerDir',
        'BetSlipWindowAlertsFac',
        'Track',
        'GTMMod'
    ],

    function (BetSlipWindowCtrl,
              BetSlipWindowDir,
              TrackSelectorWindowCtrl,
              TrackSelectorWindowDir,
              BetSlipAccountInfoDir,
              BetSlipAccountInfoCtrl,
              BetSlipAlertBannerDir,
              BetSlipWindowAlertsFac) {

        angular.module('TVG.BetSlipWindow', [
            'TVG.Track',
            'TVG.Common.GTM'
        ])
            .controller('BetSlipWindowCtrl', BetSlipWindowCtrl)
            .controller('TrackSelectorWindowCtrl', TrackSelectorWindowCtrl)
            .controller('BetSlipAccountInfoCtrl', BetSlipAccountInfoCtrl)
            .factory('betSlipWindowAlertsFac', BetSlipWindowAlertsFac)
            .directive('betslipAccountInfo', BetSlipAccountInfoDir)
            .directive('trackSelectorWindow', TrackSelectorWindowDir)
            .directive('betslipWindow', BetSlipWindowDir)
            .directive('betslipAlertBanner', BetSlipAlertBannerDir);
    }
);

modules/Features/providers/factories/featuresFac.js
'use strict';

define('FeaturesFac',[
    'lodash',
    'muton'
    ],
    function (_) {
        function FeaturesFac($location, FEATURES, LocalStorageFac, md5) {
            var _overridesEnabled = true;
            var StorageDelegate = {

                /**
                 * Get features configurations from local storage
                 * (configurations are the md5 hashes for each key)
                 *
                 * @return {Object}  Object with feature configurations hashes
                 */
                getFeaturesConfig: function() {
                    var stringified = '';
                    var featuresConfig = null;

                    try {
                        stringified = LocalStorageFac.getEncodedItem('featuresConfig');
                        featuresConfig = JSON.parse(stringified || 'null');
                    } catch(e) {
                        // ignore
                    }

                    return featuresConfig;
                },

                /**
                 * Save features configurations in local storage
                 * (configurations are the md5 hashes for each key)
                 *
                 * @param {Object} featuresConfig  Object with feature configurations hashes
                 */
                setFeaturesConfig: function(featuresConfig) {
                    var stringified = JSON.stringify(featuresConfig || null);

                    LocalStorageFac.setEncodedItem('featuresConfig', stringified);
                },

                /**
                 * Get saved features from local storage
                 * @return {Object} Features from storage
                 */
                getFeatures: function () {
                    var value = LocalStorageFac.getItem('features');
                    var features = angular.isObject(value) ? value : _toObject(value);

                    return features;
                },

                /**
                 * Convert into string and save features in local storage
                 * @param {Object} features  Hash of features to save
                 */
                setFeatures: function(features) {
                    var stringified = _toString(features);

                    LocalStorageFac.setItem('features', stringified);
                }
            };

            /**
             * Get features list from query parameter "featureOverrides",
             * and parse it into a features overrides object
             *
             * @return {Object} Features overrides
             */
            function _getUrlOverrides() {
                var featureOverrides = $location.search().featureOverrides || '';
                return _toObject(featureOverrides);
            }

            /**
             * Convert a stringified list of features into an object (separated by commas)
             *
             * @example
             * _toObject('a:true,b:false') => { a:true, b:false }
             *
             * @param  {String} stringified  Stringified features, separated by comma
             * @return {Object}              Features hash
             */
            function _toObject(stringified) {
                var pairs = (stringified || '').split(',');

                return pairs.reduce(function (acc, pair) {
                    var feature = pair.split(':');
                    var key = feature[0];
                    var value = (feature[1] === 'true');

                    if (key) {
                        acc[key] = value;
                    }

                    return acc;
                }, {});
            }

            /**
             * Convert an hash of features into a stringified list (separated by commas)
             *
             * @example
             * _toObject({ a:true, b:false }) => 'a:true,b:false'
             *
             * @param  {Object} features  Hash of features
             * @return {String}           Stringified features, separated by comma
             */
            function _toString(features) {
                return Object.keys(features || {}).map(function (key) {
                    return key + ':' + features[key];
                }).join(',');
            }

            /**
             * Encode a single feature configuration into a standarized md5 hash
             *
             * Each feature configuration may look something like these:
             * {"toggle": false }
             * {"toggle": true, "buckets": ["active", "active"] }
             * {"throttle": "20%"}
             * transfersToggle (feature) { return _.omit(feature, propertyIsDefined); } // @TODO why?
             *
             * @example
             * encodeFeatureConfig({ toggle: true, buckets: ['active', 'inactive'] })
             *   => dc3e537a6ac62a7838c4a207eba4a832
             *
             * @param  {Object/Function}  feature             Feature to encode
             * @param  {Boolean}          [feature.toggle]    Whether is toggled on
             * @param  {Array}            [feature.buckets]   Feature buckets
             * @param  {String}           [feature.throttle]  Percentage of users that should use the feature
             * @return {String}                               Encoded feature configuration
             */
            function _encodeFeatureConfig(feature) {
                var encoded = '';

                if (feature) {
                    encoded = (typeof feature === 'function') ?
                        feature.toString() : JSON.stringify(feature);
                    encoded = md5.createHash(encoded);
                }

                return encoded;
            }

            /**
             * Encode hash of feature configurations
             *
             * @example
             * encodeFeatureConfig({
             *     showLeftBar   : { toggle: true, buckets: ['active', 'inactive'] },
             *     showNewHeader : {"toggle": false },
             *     showNewFooter : {"throttle": "20%"}
             * })
             *   => {
             *     showLeftBar   : 40dec5a9bfaa7f5003f97c381cd35e0f,
             *     showNewHeader : 0b82ea90e3bb92e69689a6eb4960524b,
             *     showNewFooter : 76c580f656bef2084df0e762e315f726
             *   }
             *
             * @param  {Object} features   Features configurations hash
             * @return {Object}            Encoded features configurations hash
             */
            function _encodeFeaturesConfig(features) {
                return Object.keys(features || {}).reduce(function (acc, key) {
                    acc[key] = _encodeFeatureConfig(features[key]);
                    return acc;
                }, {});
            }

            /**
             * Compare the previously saved features configurations with the updated list
             * and identify changed features keys.
             *
             * @param {Object} newEncodedConfigs  New features configurations
             * @param {Object} oldEncodedConfigs  Old features configurations
             * @return {Object}                   Features that already have a cached value
             */
            function _findCachedFeatures(newEncodedConfigs, oldEncodedConfigs) {
                var newConfigs = newEncodedConfigs || {};
                var oldConfigs = oldEncodedConfigs || {};
                var cached = {};
                var ignoreCache = !!$location.search().noCacheFeatures;


                if (ignoreCache) {
                    return {};
                }

                Object.keys(newConfigs).filter(function (key) {
                    if (newConfigs[key] === oldConfigs[key]) {
                        cached[key] = true;
                    }
                });

                return cached;
            }

            /**
             * Get the currently set features, calculating any added/updated feature values.
             *
             * @param  {Object} userProperties  User's properties
             * @return {Object}                 Updated feature toggles hash
             */
            function _getFeatures(userProperties) {

                var pristineFeatures = _.cloneDeep(FEATURES) || {};
                var enableUrlOverrides = !!_.get(pristineFeatures, 'featureOverridesEnabled.toggle');
                var urlFeatures = _getUrlOverrides() || {};
                var updatedFeatures = {};


                // 1) filter invalid features
                pristineFeatures = _.omit(pristineFeatures, 'featureOverridesEnabled');

                // 2) parse new CMS features content and configuration
                updatedFeatures = _compileUpdatedFeatures(userProperties, pristineFeatures);

                // 3) save the updated CMS configurations in localStorage, so the can be reused
                // in a future session
                StorageDelegate.setFeatures(updatedFeatures.features);
                StorageDelegate.setFeaturesConfig(updatedFeatures.featuresConfigs);

                // 4) override features passed by URL parameters (for this session only)
                _areOverridesEnabled(enableUrlOverrides);

                if (enableUrlOverrides) {
                    Object.keys(urlFeatures).forEach(function (key) {
                        if (urlFeatures[key] !== undefined) {
                            updatedFeatures.features[key] = urlFeatures[key];
                        }
                    });
                }

                return updatedFeatures.features;
            }

            /**
             * Get feature toggles, respecting URL overrides, cache validation for previously saved
             * features, buckets and throttling values.
             *
             * @param  {Object} userProperties  User properties
             * @param  {Object} rawFeatures     Raw features (as in metadata FEATURES)
             * @return {Object}                 Updated features content and configurations
             */
            function _compileUpdatedFeatures(userProperties, rawFeatures) {

                var pristineFeatures = rawFeatures || {};
                var oldFeatures = StorageDelegate.getFeatures() || {};
                var oldFeaturesKeys = Object.keys(oldFeatures);
                var oldFeaturesConfigs = StorageDelegate.getFeaturesConfig() || {};
                var cached = {};
                var features = {};
                var newFeatures = null;
                var newFeaturesConfigs = null;


                // 1) parse new CMS features content and configuration
                newFeatures = window.muton.getFeatureMutations(userProperties, pristineFeatures);
                newFeaturesConfigs = _encodeFeaturesConfig(pristineFeatures);

                // 2) compare previously saved CMS keys with the updated list
                cached = _findCachedFeatures(newFeaturesConfigs, oldFeaturesConfigs);

                // 3) compile the updated features by checking if any of the new features
                // had already a valid value from a previous session
                features = Object.keys(newFeatures).reduce(function (acc, key) {

                    var isBucketKey = _isBucketKey(key);
                    var parentKey = _getParentKey(key);
                    var cachedBucketKey = '';


                    // check  select the correct key when using buckets
                    if (isBucketKey && cached[parentKey]) {
                        cachedBucketKey = _findOtherBucketKey(key, oldFeaturesKeys);

                        if (cachedBucketKey && oldFeatures[cachedBucketKey] !== undefined) {
                            acc[cachedBucketKey] = oldFeatures[cachedBucketKey];
                            return acc;
                        }
                    }

                    // is a cached toggle/throttle or a new one
                    if (cached[key] && oldFeatures[key] !== undefined) {
                        acc[key] = oldFeatures[key];
                    } else {
                        acc[key] = newFeatures[key];
                    }

                    return acc;
                }, {});


                return {
                    features: features,
                    featuresConfigs: newFeaturesConfigs
                };
            }

            /**
             * Is a key from a bucket feature?
             *
             * @example
             * _isBucketKey('showLeftBar') => false
             * _isBucketKey('showLeftBar.active') => true
             *
             * @param  {Strinkg}  key  Feature key
             * @return {Boolean}       Whether it's a bucket key
             */
            function _isBucketKey(key) {
                return (key || '').match(/.*\..*/);
            }

            /**
             * Try to extract the parent key from a key
             *
             * @example
             * _getParentKey('showLeftBar') => showLeftBar
             * _getParentKey('showLeftBar.active') => showLeftBar
             *
             * @param  {Strinkg}  key  Feature key
             * @return {Strinkg}       Parent key (until first dot)
             */
            function _getParentKey(key) {
                return (key || '').replace(/(.*?)\..*/i, '$1');
            }

            /**
             * Has other bucket values cached
             * @param {String} key          Feature key (e.g: showLeftBar.active)
             * @param {Object} oldFeatures  Saved features hash
             * @return {String}             Cached bucket key for with the same parent
             */
            function _findOtherBucketKey(key, oldFeaturesKeys) {
                key = key || '';
                oldFeaturesKeys = oldFeaturesKeys || [];

                var isBucketKey = _isBucketKey(key);
                var parentKey;


                // skip
                if (!isBucketKey){ return ''; }

                parentKey = _getParentKey(key) + '.';

                return _.find(oldFeaturesKeys, function (featureKey) {
                    var isSameKey = (featureKey === key);
                    var hasSameParentKey = (featureKey.indexOf(parentKey) === 0);

                    return !isSameKey && hasSameParentKey;
                });
            }

            /**
             * Manually force feature values updates
             * (does not create new features!)
             *
             * @param {Object} features  Forced features
             */
            function _setFeatures(features) {
                StorageDelegate.setFeatures(features);
            }

            /**
             * Get/set "_overridesEnabled" flag value that controls whether URL
             * feautre overrides should be enabled
             *
             * @param  {Boolean} [value]  Set a value to enable/disable feature overrides
             * @return {Boolean}          Whether feature overrides are enabled
             */
            function _areOverridesEnabled(value) {

                if (typeof value === 'boolean') {
                    _overridesEnabled = value;
                }

                return !!_overridesEnabled;
            }

            return {
                getFeatures: _getFeatures,
                setFeatures: _setFeatures,
                areOverridesEnabled: _areOverridesEnabled,
                _compileUpdatedFeatures: _compileUpdatedFeatures // for unit-tests
            };
        }

        FeaturesFac.$inject = [
            '$location',
            'FEATURES',
            'LocalStorageFac',
            'md5'
        ];

        return FeaturesFac;
    });

modules/Features/controllers/featuresConfigController.js
"use strict";

define('FeaturesConfigController',[],function () {

    function FeaturesConfigController($scope, FeaturesHandlerSvc) {

        $scope.onFeatureStateChange = function (name, state) {
            FeaturesHandlerSvc.changeFeatureState(name, state);
            FeaturesHandlerSvc.overrideFeatures();
        };

        var features = FeaturesHandlerSvc.getFeatures();
        $scope.features = [];

        for (var key in features.activeFeatures) {
            $scope.features.push({
                name: key,
                value: features.activeFeatures[key]
            });
        }
    }

    FeaturesConfigController.$inject = [
        '$scope',
        'FeaturesHandlerSvc'
    ];

    return FeaturesConfigController;
});

modules/Features/featuresMod.js
"use strict";

define(
    'Features',[
        "FeaturesFac",
        "FeaturesConfigController"
    ],
    function (FeaturesFac, FeaturesConfigController) {

        angular
            .module("TVG.Features", [])
            .run(["$uibModal", "$rootScope", "$templateCache", function ($uibModal, $rootScope, $templateCache) {
                function shouldShowFeaturesConfigModal(){
                    return window.location.href.indexOf("?features") >= 0;
                }

                function showFeaturesConfigModal(){
                    $uibModal.open({
                        backdrop: 'static',
                        windowTemplateUrl: 'src/templates/features-modal-window.html',
                        templateUrl: 'js/modules/Features/templates/feature-overrides-panel.html',
                        controller: 'FeaturesConfigController'
                    });
                }

                function init(){
                    // TODO - the following code couples this module to the FeaturesHandlerSvc with bi-directional inter dependency, this should be fixed
                    $rootScope.$watch('featureOverridesEnabled', function (featureOverridesEnabled) {
                        if(featureOverridesEnabled && shouldShowFeaturesConfigModal()){
                            addFeaturesConfigModalWindowTemplateToTemplateCache();
                            showFeaturesConfigModal();
                        }
                    });
                }

                init();

                function addFeaturesConfigModalWindowTemplateToTemplateCache(){
                    $templateCache.put('src/templates/features-modal-window.html',
                        "<div tabindex=\"-1\" class=\"modal features-config-modal no-click-feedback\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\" ng-click=\"$close($event)\"><div class=\"modal-dialog\"><div class=\"modal-content\" ng-transclude ></div></div></div>"
                    );
                }

            }])
            .factory("FeaturesFac", FeaturesFac)
            .controller("FeaturesConfigController", FeaturesConfigController);

    }
);



modules/Tracks/components/trackSelector/directives/track-selector-directive.js
'use strict';

define(
    'TrackSelectorDir',[],function () {
        function TrackSelectorDir() {
            return {
                restrict: 'E',
                templateUrl: 'js/modules/Tracks/components/trackSelector/templates/track-selector.html',
                controller: 'TrackSelectorCtrl',
                controllerAs: 'trackSelectorCtrl',
                bindToController: true,
                scope: {
                    trackSelectorDefaultOption: "=",
                    trackSelectorOnChange: "&",
                    trackSelectorType: "="
                }
            };
        }

        TrackSelectorDir.$inject = [

        ];
        return TrackSelectorDir;
    }
);


modules/Tracks/components/trackSelector/controllers/trackSelectorCtrl.js
'use strict';

define('TrackSelectorCtrl',['lodash'],
        function (_) {

            /***
             * This Controller is bound to the track-selector directive
             * Inherits trackSelectorDefaultOptions (string) ; trackSelectorOnChange (function)
             * @constructor
             */
            function TrackSelectorCtrl(
                $scope,
                $rootScope,
                $location,
                $injector,
                GTMFac,
                GraphTrackList,
                GraphRacesNavigation,
                $log,
                WagerProfileFac,
                RaceUrlFac,
                $routeParams,
                $filter,
                $window
            ) {
                var vm = this;
                var trackFactory;
                var trackListSubscription;
                var options;
                var optionsRaces;
                var wagerProfile;
                var subscriptionTime = $filter('CMSLabels')('low', 'graphqlPollingRates') || 30000; // in ms
                var races = [];
                var routeParams;
                var selectedTrack;

                vm.model = {
                    favoriteTracks: [],
                    featuredTracks: [],
                    allTracks: [],
                    dropdown: {
                        isOpen: false,
                        selectedTrackName: ""
                    },
                    isLoading: false
                };


                vm.events = {
                    onChangeSelectedTrack: function (track) {
                        if ($window.opener && $window.opener.talentPickHost) {
                            $window.opener.talentPickHost = "";
                        }
                        
                        optionsRaces = {
                            wagerProfile: wagerProfile,
                            trackAbbr: track.trackAbbr
                        };
                        GraphRacesNavigation.get(optionsRaces).then(function (response) {
                            races = response;

                            races.forEach(function (graphRace) {
                                graphRace.raceNumber = parseInt(graphRace.raceNumber, 10);
                            });
                            track.races = races;

                            vm.trackSelectorOnChange({track: track});
                            vm.trackSelectorDefaultOption = track.trackName;

                            sendBetSlipEvent(track);

                            $rootScope.$emit('raceListReady', races, track.trackAbbr);
                        });
                    },
                    goToFavorites: function () {
                        $location.path("/my-profile").hash("favorites+my-tracks");
                    },
                    openModalMenu: function () {
                        $rootScope.$emit("callLoginRequiredModal");
                    },
                    sendCloseTrackSelectorGTMEvent: sendGtmDropdownEvent
                };

                vm.trackId = function (track) {
                    return [track.trackAbbr, track.perfAbbr, track.raceNumber].join('_');
                };

                function sendBetSlipEvent(track) {

                    var trackCategory;
                    if (_.includes(vm.model.favoriteTracks, track)) {
                        trackCategory = 'Favorite Tracks';
                    } else if (_.includes(vm.model.featuredTracks, track)) {
                        trackCategory = 'Popular Tracks';
                    } else {
                        trackCategory = 'Other Tracks';
                    }

                    var eventData = GTMFac.gaEventBuilder()
                        .withGaEventAction(GTMFac.Tvg4ScreenName() + ' Click')
                        .withGaEventCategory('Site Click')
                        .withGaEventLabel('Tracks | ' + trackCategory)
                        .withEventLabel('BetTicket-TrackDropDown')
                        .build();

                    GTMFac.GTMEvent().send($rootScope, 'siteClick', GTMFac.genericEvent(eventData));
                }

                function sendGtmDropdownEvent(val) {
                    if (val) {
                        var eventData = GTMFac.gaEventBuilder()
                            .withGaEventAction(GTMFac.Tvg4ScreenName() + ' Click')
                            .withGaEventCategory('Site Click')
                            .withGaEventLabel('Top Nav | Close Window')
                            .withEventLabel('TopNav-CloseTrackList')
                            .build();

                        GTMFac.GTMEvent().send($rootScope, 'siteClick', GTMFac.genericEvent(eventData));
                    }
                }

                $scope.$on('updateTrackUrl', function (event, race) {
                    vm.events.onChangeSelectedTrack(race);
                });

                function _setViewModelTracksBasedOnTrackList(trackList) {
                    selectedTrack = RaceUrlFac.getRacesInfoFromRouteParams().trackAbbr || $routeParams.trackAbbr;
                    // Hammer Time!! Because graph is return the race number as a string
                    /* istanbul ignore next */
                    trackList.forEach(function (track) {
                        if(track.trackAbbr == selectedTrack) {
                            track.races = races;
                            track.races.forEach(function (race) {
                                race.raceNumber = parseInt(race.raceNumber, 10);
                            });
                        }
                    });

                    vm.model.favoriteTracks = trackFactory.createTrackSelectorItemsForFavoriteTracks(trackList);
                    vm.model.featuredTracks = trackFactory.createTrackSelectorItemsForFeaturedTracks(trackList);
                    vm.model.allTracks = trackFactory.createTrackSelectorItemsForAllTracks(trackList);

                    $rootScope.$emit('trackListReady', trackList);
                }

                function _buildTrackListFromGraph(trackList) {
                    var track = _.find(trackList, function (track) {
                        return track.trackAbbr === selectedTrack;
                    });

                    if (!track) {
                        // means the user logged in with a profile that doesn't allow betting for this race, so lets say its the first track available (ordered alphabetically)
                        // TODO: this should be the track that has the closest race to bet ATM
                        track = trackList[0];
                        selectedTrack = track.trackAbbr;
                        $rootScope.$broadcast('video:stop', { instanceId: 'video-main-programpage' });
                        vm.model.isLoading = false;
                    }

                    optionsRaces = {
                        wagerProfile: wagerProfile,
                        trackAbbr: selectedTrack
                    };

                    GraphRacesNavigation.get(optionsRaces).then(function (response) {
                        //fix race selector not being updated
                        if (response.length && response[0].trackAbbr !== $routeParams.trackAbbr) {
                            vm.model.isLoading = false;
                            return;
                        }

                        races = response;

                        // TODO: remove this one graph returns raceNumber as int
                        races.forEach(function (graphRace) {
                            graphRace.raceNumber = parseInt(graphRace.raceNumber, 10);
                        });

                        track.races = races;
                        _setViewModelTracksBasedOnTrackList(trackList);
                        vm.model.isLoading = false;

                        if ($scope.$root && !$scope.$root.$$phase) {
                            $scope.$apply();
                        }
                    });
                }

                function _populateViewModelWithTracks() {
                    vm.model.isLoading = true;

                    // Graph request
                    wagerProfile = WagerProfileFac.getSessionOrGenericProfile();
                    options = {
                        wagerProfile: wagerProfile,
                        filter: {
                            isGreyhound: $rootScope.isGreyhoundRace
                        }
                    };

                    if (!trackListSubscription) {
                        trackListSubscription = GraphTrackList.subscribe(options, {
                            success: _buildTrackListFromGraph,
                            fail: function (error) {
                                $log.error(error); // eslint-disable-line
                                vm.model.isLoading = false;
                            }
                        }, subscriptionTime, true);
                    } else {
                        GraphTrackList.refetch({wagerProfile: WagerProfileFac.getSessionOrGenericProfile()}).then(_buildTrackListFromGraph);
                    }
                }

                function _selectTrackSelectorFactory() {
                    switch (vm.trackSelectorType) {
                        case "programPage":
                            trackFactory = $injector.get('TrackSelectorItemCurrentRaceFactory');
                            break;
                        default:
                            trackFactory = $injector.get('TrackSelectorItemFactory');
                    }

                }

                (function init() {
                    routeParams = RaceUrlFac.getRacesInfoFromRouteParams();

                    if (routeParams.trackAbbr && routeParams !== '') {
                        selectedTrack = routeParams.trackAbbr;
                    } else {
                        selectedTrack = $routeParams.trackAbbr;
                    }

                    _selectTrackSelectorFactory();

                    if ($rootScope.restartBetslipSubscribe){
                        _populateViewModelWithTracks();
                        delete $rootScope.restartBetslipSubscribe;
                    }
                }());

                $scope.$on("$destroy", function () {
                    if (trackListSubscription){
                        trackListSubscription.unsubscribe();
                    }
                });

                var unbindOnSession = $scope.$on('session', function () {
                    _populateViewModelWithTracks();
                    unbindOnSession();
                });

                $scope.$on('user', _populateViewModelWithTracks);

            }

            TrackSelectorCtrl.$inject = [
                '$scope',
                '$rootScope',
                '$location',
                '$injector',
                'GTMFac',
                'GraphTrackList',
                'GraphRacesNavigation',
                '$log',
                'WagerProfileFac',
                'RaceUrlFac',
                '$routeParams',
                '$filter',
                "$window"
            ];

            return TrackSelectorCtrl;
        }
);

modules/Tracks/components/trackSelector/models/trackSelectorItem.js
'use strict';

define(
    'TrackSelectorItem',[
        'moment'
    ],
    function (moment) {

        function TrackSelectorItem(trackName, trackAbbr, raceNumber, racePostTime, perfAbbr) {
            this.trackName = trackName;
            this.trackAbbr = trackAbbr;
            this.raceNumber = raceNumber;
            this.racePostTime = racePostTime;
            this.perfAbbr = perfAbbr;
        }

        /***
         * This method checks if the time for the start of the race is less than 2h.
         * If so, it shows the MTP, otherwise, it shows the time in format HH:MM.
         */
        TrackSelectorItem.prototype.getTimeToBeDisplayed = function () {
            var timeToBeDisplayed = "N/A";
            var currentTime = new Date().getTime();

            var milisecondsToRaceStart = this.racePostTime - currentTime;
            var minutesToRaceStart = milisecondsToRaceStart / 1000 / 60;

            // 0 < minutesToRaceStart < 60
            if (minutesToRaceStart >= 0 && minutesToRaceStart <= 60) {
                timeToBeDisplayed = Math.round(minutesToRaceStart).toString() + " MTP";
            }
            // minutesToRaceStart < 0
            else if (minutesToRaceStart < 0) {
                timeToBeDisplayed = "0 MTP";
            }
            // minutesToRaceStart >= 60
            else {
                timeToBeDisplayed = moment(this.racePostTime).format("hh:mm A");
            }

            return timeToBeDisplayed;
        };

        return TrackSelectorItem;

    });

modules/Tracks/components/trackSelector/models/builders/trackSelectorItemBuilder.js
'use strict';

define(
    'TrackSelectorItemBuilder',[
        'TrackSelectorItem'
    ],
    function (TrackSelectorItem) {

        function TrackSelectorItemBuilder() {

            var trackSelectorItem = new TrackSelectorItem();

            return {
                withTrackAbbr: function (trackAbbr) {
                    trackSelectorItem.trackAbbr = trackAbbr;
                    return this;
                },
                withTrackName: function (trackName) {
                    trackSelectorItem.trackName = trackName;
                    return this;
                },
                withRaceNumber: function (raceNumber) {
                    trackSelectorItem.raceNumber = raceNumber;
                    return this;
                },
                withPostTime: function (racePostTime) {
                    trackSelectorItem.racePostTime = racePostTime;
                    return this;
                },
                withPerfAbbr: function (perfAbbr) {
                    trackSelectorItem.perfAbbr = perfAbbr;
                    return this;
                },
                withCurrentWagerableRace: function (currentWagerableRace) {
                    trackSelectorItem.currentWagerableRace = currentWagerableRace;
                    return this;
                },
                build: function () {
                    return trackSelectorItem;
                }
            };

        }

        return TrackSelectorItemBuilder;

    });

modules/Tracks/components/trackSelector/factories/trackSelectorItemFactory.js
'use strict';

define(
    'TrackSelectorItemFactory',[
        'TrackSelectorItemBuilder'
    ],
    function (TrackSelectorItemBuilder) {

        function TrackSelectorItemsFactory(FavoriteTracksFac) {

            var _mappers = {
                toTrackSelectorItem: function (trackName, trackAbbr, raceNumber, racePostTime, perfAbbr) {
                    return TrackSelectorItemBuilder()
                        .withTrackName(trackName)
                        .withTrackAbbr(trackAbbr)
                        .withRaceNumber(raceNumber)
                        .withPostTime(racePostTime)
                        .withPerfAbbr(perfAbbr)
                        .build();
                }
            };

            function _mapToTrackSelectorItem(track) {
                return _mappers.toTrackSelectorItem(track.name, track.trackAbbr, track.currentWagerableRace, track.currentWagerableRacePostTime, track.perfAbbr);
            }

            return {
                createTrackSelectorItemsForFavoriteTracks: function (tracks) {
                    var favoritesTracks = FavoriteTracksFac.getFavoriteTracks();
                    if (!favoritesTracks || favoritesTracks.length === 0) {
                        return [];
                    }
                    return tracks.filter(function (track) {
                        return track.currentWagerableRace !== 0 && favoritesTracks.indexOf(track.trackAbbr) >= 0;
                    }).map(_mapToTrackSelectorItem);
                },

                createTrackSelectorItemsForFeaturedTracks: function (tracks) {
                    return tracks.filter(function (track) {
                        return track.currentWagerableRace !== 0 && track.featured == true;
                    }).map(_mapToTrackSelectorItem);
                },

                createTrackSelectorItemsForAllTracks: function (tracks) {
                    return tracks.filter(function (track) {
                        return track.currentWagerableRace !== 0;
                    }).map(_mapToTrackSelectorItem);
                }
            };

        }

        TrackSelectorItemsFactory.$inject = [
            'FavoriteTracksFac'
        ];

        return TrackSelectorItemsFactory;
    }
);




modules/Tracks/components/trackSelector/factories/trackSelectorItemCurrentRaceFactory.js
'use strict';

define(
    'TrackSelectorItemCurrentRaceFactory',[
        'TrackSelectorItemBuilder'
    ],
    function (TrackSelectorItemBuilder) {

        function TrackSelectorItemsCurrentRaceFactory(FavoriteTracksFac) {

            var _mappers = {
                toTrackSelectorItem: function (trackName, trackAbbr, raceNumber, racePostTime, perfAbbr, currentWagerableRace) {
                    return TrackSelectorItemBuilder()
                        .withTrackName(trackName)
                        .withTrackAbbr(trackAbbr)
                        .withRaceNumber(raceNumber)
                        .withPostTime(racePostTime)
                        .withPerfAbbr(perfAbbr)
                        .withCurrentWagerableRace(currentWagerableRace)
                        .build();
                }
            };

            function _mapToTrackSelectorItem(track) {
                return _mappers.toTrackSelectorItem(track.name, track.trackAbbr, track.currentRace, track.currentWagerableRacePostTime, track.perfAbbr, track.currentWagerableRace);
            }

            return {
                createTrackSelectorItemsForFavoriteTracks: function (tracks) {
                    var favoritesTracks = FavoriteTracksFac.getFavoriteTracks();
                    if (!favoritesTracks || favoritesTracks.length === 0) {
                        return [];
                    }
                    return tracks.filter(function (track) {
                        return track.currentRace !== 0 && favoritesTracks.indexOf(track.trackAbbr) >= 0;
                    }).map(_mapToTrackSelectorItem);
                },

                createTrackSelectorItemsForFeaturedTracks: function (tracks) {
                    return tracks.filter(function (track) {
                        return track.currentRace !== 0 && track.featured == true;
                    }).map(_mapToTrackSelectorItem);
                },

                createTrackSelectorItemsForAllTracks: function (tracks) {
                    return tracks.filter(function (track) {
                        return track.currentRace !== 0;
                    }).map(_mapToTrackSelectorItem);
                }
            };

        }

        TrackSelectorItemsCurrentRaceFactory.$inject = [
            'FavoriteTracksFac'
        ];

        return TrackSelectorItemsCurrentRaceFactory;
    }
);

modules/Tracks/components/trackSelector/trackSelectorMod.js
'use strict';

define(
    'TrackSelector',[
        'TrackSelectorDir',
        'TrackSelectorCtrl',
        'TrackSelectorItemFactory',
        'TrackSelectorItemCurrentRaceFactory',
        'uibootstrap',
        'uibootstraptpls',
        'GTMMod'
    ],

    function TrackSelectorModule(TrackSelectorDir, TrackSelectorCtrl, TrackSelectorItemFactory, TrackSelectorItemCurrentRaceFactory) {
        angular.module('TVG.TrackSelector', [
            'ui.bootstrap',
            'TVG.Common.GTM'
        ])
            .factory('TrackSelectorItemFactory', TrackSelectorItemFactory)
            .factory('TrackSelectorItemCurrentRaceFactory', TrackSelectorItemCurrentRaceFactory)
            .controller('TrackSelectorCtrl', TrackSelectorCtrl)
            .directive('trackSelector', TrackSelectorDir);
    }
);

tvg.templates.js
angular.module('TVG.Templates', ['js/modules/BetSlipWindow/templates/betslip-account-info.html', 'js/modules/BetSlipWindow/templates/betslip-alert-banner.html', 'js/modules/BetSlipWindow/templates/betslip-message.html', 'js/modules/BetSlipWindow/templates/betslip-view-bet.html', 'js/modules/BetSlipWindow/templates/betslip-view-confirm.html', 'js/modules/BetSlipWindow/templates/betslip-view-receipt.html', 'js/modules/BetSlipWindow/templates/betslip-window-form.html', 'js/modules/BetSlipWindow/templates/betslip-window.html', 'js/modules/BetSlipWindow/templates/round-up-message.html', 'js/modules/BetSlipWindow/templates/track-selector-window.html', 'js/modules/Features/templates/feature-overrides-panel.html', 'js/modules/Races/components/raceMtpLabel/templates/race-mtp-label.html', 'js/modules/Tracks/components/trackSelector/templates/track-selector.html', 'js/modules/UserProfile/templates/quick-deposit.html', 'js/modules/Utilities/directives/templates/states.html', 'js/modules/Utilities/templates/modal-window.html', 'js/views/betslip-window.html']);

angular.module("js/modules/BetSlipWindow/templates/betslip-account-info.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-account-info.html",
    "<div class=bet-slip-window__account qa-label=betSlipAccountInfo><h1 ng-if=\"$root.accountBalance && data.showBalance === 1\"><div class=balance-label><span>Balance</span> <span class=tvg-icon-refresh-icon ng-click=events.updateBalance() ng-class=\"{'rotate': data.updatingBalance}\"></span></div><span qa-label=balanceValue class=value>{{$root.accountBalance}}</span></h1><ul><li ng-if=\"$root.activeFeatures['showDepositBetSlip']\"><a href qa-label=quickDepositButton class=deposit-btn ng-click=events.openQuickDeposit()><i class=\"tvg-icon tvg-icon-deposit-funds\"></i> <span>Quick Deposit</span></a></li></ul></div>");
}]);

angular.module("js/modules/BetSlipWindow/templates/betslip-alert-banner.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-alert-banner.html",
    "<div class=betslip_feedback ng-class=\"{\n" +
    "    'betslip_alert': type === 'warning',\n" +
    "    'betslip_error': type === 'error',\n" +
    "    'betslip_success': type === 'success',\n" +
    "    'betslip_info': type === 'info'\n" +
    "}\"><div class=close-message ng-if=closeable><a qa-label=close-message-button href=\"\" ng-click=\"close({$event: $event})\"><i class=tvg-icon-times></i></a></div><div><i class=betslip_feedback__icon ng-class=\"'tvg-icon-' + type\"></i><div qa-label=\"betticket-{{ type }}-message\" class=betslip_feedback__message ng-bind-html=message></div></div></div>");
}]);

angular.module("js/modules/BetSlipWindow/templates/betslip-message.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-message.html",
    "<div name=loginError class=\"modal-header text-centered\">{{data.infoTitle}}</div><table class=error><tr><td><span>{{data.infoMessage}}</span></td></tr></table><div name=errorFooter class=modal-footer><button class=gray ng-click=events.closeInfoMessage()>Ok</button></div>");
}]);

angular.module("js/modules/BetSlipWindow/templates/betslip-view-bet.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-view-bet.html",
    "<table class=betslip-layout-group><tr><td class=bet-header qa-label=betticket-header><header><div class=track-selector__mtp qa-label=mtp><i class=\"tvg-icon tvg-icon-mtp\" ng-class=\"{'mtp-near' : data.mtp.status == 'near',\n" +
    "                                      'mtp-med' : data.mtp.status == 'med',\n" +
    "                                      'mtp-far' : data.mtp.status == 'far',\n" +
    "                                      'mtp-hide' : data.mtp.status == 'time-format'}\"></i> <span ng-bind=data.mtp.time></span></div><betslip-account-info></betslip-account-info><betslip-alert-banner ng-repeat=\"alert in alerts track by $index\" type={{alert.type}} closeable={{alert.closeable}} message={{alert.message}} close=\"!alert.closeForever ? events.closeAlert($index) : events.closeAlertForever($index)\"></betslip-alert-banner><div class=header-form><track-selector-window></track-selector-window><ng-include src=\"'js/modules/BetSlipWindow/templates/betslip-window-form.html'\"></ng-include></div></header></td></tr><tr><td class=bet-top><div class=overlay ng-if=data.currentRace.closedForBetting></div><table qa-label=betSlip-runners-header class=\"table bet-slip-window__runners\"><thead><tr class=first-row ng-if=\"data.layoutType !== 'single'\"><th class=header-id><span ng-if=\"data.layoutType == 'multiple' && !data.selectedBetType.isKey\" ng-bind=data.selectedBetType.columnType></span></th><th ng-if=\"data.layoutType == 'multiple' && data.isLeg\" ng-class=\"{'active': data.activeTab === col}\" ng-repeat=\"(col, runners) in data.legRacesRunners track by $index\" ng-mouseenter=\"data.activeTab = col\"><span qa-label=raceId ng-bind=\"col + 1\"></span></th><th ng-if=\"data.layoutType == 'multiple' && !data.isLeg && !data.selectedBetType.isKey\" ng-class=\"{'active': data.activeTab === col}\" ng-repeat=\"(col, pos) in data.cols track by $index\" ng-mouseenter=\"data.activeTab = col\"><span qa-label=raceId>{{ pos }}{{ col === 0 ? 'st' : (col === 1 ? 'nd' : (col === 2 ? 'rd' : 'th')) }}</span></th><th ng-if=\"data.layoutType == 'multiple' && data.selectedBetType.isKey\" ng-class=\"{'active': data.activeTab === col}\" ng-repeat=\"(col, pos) in data.cols\" ng-mouseenter=\"data.activeTab = col\"><span ng-if=\"col === 0\">Key</span> <span ng-if=\"col > 0\">W/</span></th><th colspan=2></th></tr><tr ng-class=\"{'single': data.layoutType === 'single', 'key': data.selectedBetType.isKey}\"><th class=header-id>#</th><th ng-if=\"data.layoutType == 'single'\" class=header-selection><label class=\"checkbox green\"><input type=checkbox ng-class=\"{checked: events.isSelectedAll(data.activeTab), dashed: data.selectedBetType.isKey && data.activeTab == 0}\" ng-click=\"(!data.selectedBetType.isKey || data.activeTab != 0) && events.toggleAll(data.colsChecked[data.activeTab], data.activeTab)\" ng-checked=events.isSelectedAll(data.activeTab) ng-disabled=\"data.selectedBetType.isKey && data.activeTab == 0\"> <span><i class=tvg-icon-check></i></span></label></th><th class=header-selection ng-class=\"{'active': data.activeTab === col}\" ng-if=\"data.layoutType == 'multiple' && data.isLeg\" ng-repeat=\"(col, runners) in data.legRacesRunners\" ng-mouseenter=\"data.activeTab = col\"><label class=\"checkbox green\"><input type=checkbox ng-class=\"{checked: events.isSelectedAll(col)}\" ng-checked=events.isSelectedAll(col) ng-click=\"events.toggleAll(data.colsChecked[col], col)\"> <span><i class=tvg-icon-check></i></span></label></th><th class=header-selection ng-class=\"{'active': data.activeTab === col}\" ng-if=\"data.layoutType == 'multiple' && !data.isLeg && !data.selectedBetType.isKey\" ng-repeat=\"(col, pos) in data.cols\" ng-mouseenter=\"data.activeTab = col\"><label class=\"checkbox green\"><input type=checkbox ng-class=\"{checked: events.isSelectedAll(col)}\" ng-checked=events.isSelectedAll(col) ng-click=\"events.toggleAll(data.colsChecked[col], col)\"> <span><i class=tvg-icon-check></i></span></label></th><th class=header-selection ng-class=\"{'active': data.activeTab === col}\" ng-if=\"data.layoutType == 'multiple' && data.selectedBetType.isKey\" ng-repeat=\"(col, pos) in data.cols\" ng-mouseenter=\"data.activeTab = col\"><span class=key><i ng-if=\"col == 0\" class=tvg-icon-key></i></span><label class=\"checkbox green\" ng-if=\"col > 0\"><input type=checkbox ng-class=\"{checked: events.isSelectedAll(col)}\" ng-checked=events.isSelectedAll(col) ng-click=\"events.toggleAll(data.colsChecked[col], col)\"> <span><i class=tvg-icon-check></i></span></label></th><th class=header-odds ng-class=\"{'oddTitleScratchedHorse': events.isScratchedHorseInList()}\">Odds</th><th class=header-horse>Runner Name</th></tr></thead></table></td></tr><tr><td><div class=overlay ng-if=data.currentRace.closedForBetting><div class=overlay__message ng-bind=data.closedForBettingMessage></div></div><div class=bet-runner-list><table qa-label=betSlip-runners class=\"table bet-slip-window__runners\"><tbody ng-if=\"data.layoutType == 'single'\"><tr qa-label=runner-in-list ng-repeat=\"runner in data.runners\" ng-class=\"{'runner--scratched': events.areAllRunnersScratched(runner), 'runner--select': events.isSelected(runner.bettingInterestNumber, data.activeTab)}\"><td class=runner__id qa-label=runner-id><span ng-if=!isGreyhoundRace ng-style=\"{'background-color': runner.saddleColor, 'color': runner.numberColor}\"><span ng-bind=runner.horseID></span> </span><span ng-if=isGreyhoundRace class=\"saddle dog-saddle-{{runner.bettingInterestNumber}}\" ng-bind=runner.bettingInterestNumber></span></td><td class=runner__check><label class=\"checkbox green\" qa-label=runner-checkbox><input type=checkbox ng-click=\"!events.areAllRunnersScratched(runner) && events.toggleSelection(runner.bettingInterestNumber, data.activeTab)\" ng-checked=\"!events.areAllRunnersScratched(runner) && events.isSelected(runner.bettingInterestNumber, data.activeTab)\" ng-disabled=events.areAllRunnersScratched(runner)> <span><i class=tvg-icon-check></i></span></label></td><td class=runner__odds qa-label=runner-odds ng-class=\"{'scratched': events.areAllRunnersScratched(runner)}\"><span ng-if=!events.areAllRunnersScratched(runner) ng-class=\"{'runner__odds--favorite' : runner.favorite === true}\" ng-bind=runner.currentOddsString></span> <span ng-if=events.areAllRunnersScratched(runner)>SCRATCHED</span></td><td class=runner__horse qa-label=runner-horse-name><span class=runner__horse-name ng-bind=runner.horseName ng-class=\"{'scratched': runner.scratched }\"></span> <span ng-if=runner.coupledRunners><span ng-repeat=\"coupledRunner in runner.coupledRunners track by $index\">&nbsp;/&nbsp; <span class=runner__horse-name ng-bind=coupledRunner.horseName ng-class=\"{'scratched': coupledRunner.scratched }\"></span></span></span></td></tr></tbody><tbody ng-if=\"data.layoutType == 'multiple' && data.isLeg\"><tr qa-label=runner-in-list ng-repeat=\"(row, runners) in data.legColumnHeight track by $index\" ng-class=\"{'runner--select': events.isSelected(data.legRacesRunners[data.activeTab][row].bettingInterestNumber, data.activeTab),\n" +
    "                                   'runner--scratched': events.areAllRunnersScratched(data.legRacesRunners[data.activeTab][row])}\"><td class=runner__id qa-label=runner-id><span ng-if=\"!isGreyhoundRace && events.legHasRunner(row, data.activeTab)\" ng-style=\"{'background-color': data.legRacesRunners[data.activeTab][row].saddleColor, 'color': data.legRacesRunners[data.activeTab][row].numberColor}\"><span ng-bind=data.legRacesRunners[data.activeTab][row].horseID></span> </span><span ng-if=\"isGreyhoundRace && events.legHasRunner(row, data.activeTab)\" class=\"saddle dog-saddle-{{data.legRacesRunners[data.activeTab][row].bettingInterestNumber}}\" ng-bind=data.legRacesRunners[data.activeTab][row].horseID></span></td><td class=runner__check ng-repeat=\"(col, runners) in data.legRacesRunners track by $index\" ng-class=\"{'active': data.activeTab === col,\n" +
    "                                       'selected': events.isSelected(data.legRacesRunners[col][row].bettingInterestNumber, col),\n" +
    "                                       'scratched': events.areAllRunnersScratched(data.legRacesRunners[col][row])}\" ng-mouseenter=\"data.activeTab = col\"><label class=\"checkbox green\" qa-label=runner-checkbox ng-if=\"events.legHasRunner(row, col)\"><input type=checkbox class=native ng-click=\"!events.areAllRunnersScratched(data.legRacesRunners[col][row]) && events.toggleSelection(data.legRacesRunners[col][row].bettingInterestNumber, col)\" ng-checked=\"!events.areAllRunnersScratched(data.legRacesRunners[col][row]) && events.isSelected(data.legRacesRunners[col][row].bettingInterestNumber, col)\" ng-disabled=events.areAllRunnersScratched(data.legRacesRunners[col][row])> <span><i class=tvg-icon-check></i></span></label></td><td class=runner__odds qa-label=runner-odds ng-class=\"{'scratched': events.areAllRunnersScratched(data.legRacesRunners[col][row])}\"><span ng-if=\"events.legHasRunner(row, data.activeTab) && !events.areAllRunnersScratched(data.legRacesRunners[col][row])\" ng-class=\"{'runner__odds--favorite' : data.legRacesRunners[data.activeTab][row].favorite === true}\" ng-bind=data.legRacesRunners[data.activeTab][row].currentOddsString></span> <span ng-if=\"events.legHasRunner(row, data.activeTab) && events.areAllRunnersScratched(data.legRacesRunners[col][row])\">SCRATCHED</span></td><td class=runner__horse qa-label=runner-horse-name><span class=runner__horse-name ng-bind=data.legRacesRunners[data.activeTab][row].horseName ng-class=\"{'scratched': data.legRacesRunners[data.activeTab][row].scratched }\"></span> <span ng-if=data.legRacesRunners[data.activeTab][row].coupledRunners><span ng-repeat=\"coupledRunner in data.legRacesRunners[data.activeTab][row].coupledRunners track by $index\">&nbsp;/&nbsp; <span class=runner__horse-name ng-bind=coupledRunner.horseName ng-class=\"{'scratched': coupledRunner.scratched }\"></span></span></span></td></tr></tbody><tbody ng-if=\"data.layoutType == 'multiple' && !data.isLeg && !data.selectedBetType.isKey\"><tr qa-label=runner-in-list ng-repeat=\"runner in data.runners track by $index\" ng-class=\"{'runner--scratched': events.areAllRunnersScratched(runner), 'runner--select': events.isSelected(runner.bettingInterestNumber, data.activeTab)}\"><td class=runner__id qa-label=runner-id><span ng-if=!isGreyhoundRace ng-style=\"{'background-color': runner.saddleColor, 'color': runner.numberColor}\"><span ng-bind=runner.horseID></span> </span><span ng-if=isGreyhoundRace class=\"saddle dog-saddle-{{runner.bettingInterestNumber}}\" ng-bind=runner.bettingInterestNumber></span></td><td class=runner__check ng-repeat=\"(col, pos) in data.cols track by $index\" ng-class=\"{'active': data.activeTab === col, 'selected': events.isSelected(runner.bettingInterestNumber, col)}\" ng-mouseenter=\"data.activeTab = col\"><label class=\"checkbox green\" qa-label=runner-checkbox><input type=checkbox class=native ng-click=\"!events.areAllRunnersScratched(runner) && events.toggleSelection(runner.bettingInterestNumber, col)\" ng-checked=\"!events.areAllRunnersScratched(runner) && events.isSelected(runner.bettingInterestNumber, col)\" ng-disabled=events.areAllRunnersScratched(runner)> <span><i class=tvg-icon-check></i></span></label></td><td class=runner__odds qa-label=runner-odds ng-class=\"{'scratched': events.areAllRunnersScratched(runner)}\"><span ng-if=!events.areAllRunnersScratched(runner) ng-class=\"{'runner__odds--favorite' : runner.favorite === true}\" ng-bind=runner.currentOddsString></span> <span ng-if=events.areAllRunnersScratched(runner)>SCRATCHED</span></td><td class=runner__horse qa-label=runner-horse-name><span class=runner__horse-name ng-bind=runner.horseName ng-class=\"{'scratched': runner.scratched }\"></span> <span ng-if=runner.coupledRunners><span ng-repeat=\"coupledRunner in runner.coupledRunners track by $index\">&nbsp;/&nbsp; <span class=runner__horse-name ng-bind=coupledRunner.horseName ng-class=\"{'scratched': coupledRunner.scratched }\"></span></span></span></td></tr></tbody><tbody ng-if=\"data.layoutType == 'multiple' && data.selectedBetType.isKey\"><tr qa-label=runner-in-list ng-repeat=\"runner in data.runners track by $index\" ng-class=\"{'runner--scratched': events.areAllRunnersScratched(runner),\n" +
    "                                   'runner--select': events.isSelected(runner.bettingInterestNumber, data.activeTab)}\"><td class=runner__id qa-label=runner-id><span ng-if=!isGreyhoundRace ng-style=\"{'background-color': runner.saddleColor, 'color': runner.numberColor}\"><span ng-bind=runner.horseID ng-class=\"{'scratched': runner.scratched }\"></span> </span><span ng-if=isGreyhoundRace class=\"saddle dog-saddle-{{runner.bettingInterestNumber}}\" ng-bind=runner.bettingInterestNumber></span></td><td class=runner__check ng-repeat=\"(col, pos) in data.cols track by $index\" ng-class=\"{'active': data.activeTab === col,\n" +
    "                                       'selected': events.isSelected(runner.bettingInterestNumber, col)}\" ng-mouseenter=\"data.activeTab = col\"><label class=\"checkbox green\" qa-label=runner-checkbox><input type=checkbox class=native ng-click=\"!events.areAllRunnersScratched(runner) && events.toggleSelection(runner.bettingInterestNumber, col)\" ng-checked=\"!events.areAllRunnersScratched(runner) && events.isSelected(runner.bettingInterestNumber, col)\" ng-disabled=events.areAllRunnersScratched(runner)> <span><i class=tvg-icon-check></i></span></label></td><td class=runner__odds qa-label=runner-odds ng-class=\"{'scratched': events.areAllRunnersScratched(runner)}\"><span ng-if=!events.areAllRunnersScratched(runner) ng-class=\"{'runner__odds--favorite' : runner.favorite === true}\" ng-bind=runner.currentOddsString></span> <span ng-if=events.areAllRunnersScratched(runner)>SCRATCHED</span></td><td class=runner__horse qa-label=runner-horse-name><span class=runner__horse-name ng-bind=runner.horseName ng-class=\"{'scratched': runner.scratched }\"></span> <span ng-if=runner.coupledRunners><span ng-repeat=\"coupledRunner in runner.coupledRunners track by $index\">&nbsp;/&nbsp; <span class=runner__horse-name ng-bind=coupledRunner.horseName ng-class=\"{'scratched': coupledRunner.scratched }\"></span></span></span></td></tr></tbody></table></div></td></tr><tr><td class=bet-footer qa-label=betticket-footer><footer><div class=overlay ng-if=data.currentRace.closedForBetting></div><div class=bet-submit><button class=\"bt-button bt-primary pull-right\" ng-disabled=\"!data.betEnabled || data.currentRace.closedForBetting\" qa-label=submit-bet ng-click=\"data.betEnabled && data.betValidation.betCost > 0 && !data.currentRace.closedForBetting && events.submitBet()\" ng-class=\"{'disabled': data.blockAnyBetting || !data.betEnabled || data.betValidation.betCost == 0 || data.currentRace.closedForBetting}\">{{data.betEnabled && data.betValidation.betCost > 0 ? (data.isBetConfirmed ? 'Confirm Bet' : 'Submit Bet Now') : 'Please make your selection'}}</button><div ng-if=\"data.betEnabled && data.betValidation.betCost > 0\" class=bet-submit__total qa-label=bet-total>Bet Total <strong><i class=tvg-icon-dollar></i><span ng-bind=data.betValidation.betCost></span></strong></div></div></footer></td></tr></table>");
}]);

angular.module("js/modules/BetSlipWindow/templates/betslip-view-confirm.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-view-confirm.html",
    "<table class=betslip-betwizard qa-label=betslip-confirm><tr><td class=betslip-betwizard__header qa-label=betticket-header><header><a qa-label=back-button href ng-click=events.goBack(); ng-show=!data.repeatBet class=back-button><i class=tvg-icon-arrow-left></i> Back </a><span ng-show=!data.repeatBet qa-label=confirm-bets-header>Confirm bets</span> <span ng-show=data.repeatBet qa-label=repeat-bets-header>Repeat Bet</span></header><betslip-alert-banner ng-repeat=\"alert in alerts track by $index\" type={{alert.type}} closeable={{alert.closeable}} message={{alert.message}} close=\"!alert.closeForever ? events.closeAlert($index) : events.closeAlertForever($index)\"></betslip-alert-banner><message ng-show=data.showConfirmWarn><div class=\"betslip_feedback betslip_alert\"><mbody qa-label=message-text><i class=tvg-icon-info></i> <span class=betslip_feedback__message>Your bets have not been placed yet</span></mbody></div></message></td></tr><tr><td class=betslip-betwizard__resume qa-label=betslip-confirm-resume><header><div class=track-selector__mtp qa-label=mtp><i class=\"tvg-icon tvg-icon-mtp\" ng-class=\"{'mtp-near' : data.mtp.status == 'near',\n" +
    "                                      'mtp-med' : data.mtp.status == 'med',\n" +
    "                                      'mtp-far' : data.mtp.status == 'far',\n" +
    "                                      'mtp-hide' : data.mtp.status == 'time-format'}\"></i> <span ng-class=\"{'only-time' : data.mtp.status == 'time-format'}\">{{data.mtp.time}}</span></div><span qa-label=track-name class=betslip-betwizard_track-name>{{data.currentRace.trackName}}</span> <span qa-label=race-number class=betslip-betwizard_race-number>R{{data.currentRace.raceNumber}}</span></header><ul><li><strong>Bet type:</strong> <span qa-label=confirm-bet-type>{{data.betValidation.wagerName}}</span></li><li><strong>Bet Amount</strong> <span qa-label=confirm-bet-amount>{{data.betAmount | currency:\"$\"}}</span> <strong ng-if=\"data.repeatBet && (data.repeatTimes > 1)\">{{'x ' + data.repeatTimes}}</strong></li><li><strong>Bet Total:</strong> <span qa-label=confirm-bet-total>{{data.repeatBet ? (data.betValidation.betCost * data.repeatTimes) : data.betValidation.betCost | currency:\"$\"}}</span></li></ul></td></tr><tr><td class=betslip-betwizard__selections><div class=\"overlay message\" ng-if=data.currentRace.closedForBetting><div class=overlay__message>{{data.closedForBettingMessage}}</div></div><div class=selections-holder><div class=selections-section qa-label=selections-section><h2>Selection(s)</h2><ul ng-repeat=\"(index, runnerSaddlesByLeg) in data.selectedSaddle\" qa-label=leg><li class=selection-index ng-if=data.isLeg>L{{index+1}}</li><li class=selection-index ng-if=\"data.selectedBetType.isKey && index === 0\">K</li><li class=selection-index ng-if=\"data.selectedBetType.isKey && index > 0\">W/</li><li class=selection-index ng-if=\"!data.isLeg && !data.selectedBetType.isKey && data.selectedSaddle.length > 1\">P{{index+1}}</li><li ng-if=!isGreyhoundRace ng-repeat=\"runnerSaddle in runnerSaddlesByLeg\" title={{runnerSaddle.horseName}} ng-style=\"{'background-color': runnerSaddle.backgroundColor, 'color': runnerSaddle.numberColor}\" qa-label=selected-horse-id>{{runnerSaddle.horseId}}</li><li ng-if=isGreyhoundRace ng-repeat=\"runnerSaddle in runnerSaddlesByLeg\" title={{runnerSaddle.horseName}} qa-label=selected-horse-id><span class=\"saddle dog-saddle-{{runnerSaddle.bettingInterestNumber}}\" ng-bind=runnerSaddle.horseId></span></li></ul></div></div></td></tr><tr><td ng-if=!data.repeatBet class=betslip-betwizard__footer qa-label=betticket-footer><footer><div class=overlay ng-if=data.currentRace.closedForBetting></div><div class=bet-confirm qa-label=bet-confirm-checkbox><label class=\"checkbox blue\"><input type=checkbox ng-checked=!data.isBetConfirmed ng-click=events.confirmBet()> <span><i class=tvg-icon-check></i></span> Don’t show this confirmation screen next time</label></div><div class=bet-submit qa-label=bet-total><span ng-if=\"data.betEnabled && data.betValidation.betCost > 0\" class=\"bet-submit__total pull-left\">Bet Total <strong><i class=tvg-icon-dollar></i>{{data.betValidation.betCost}}</strong> </span><button class=\"bt-button bt-primary pull-right\" qa-label=submit-bet ng-click=events.submitBet() ng-class=\"{'disabled': data.currentRace.closedForBetting}\" ng-disabled=data.currentRace.closedForBetting>Submit Bet Now</button></div></footer></td><td ng-if=!!data.repeatBet class=betslip-betwizard__footer qa-label=betticket-footer><footer><div class=repeat-bet qa-label=repeat-bet-section><label for=repeat-times>Repeat bet how many times?</label><input id=repeat-times type=number class=input-ui qa-label=repeat-times min=1 max={{data.maxRepeatTimes}} ng-model=data.repeatTimes ng-change=events.validateRepeatValue() ng-class=\"{'invalid': !data.repeatValid}\"> <span ng-if=\"data.betValidation.betCost > 0\" class=\"bet-submit__total pull-right\" qa-label=repeat-bet-total>Bet Total <strong><i class=tvg-icon-dollar></i>{{(data.betValidation.betCost * data.repeatTimes) | number:2}}</strong></span></div><div class=bet-submit><button qa-label=close-betticket name=closeBetSlipBtn class=\"bt-button bt-small bt-tertiary pull-left btn-close\" ng-click=events.closeBetslip();>Close</button> <button class=\"bt-button bt-fluid bt-primary pull-right\" qa-label=submit-bet ng-click=events.submitBet() ng-class=\"{'disabled': ((data.repeatBet === true) && (data.repeatValid === false)) || data.currentRace.closedForBetting || isPlacingBet}\" ng-disabled=\"((data.repeatBet === true) && (data.repeatValid === false)) || data.currentRace.closedForBetting || isPlacingBet\">Submit Bet Now</button></div></footer></td></tr></table>");
}]);

angular.module("js/modules/BetSlipWindow/templates/betslip-view-receipt.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-view-receipt.html",
    "<table class=betslip-betwizard qa-label=bet-ticket-receipt><tr><td class=betslip-betwizard__header qa-label=betticket-header><header>Bet Ticket receipt</header><message ng-switch on=data.showMessage><div class=\"betslip_feedback betslip_success\" ng-switch-when=success><mbody qa-label=message-text><i class=tvg-icon-success></i><div class=betslip_feedback__message>Bet placed successfully. Good Luck!</div></mbody></div><div class=\"betslip_feedback betslip_error\" ng-switch-when=error><mbody qa-label=message-text><i class=tvg-icon-error></i><div class=betslip_feedback__message><strong>An error occurred while trying to place your bet.</strong><p ng-bind-html=data.errorMessage></div></mbody></div></message></td></tr><tr><td class=betslip-betwizard__resume qa-label=receipt-resume><header><div class=track-selector__mtp qa-label=mtp><i class=\"tvg-icon tvg-icon-mtp\" ng-class=\"{'mtp-near' : data.mtp.status == 'near',\n" +
    "                                      'mtp-med' : data.mtp.status == 'med',\n" +
    "                                      'mtp-far' : data.mtp.status == 'far',\n" +
    "                                      'mtp-hide' : data.mtp.status == 'time-format'}\"></i> <span ng-class=\"{'only-time' : data.mtp.status == 'time-format'}\">{{data.mtp.time}}</span></div><span qa-label=race-number class=betslip-confirm_race-number>R{{data.currentRace.raceNumber}}</span> <span qa-label=track-name class=betslip-confirm_track-name>{{data.currentRace.trackName}}</span></header><ul><li><strong>Bet type:</strong> <span qa-label=receipt-resume-bet-type>{{data.betValidation.wagerName}}</span></li><li><strong>Bet Amount</strong> <span qa-label=receipt-resume-bet-amount>{{data.betAmount | currency:\"$\"}}</span> <strong ng-if=\"data.repeatBet && (data.repeatTimes > 1)\">{{'x ' + data.repeatTimes}}</strong></li><li><strong>Bet Total:</strong> <span qa-label=receipt-resume-bet-total>{{data.repeatBet ? (data.betValidation.betCost * data.repeatTimes) : data.betValidation.betCost | currency:\"$\"}}</span></li></ul></td></tr><tr><td class=betslip-betwizard__selections><div class=overlay ng-if=data.currentRace.closedForBetting><div class=overlay__message>{{data.closedForBettingMessage}}</div></div><div class=selections-holder><div class=selections-section qa-label=selections-section><h2>Selection(s)</h2><ul ng-repeat=\"(index, runnerSaddlesByLeg) in data.selectedSaddle\" qa-label=leg><li class=selection-index ng-if=data.isLeg>L{{index+1}}</li><li class=selection-index ng-if=\"data.selectedBetType.isKey && index === 0\">K</li><li class=selection-index ng-if=\"data.selectedBetType.isKey && index > 0\">W/</li><li class=selection-index ng-if=\"!data.isLeg && !data.selectedBetType.isKey && data.selectedSaddle.length > 1\">P{{index+1}}</li><li ng-if=!isGreyhoundRace ng-repeat=\"runnerSaddle in runnerSaddlesByLeg\" title={{runnerSaddle.horseName}} ng-style=\"{'background-color': runnerSaddle.backgroundColor, 'color': runnerSaddle.numberColor}\" qa-label=horse-{{runnerSaddle.horseId}}>{{runnerSaddle.horseId}}</li><li ng-if=isGreyhoundRace ng-repeat=\"runnerSaddle in runnerSaddlesByLeg\" title={{runnerSaddle.horseName}} qa-label=selected-horse-id><span class=\"saddle dog-saddle-{{runnerSaddle.bettingInterestNumber}}\" ng-bind=runnerSaddle.horseId></span></li></ul></div></div></td></tr><tr><td class=betslip-betwizard__footer qa-label=betticket-footer><footer><div class=actions><button qa-label=sameBetBtn name=sameBetBtn class=\"bt-button bt-small bt-primary\" ng-class=\"{disabled:  data.currentRace.closedForBetting || data.showMessage === 'error'}\" ng-disabled=\"data.currentRace.closedForBetting || data.showMessage === 'error'\" ng-click=\"!data.currentRace.closedForBetting && events.createSameBet();\">Same Bet</button> <button qa-label=sameRaceBtn name=sameRaceBtn class=\"bt-button bt-small bt-primary\" ng-class=\"{disabled:  data.currentRace.closedForBetting || data.showMessage === 'error'}\" ng-disabled=\"data.currentRace.closedForBetting || data.showMessage === 'error'\" ng-click=\"!data.currentRace.closedForBetting && events.createSameRace();\">Same Race</button> <button qa-label=repeatBetBtn name=repeatBtn class=\"bt-button bt-small bt-primary\" ng-class=\"{disabled:  data.currentRace.closedForBetting || data.showMessage === 'error'}\" ng-disabled=\"data.currentRace.closedForBetting || data.showMessage === 'error'\" ng-click=\"!data.currentRace.closedForBetting && events.repeatBet();\" ng-if=$root.activeFeatures.betSlipRepeatBet>Repeat Bet</button></div><div><button qa-label=closeBetSlipBtn name=closeBetSlipBtn class=\"bt-button bt-small bt-tertiary btn-close-betslip\" ng-click=events.closeBetslip();>Close</button></div></footer></td></tr></table>");
}]);

angular.module("js/modules/BetSlipWindow/templates/betslip-window-form.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-window-form.html",
    "<form qa-label=betTicketOption name=betticket class=bet-ticket-form ng-if=!data.currentRace.closedForBetting novalidate><div class=\"form-group bet-ticket-form__type\"><label>Bet Type</label><div class=bettype-holder><select-container class=select-container--alt><select class=cb-bettype ng-init=\"\" ng-model=data.selectedBetType ng-options=\"wager.name for wager in data.wagerTypes track by wager.id\" ng-change=events.betTypeChanged(data.selectedBetType) qa-label=betslip-bet-types-select></select><span qa-label=betTicketBetType ng-bind=data.selectedBetType.name></span> <i class=\"bdg bdg-right bdg-small new-tag\" ng-if=events.isNewWagerType(data.selectedBetType.abbreviation)>New</i></select-container></div></div><div class=\"form-group bet-ticket-form__amount\"><label>Bet Amount</label><div class=amount-holder><select-container class=select-container--alt><select ng-init=\"\" ng-model=data.selectedBetAmount ng-options=\"amount.amountString for amount in data.selectedBetAmounts track by amount.amount\" ng-change=events.betAmountChanged() qa-label=betslip-bet-amounts-select></select><span qa-label=betTicketBetAmount ng-bind=data.selectedBetAmount.amountString></span></select-container><div class=other-amount-holder ng-if=data.otherAmountShown><i class=tvg-icon-dollar></i> <input qa-label=betTicketAmount name=otherAmountInput type=number step={{data.otherAmountStep}} ng-model=data.otherAmount placeholder=Amount ng-blur=\"events.otherAmountChanged(data.otherAmount, betticket.otherAmountInput.$valid, true)\" ng-change=\"events.otherAmountChanged(data.otherAmount, betticket.otherAmountInput.$valid, false)\"></div></div></div></form>");
}]);

angular.module("js/modules/BetSlipWindow/templates/betslip-window.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/betslip-window.html",
    "<div class=bet-slip-window ng-show=\"data.currentRace!==null && !sessionInvalid\" ng-switch on=data.showView ng-class=\"{loading: (isLoading || isPlacingBet)}\"><div ng-switch-when=bet><div ng-include=\"'js/modules/BetSlipWindow/templates/betslip-view-bet.html'\"></div></div><div ng-switch-when=receipt><div ng-include=\"'js/modules/BetSlipWindow/templates/betslip-view-receipt.html'\"></div></div><div ng-switch-when=confirmation><div ng-include=\"'js/modules/BetSlipWindow/templates/betslip-view-confirm.html'\"></div></div></div><info-dialog ng-if=\"data.currentRace === null && !isLoading || sessionInvalid\"><div class=container><p>This race is not available</p></div></info-dialog>");
}]);

angular.module("js/modules/BetSlipWindow/templates/round-up-message.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/round-up-message.html",
    "<div name=loginError class=\"modal-header text-centered\">Bet Size Changed</div><table class=error><tr><td><span>{{data.infoMessage}}</span></td></tr></table><div name=errorFooter class=modal-footer><button class=gray ng-click=events.closeInfoMessage()>Ok</button></div>");
}]);

angular.module("js/modules/BetSlipWindow/templates/track-selector-window.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/BetSlipWindow/templates/track-selector-window.html",
    "<div qa-label=trackSelector class=track-selector ng-class=\"{loading: data.loading}\"><track-selector class=track-selector__track track-selector-on-change=events.onTrackChangedForNewTrackSelector(track) track-selector-default-option=data.trackSelected.name track-selector-type=default></track-selector><select-container class=\"select-container--alt track-selector__race\"><select name=raceOfTrack qa-label=raceOfTrack ng-model=data.currentRace ng-options=\"'R'+race.raceNumber for race in data.races | orderBy:'raceNumber'\" ng-change=events.raceChanged() ng-disabled=data.racesLoading></select><span qa-label=raceSelected>R{{data.currentRace.raceNumber}}</span> <span ng-class=\"{'loading' : data.racesLoading}\"></span></select-container></div>");
}]);

angular.module("js/modules/Features/templates/feature-overrides-panel.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/Features/templates/feature-overrides-panel.html",
    "<a class=\"close-modal tvg-icon-times\" ng-click=$close($event)></a><table class=\"table features-override-config\"><thead><tr><th colspan=2>Feature</th></tr></thead><tbody ng-show=\"features.length === 0\"><tr><td colspan=2 class=loading></td></tr></tbody><tbody ng-show=\"features.length > 0\"><tr ng-repeat=\"feature in features | orderBy:'name' track by $index\"><td ng-bind=feature.name></td><td><label class=switch style=position:relative><input type=checkbox ng-model=feature.value ng-change=\"onFeatureStateChange(feature.name, feature.value)\"> <i class=\"switch__control thumb\"></i></label></td></tr></tbody></table>");
}]);

angular.module("js/modules/Races/components/raceMtpLabel/templates/race-mtp-label.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/Races/components/raceMtpLabel/templates/race-mtp-label.html",
    "<span ng-if=\"currentMtpFormat == mtpFormatsEnum.MTP\"><span class=mtp_time qa-label=time-to-play><strong ng-bind=raceMtp.mtp></strong> MTP </span></span><span class=mtp_time qa-label=time-to-play ng-if=\"currentMtpFormat == mtpFormatsEnum.TIME\" ng-bind=raceMtp.date></span> <span class=mtp_time-with-day qa-label=time-to-play ng-if=\"currentMtpFormat == mtpFormatsEnum.TIME_WITH_DAY\"><span class=mtp_time><strong ng-bind=raceMtp.timeWithDay.time></strong> </span><span class=mtp_am_pm ng-bind=raceMtp.timeWithDay.amPmMarker></span> <span class=mtp_day ng-bind=raceMtp.timeWithDay.day></span></span>");
}]);

angular.module("js/modules/Tracks/components/trackSelector/templates/track-selector.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/Tracks/components/trackSelector/templates/track-selector.html",
    "<div class=btn-group uib-dropdown is-open=trackSelectorCtrl.model.dropdown.isOpen qa-label=dropdown-track><button id=single-button type=button class=\"button dropdown-button track-selector-dropdown-button\" ng-click=trackSelectorCtrl.events.sendCloseTrackSelectorGTMEvent(trackSelectorCtrl.model.dropdown.isOpen) uib-dropdown-toggle qa-label=dropdown-track-btn-open><span class=dropdown-arrow ng-class=\"{'tvg-icon-arrow-down' : trackSelectorCtrl.model.dropdown.isOpen === false,\n" +
    "                         'tvg-icon-arrow-up': trackSelectorCtrl.model.dropdown.isOpen === true}\"></span> <span qa-label=dropdown-track-selected class=dropdown-selected-option ng-bind=\"trackSelectorCtrl.trackSelectorDefaultOption || 'Loading...'\"></span></button><div class=\"dropdown-menu dropdown-options-container\" ng-class=\"{loading: trackSelectorCtrl.model.isLoading}\" role=menu aria-labelledby=single-button><div ng-if=!$root.isGreyhoundRace><h4 qa-label=track-selector-favorite-tracks-title>Favorite Tracks</h4><ul qa-label=track-selector-favorite-tracks-list class=list-item-primary ng-show=\"trackSelectorCtrl.model.favoriteTracks.length > 0 && $root.userSession\"><li ng-click=trackSelectorCtrl.events.onChangeSelectedTrack(favTrack) ng-repeat=\"favTrack in trackSelectorCtrl.model.favoriteTracks track by trackSelectorCtrl.trackId(favTrack) | orderBy:'trackName'\"><table class=race-track-selector-item><tr><td qa-label=dropdown-track-option-track-name>{{::favTrack.trackName}}</td><td qa-label=dropdown-track-option-race-number class=race-number-track-selector-column ng-if=!!favTrack.currentWagerableRace><strong>{{:: \"R\" + favTrack.currentWagerableRace}}</strong></td><td qa-label=dropdown-track-option-race-mtp class=race-mtp-track-selector-column ng-switch=favTrack.currentWagerableRace><span class=race-mtp-track-selector ng-switch-when=0>Results</span> <span class=race-mtp-track-selector ng-switch-default ng-bind=favTrack.getTimeToBeDisplayed()></span></td></tr></table></li></ul><ul qa-label=track-selector-favorite-tracks-empty-list-message class=list-item-primary ng-show=\"trackSelectorCtrl.model.favoriteTracks.length === 0 && trackSelectorCtrl.model.isLoading === false && $root.userSession\"><li class=list-item-no-favorites-tracks>You currently have no favorites racing today.<br>Please manage your favorites to add tracks you are interested in.</li></ul><ul qa-label=track-selector-favorite-tracks-empty-list-message-logged-out ng-show=!$root.userSession class=list-item-primary><li><table class=race-track-selector-item><tbody><tr><td>Please <a href=\"\" ng-click=trackSelectorCtrl.events.openModalMenu() class=favourites-logged-out>Log In</a> to view your favorite tracks</td></tr></tbody></table></li></ul><h4 qa-label=track-selector-popular-tracks-title ng-show=\"trackSelectorCtrl.model.featuredTracks.length > 0\">Popular Tracks</h4><ul qa-label=track-selector-popular-tracks-list ng-show=\"trackSelectorCtrl.model.featuredTracks.length > 0\" class=list-item-primary><li ng-click=trackSelectorCtrl.events.onChangeSelectedTrack(featuredTrack) ng-repeat=\"featuredTrack in trackSelectorCtrl.model.featuredTracks track by trackSelectorCtrl.trackId(featuredTrack) | orderBy:'trackName'\"><table class=race-track-selector-item><tr><td qa-label=dropdown-track-option-track-name>{{::featuredTrack.trackName}}</td><td qa-label=dropdown-track-option-race-number class=race-number-track-selector-column ng-if=!!featuredTrack.currentWagerableRace><strong>{{ ::\"R\" + featuredTrack.currentWagerableRace}}</strong></td><td qa-label=dropdown-track-option-race-mtp class=race-mtp-track-selector-column ng-switch=featuredTrack.currentWagerableRace><span class=race-mtp-track-selector ng-switch-when=0>Results</span> <span class=race-mtp-track-selector ng-switch-default ng-bind=featuredTrack.getTimeToBeDisplayed()></span></td></tr></table></li></ul></div><h4 qa-label=track-selector-others-tracks-title ng-if=!$root.isGreyhoundRace>Other Tracks</h4><ul qa-label=track-selector-others-tracks-list ng-show=\"trackSelectorCtrl.model.allTracks.length > 0\" class=list-item-primary><li ng-click=trackSelectorCtrl.events.onChangeSelectedTrack(otherTrack) ng-repeat=\"otherTrack in trackSelectorCtrl.model.allTracks track by trackSelectorCtrl.trackId(otherTrack) | orderBy:'trackName'\"><table class=race-track-selector-item><tr><td qa-label=dropdown-track-option-track-name>{{::otherTrack.trackName}}</td><td qa-label=dropdown-track-option-race-number class=race-number-track-selector-column ng-if=!!otherTrack.currentWagerableRace><strong>{{:: \"R\" + otherTrack.currentWagerableRace}}</strong></td><td qa-label=dropdown-track-option-race-mtp class=race-mtp-track-selector-column ng-switch=otherTrack.currentWagerableRace><span class=race-mtp-track-selector ng-switch-when=0>Results</span> <span class=race-mtp-track-selector ng-switch-default ng-bind=otherTrack.getTimeToBeDisplayed()></span></td></tr></table></li></ul><ul qa-label=track-selector-others-tracks-empty-list ng-show=\"trackSelectorCtrl.model.allTracks.length === 0 && trackSelectorCtrl.model.isLoading === false\" class=list-item-primary><li ng-bind=\"('noRacesAvailable' | CMSValue)\"></li></ul></div></div>");
}]);

angular.module("js/modules/UserProfile/templates/quick-deposit.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/UserProfile/templates/quick-deposit.html",
    "<div class=modal-header>Quick Deposit <button name=quickDepositCloseBtn class=btn-close ng-click=events.close($event)></button></div><br><div ng-if=\"!msgHidden && !depositSuccessData\" class=\"notification {{msgType}}\"><div class=title-container><span class=icon></span><h2 class=title>{{msgText.title}}</h2></div><p class=text ng-bind-html=\"(msgText.text) | trust\"></p><button class=dismiss-btn ng-click=dismissNotification()>OK</button></div><quick-deposit ng-if=!depositSuccessData ng-attr-with-placeholders=true ng-attr-notify-errors=true></quick-deposit><success-deposit ng-if=depositSuccessData ng-attr-deposit-data=depositSuccessData></success-deposit>");
}]);

angular.module("js/modules/Utilities/directives/templates/states.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/Utilities/directives/templates/states.html",
    "<select class=form-control ng-controller=StatesCtrl><option ng-repeat=\"states as state\" value={{state.abbreviation}}>{{state.name}}</option></select>");
}]);

angular.module("js/modules/Utilities/templates/modal-window.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/modules/Utilities/templates/modal-window.html",
    "<div modal-render={{$isRendered}} tabindex=-1 role=dialog class=\"tvgmodal fade in\" ng-style=\"{'z-index': 1050 + index*10, display: 'block'}\"><div class=\"tvgmodal-dismiss no-click-feedback\" ng-click=close($event)></div><div class=tvgmodal-dialog><div class=tvgmodal-content ng-transclude></div></div></div>");
}]);

angular.module("js/views/betslip-window.html", []).run(["$templateCache", function ($templateCache) {
  $templateCache.put("js/views/betslip-window.html",
    "<div ng-class=\"{loading: loadingTrack}\"><div ng-class=\"{loading: data.loading}\" qa-label=bet-slip-window-container><betslip-window qa-label=betslip-window class=betslip></betslip-window></div></div>");
}]);

define("tvgTemplates", function(){});

modules/Main/providers/crossWindowMessagingFac.js
'use strict';

define('CrossWindowMessagingFac',[],
    function () {

        /**
         * @ngdoc factory
         * @name TVG.BetslipMain.CrossWindowMessaging
         *
         * @description
         * Service where we register event listeners for the $rootScope.
         */
        function crossWindowMessaging($rootScope, $window, $log) {
            /**
             * @private
             * @description
             * Every time an account balance update is performed in a betslip window we need to notify the "main" window
             * in order to guarantee that other modules get their matching info updated automatically, if needed.
             */
            function _onAccountBalanceUpdate() {
                $rootScope.$on('accountBalance_update', function () {
                    if (!$window.opener || !$window.opener.hasOwnProperty('__rootScope')) {
                        $log.warn('Unable to notify other windows about the account balance update.');
                        return;
                    }
                    // Notify the other windows that the account balance was updated.
                    $window.opener.__rootScope.$emit('accountBalance_update');
                });
            }

            /**
             * @private
             * @description
             * Every time a bet is placed in the betslip window we need to notify the "main" window
             * in order to guarantee that other modules get their matching info updated automatically, if needed.
             */
            function _onBetPlaced() {
                $rootScope.$on('bet_placed', function (event, race) {
                    /*jslint unparam:true*/
                    if (!$window.opener || !$window.opener.hasOwnProperty('__rootScope')) {
                        $log.warn('Unable to notify other windows about the new bet placed.');
                        return;
                    }
                    // Notify the other windows that the account balance was updated.
                    $window.opener.__rootScope.$emit('bet_placed', race);
                });
            }

            return {
                onAccountBalanceUpdate: _onAccountBalanceUpdate,
                onBetPlaced: _onBetPlaced
            };
        }

        crossWindowMessaging.$inject = [
            '$rootScope',
            '$window',
            '$log'
        ];

        return crossWindowMessaging;
    });

modules/Main/betslipMainMod.js
'use strict';

define('BetslipMainMod',['CrossWindowMessagingFac'],
    function (CrossWindowMessagingFac) {

        angular.module('TVG.BetslipMain', [])
            .factory('CrossWindowMessaging', CrossWindowMessagingFac);
    });

modules/FavoriteTracks/providers/favoriteTracksFac.js
'use strict';

define('FavoriteTracksFac',['PreferencesEntityBuilder'], function (PreferencesEntityBuilder) {

    function FavoriteTracksFac(PreferencesFac, $q, FavoriteCookieFac) {

        var FAVORITE_TRACKS_KEY = 'FAVORITE_TRACKS';
        var favoriteTracks = [];
        var loaded = false;

        function _retrieveFavoriteTracksList(preference) {
            var trackList = preference.metadata.split(',');
            favoriteTracks = trackList;
            loaded = true;
        }

        var favoriteTracksFac =  {
            clearFavoriteList: function () {
                loaded = false;
                favoriteTracks.length = 0;
            },
            loadFavoriteTracks: function() {
                if (loaded) {
                    return $q.when();
                }
                return PreferencesFac
                    .getUniquePreference(FAVORITE_TRACKS_KEY)
                    .then(_retrieveFavoriteTracksList);
            },
            getFavoriteTracks: function() {
                return favoriteTracks;
            },
            updateFavoriteTracks: function(favoriteTrackList) {
                var metadata = favoriteTrackList.join(',');
                var postData = PreferencesEntityBuilder()
                    .withMetadata(metadata)
                    .withDescription(FAVORITE_TRACKS_KEY)
                    .build();
                return PreferencesFac.updatePreferences(postData).then(function(){
                    favoriteTracks = favoriteTrackList;

                    //TODO Remove this once all preferences update are on the micro service
                    FavoriteCookieFac.updateFavoriteTrackList(favoriteTrackList);
                });
            }
        };

        return {
            loadFavoriteTracks: favoriteTracksFac.loadFavoriteTracks,
            getFavoriteTracks: favoriteTracksFac.getFavoriteTracks,
            updateFavoriteTracks: favoriteTracksFac.updateFavoriteTracks,
            clearFavoriteList: favoriteTracksFac.clearFavoriteList
        };
    }

    FavoriteTracksFac.$inject = [
        'PreferencesFac',
        '$q',
        'FavoriteCookieFac'
    ];

    return FavoriteTracksFac;

});

modules/FavoriteTracks/favoriteTracksMod.js
'use strict';

define(
    'FavoriteTracks',[
        'FavoriteTracksFac'
    ],

    function (FavoriteTracksFac) {

        angular.module('TVG.FavoriteTracks', [])
            .factory('FavoriteTracksFac', FavoriteTracksFac);
    }
);

modules/Preferences/providers/preferencesFac.js
'use strict';

define('PreferencesFac',[
    'PreferencesEntityBuilder',
    'lodash'
], function (PreferencesEntityBuilder, _) {
    function PreferencesFac($http, $q, $rootScope, ConfigurationFac) {
        var baseUrl = ConfigurationFac.getServiceApiUrl('uam');
        var preferencesStore;
        var userId;

        function _readUserId() {
            userId = $rootScope.user ? $rootScope.user.accountNumber : false;
        }

        function isPreferenceObject (pref) {
            return _.isObject(pref) && pref.hasOwnProperty('metadata') && pref.hasOwnProperty('description');
        }

        function _buildPreferenceList(preferences){
            var userPreferences = [];
            if (_.isArray(preferences)) {
                userPreferences = preferences.map(function(preference) {
                    return PreferencesEntityBuilder()
                        .withMetadata(preference.metadata)
                        .withDescription(preference.description)
                        .build();
                });
            }

            if (isPreferenceObject(preferences)) {
                userPreferences.push(preferences);
            }

            return userPreferences;
        }

        var preferencesFac =  {
            // returns preferences in legacy format
            getUserPreferences: function(forceFetch) {
                var deferred = $q.defer();

                if(preferencesStore && !forceFetch) {
                    deferred.resolve(preferencesStore);
                } else {
                    preferencesStore = [];
                    this.getPreferences().then(function(preferenceData) {
                        _.map(preferenceData, function(pref) {
                            var value = pref.metadata;
                            switch(pref.description) {
                                case 'balance_is_shown':
                                case 'show_bet_confirm':
                                case 'bet_type': {
                                    value = parseInt(pref.metadata);
                                    break;
                                }
                                case 'bet_prefs': {
                                    if($rootScope.activeFeatures.usePrefReact) {
                                        value = JSON.parse(pref.metadata);
                                    } else {
                                        value = {
                                            defaultBetType: "10",
                                            default_bet_amount:{
                                                10: "0.00",
                                                20: "0.00",
                                                30: "0.00",
                                                110: "0.00",
                                                160: "0.00",
                                                210: "0.00",
                                                260: "0.00",
                                                "P": "0.00"
                                            },
                                            useCustomBetAmount: false,
                                            useMinimumBetAmount: true
                                        };
                                    }
                                    break;
                                }
                            }
                            preferencesStore[pref.description] = value;
                        });

                        $rootScope.$broadcast('preferencesReady', preferencesStore);

                        deferred.resolve(preferencesStore);
                    }, function(response) {
                        deferred.reject(response.error);
                    });
                }

                return deferred.promise;
            },
            getPreferences: function() {
                var deferred = $q.defer();

                _readUserId();
                if(!userId) {
                    deferred.reject('Could not obtain user id');
                } else {
                    var url = baseUrl + '/users/' + userId + '/preferences';

                    $http.get(url).success(function (response) {
                        deferred.resolve(_buildPreferenceList((response.preferences)));
                    }).error(function (response) {
                        deferred.reject(response.error);
                    });
                }

                return deferred.promise;
            },
            getUniquePreference: function(preferenceName) {
                var deferred = $q.defer();
                var url = baseUrl;

                if(preferenceName === 'FAVORITE_TRACKS') {
                    url += '/preferences?preferenceName=' + preferenceName;
                } else {
                    _readUserId();
                    if(!userId) {
                        deferred.reject('Could not obtain user id');
                        return deferred.promise;
                    }

                    url += baseUrl + '/users/' + userId + '/preferences/' + preferenceName;
                }

                $http.get(url).success(function (response) {
                    if (_.isArray(response.preferences) && response.preferences.length)
                    {
                       var preference = PreferencesEntityBuilder()
                           .withMetadata(response.preferences[0].metadata)
                           .withDescription(response.preferences[0].description)
                           .build();

                        deferred.resolve(preference);
                    } else {
                        deferred.reject('Invalid Data');
                    }
                }).error(function () {
                    var defaultPrefs = {
                        description: 'FAVORITE_TRACKS',
                        metadata: ''
                    };
                    deferred.resolve(defaultPrefs);
                });

                return deferred.promise;
            },
            updatePreferences: function(preferences) {
                var deferred = $q.defer();

                _readUserId();
                if(!userId) {
                    deferred.reject('Could not obtain user id');
                } else {
                    var prefList = _buildPreferenceList(preferences);
                    var url = baseUrl + '/users/' + userId + '/preferences';

                    $http.put(url, {
                        preferences: prefList
                    }).success(function (response) {
                        deferred.resolve(response);
                    }).error(function (response) {
                        deferred.reject(response.error);
                    });
                }

                return deferred.promise;
            }
        };

        return {
            getPreferences: preferencesFac.getPreferences,
            getUniquePreference: preferencesFac.getUniquePreference,
            updatePreferences: preferencesFac.updatePreferences,
            getUserPreferences: preferencesFac.getUserPreferences
        };
    }

    PreferencesFac.$inject = [
        '$http',
        '$q',
        '$rootScope',
        'ConfigurationFac'
    ];

    return PreferencesFac;

});

modules/Preferences/preferencesMod.js
'use strict';

define(
    'Preferences',[
        'PreferencesFac'
    ],

    function (PreferencesFac) {

        angular.module('TVG.Preferences', [])
            .factory('PreferencesFac', PreferencesFac);
    }
);

../node_modules/@tvg/graph/dist/tvg-graph.mod.umd.js
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("moment"), require("angular"));
	else if(typeof define === 'function' && define.amd)
		define('Graph',["moment", "angular"], factory);
	else {
		var a = typeof exports === 'object' ? factory(require("moment"), require("angular")) : factory(root["moment"], root["angular"]);
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})(this, function(__WEBPACK_EXTERNAL_MODULE_21__, __WEBPACK_EXTERNAL_MODULE_131__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// identity function for calling harmony imports with the correct context
/******/ 	__webpack_require__.i = function(value) { return value; };
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 133);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.GraphQLSubscribeInterface = exports.GraphQLClient = undefined;

var _graphqlClient = __webpack_require__(54);

var _graphqlClient2 = _interopRequireDefault(_graphqlClient);

var _graphqlSubscribeInterface = __webpack_require__(55);

var _graphqlSubscribeInterface2 = _interopRequireDefault(_graphqlSubscribeInterface);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.GraphQLClient = _graphqlClient2.default;
exports.GraphQLSubscribeInterface = _graphqlSubscribeInterface2.default;

/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {

var parse = __webpack_require__(101).parse;

// Strip insignificant whitespace
// Note that this could do a lot more, such as reorder fields etc.
function normalize(string) {
  return string.replace(/[\s,]+/g, ' ').trim();
}

// A map docString -> graphql document
var docCache = {};

// A map fragmentName -> [normalized source]
var fragmentSourceMap = {};

function cacheKeyFromLoc(loc) {
  return normalize(loc.source.body.substring(loc.start, loc.end));
}

// For testing.
function resetCaches() {
  docCache = {};
  fragmentSourceMap = {};
}

// Take a unstripped parsed document (query/mutation or even fragment), and
// check all fragment definitions, checking for name->source uniqueness.
// We also want to make sure only unique fragments exist in the document.
var printFragmentWarnings = true;
function processFragments(ast) {
  var astFragmentMap = {};
  var definitions = [];

  for (var i = 0; i < ast.definitions.length; i++) {
    var fragmentDefinition = ast.definitions[i];

    if (fragmentDefinition.kind === 'FragmentDefinition') {
      var fragmentName = fragmentDefinition.name.value;
      var sourceKey = cacheKeyFromLoc(fragmentDefinition.loc);

      // We know something about this fragment
      if (fragmentSourceMap.hasOwnProperty(fragmentName) && !fragmentSourceMap[fragmentName][sourceKey]) {

        // this is a problem because the app developer is trying to register another fragment with
        // the same name as one previously registered. So, we tell them about it.
        if (printFragmentWarnings) {
          console.warn("Warning: fragment with name " + fragmentName + " already exists.\n"
            + "graphql-tag enforces all fragment names across your application to be unique; read more about\n"
            + "this in the docs: http://dev.apollodata.com/core/fragments.html#unique-names");
        }

        fragmentSourceMap[fragmentName][sourceKey] = true;

      } else if (!fragmentSourceMap.hasOwnProperty(fragmentName)) {
        fragmentSourceMap[fragmentName] = {};
        fragmentSourceMap[fragmentName][sourceKey] = true;
      }

      if (!astFragmentMap[sourceKey]) {
        astFragmentMap[sourceKey] = true;
        definitions.push(fragmentDefinition);
      }
    } else {
      definitions.push(fragmentDefinition);
    }
  }

  ast.definitions = definitions;
  return ast;
}

function disableFragmentWarnings() {
  printFragmentWarnings = false;
}

function stripLoc(doc, removeLocAtThisLevel) {
  var docType = Object.prototype.toString.call(doc);

  if (docType === '[object Array]') {
    return doc.map(function (d) {
      return stripLoc(d, removeLocAtThisLevel);
    });
  }

  if (docType !== '[object Object]') {
    throw new Error('Unexpected input.');
  }

  // We don't want to remove the root loc field so we can use it
  // for fragment substitution (see below)
  if (removeLocAtThisLevel && doc.loc) {
    delete doc.loc;
  }

  if (doc.loc) {
    delete doc.loc.startToken;
    delete doc.loc.endToken;
  }

  var keys = Object.keys(doc);
  var key;
  var value;
  var valueType;

  for (key in keys) {
    if (keys.hasOwnProperty(key)) {
      value = doc[keys[key]];
      valueType = Object.prototype.toString.call(value);

      if (valueType === '[object Object]' || valueType === '[object Array]') {
        doc[keys[key]] = stripLoc(value, true);
      }
    }
  }

  return doc;
}

function parseDocument(doc) {
  var cacheKey = normalize(doc);

  if (docCache[cacheKey]) {
    return docCache[cacheKey];
  }

  var parsed = parse(doc);
  if (!parsed || parsed.kind !== 'Document') {
    throw new Error('Not a valid GraphQL document.');
  }

  // check that all "new" fragments inside the documents are consistent with
  // existing fragments of the same name
  parsed = processFragments(parsed);
  parsed = stripLoc(parsed, false);
  docCache[cacheKey] = parsed;

  return parsed;
}

// XXX This should eventually disallow arbitrary string interpolation, like Relay does
function gql(/* arguments */) {
  var args = Array.prototype.slice.call(arguments);

  var literals = args[0];

  // We always get literals[0] and then matching post literals for each arg given
  var result = literals[0];

  for (var i = 1; i < args.length; i++) {
    if (args[i] && args[i].kind && args[i].kind === 'Document') {
      result += args[i].loc.source.body;
    } else {
      result += args[i];
    }

    result += literals[i];
  }

  return parseDocument(result);
}

// Support typescript, which isn't as nice as Babel about default exports
gql.default = gql;
gql.resetCaches = resetCaches;
gql.disableFragmentWarnings = disableFragmentWarnings;

module.exports = gql;


/***/ }),
/* 2 */
/***/ (function(module, exports) {

/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]';

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/**
 * A faster alternative to `Function#apply`, this function invokes `func`
 * with the `this` binding of `thisArg` and the arguments of `args`.
 *
 * @private
 * @param {Function} func The function to invoke.
 * @param {*} thisArg The `this` binding of `func`.
 * @param {Array} args The arguments to invoke `func` with.
 * @returns {*} Returns the result of `func`.
 */
function apply(func, thisArg, args) {
  switch (args.length) {
    case 0: return func.call(thisArg);
    case 1: return func.call(thisArg, args[0]);
    case 2: return func.call(thisArg, args[0], args[1]);
    case 3: return func.call(thisArg, args[0], args[1], args[2]);
  }
  return func.apply(thisArg, args);
}

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Built-in value references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeKeys = overArg(Object.keys, Object),
    nativeMax = Math.max;

/** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */
var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf');

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  // Safari 9 makes `arguments.length` enumerable in strict mode.
  var result = (isArray(value) || isArguments(value))
    ? baseTimes(value.length, String)
    : [];

  var length = result.length,
      skipIndexes = !!length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * Assigns `value` to `key` of `object` if the existing value is not equivalent
 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * for equality comparisons.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function assignValue(object, key, value) {
  var objValue = object[key];
  if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
      (value === undefined && !(key in object))) {
    object[key] = value;
  }
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @returns {Function} Returns the new function.
 */
function baseRest(func, start) {
  start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
  return function() {
    var args = arguments,
        index = -1,
        length = nativeMax(args.length - start, 0),
        array = Array(length);

    while (++index < length) {
      array[index] = args[start + index];
    }
    index = -1;
    var otherArgs = Array(start + 1);
    while (++index < start) {
      otherArgs[index] = args[index];
    }
    otherArgs[start] = array;
    return apply(func, this, otherArgs);
  };
}

/**
 * Copies properties of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy properties from.
 * @param {Array} props The property identifiers to copy.
 * @param {Object} [object={}] The object to copy properties to.
 * @param {Function} [customizer] The function to customize copied values.
 * @returns {Object} Returns `object`.
 */
function copyObject(source, props, object, customizer) {
  object || (object = {});

  var index = -1,
      length = props.length;

  while (++index < length) {
    var key = props[index];

    var newValue = customizer
      ? customizer(object[key], source[key], key, object, source)
      : undefined;

    assignValue(object, key, newValue === undefined ? source[key] : newValue);
  }
  return object;
}

/**
 * Creates a function like `_.assign`.
 *
 * @private
 * @param {Function} assigner The function to assign values.
 * @returns {Function} Returns the new assigner function.
 */
function createAssigner(assigner) {
  return baseRest(function(object, sources) {
    var index = -1,
        length = sources.length,
        customizer = length > 1 ? sources[length - 1] : undefined,
        guard = length > 2 ? sources[2] : undefined;

    customizer = (assigner.length > 3 && typeof customizer == 'function')
      ? (length--, customizer)
      : undefined;

    if (guard && isIterateeCall(sources[0], sources[1], guard)) {
      customizer = length < 3 ? undefined : customizer;
      length = 1;
    }
    object = Object(object);
    while (++index < length) {
      var source = sources[index];
      if (source) {
        assigner(object, source, index, customizer);
      }
    }
    return object;
  });
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if the given arguments are from an iteratee call.
 *
 * @private
 * @param {*} value The potential iteratee value argument.
 * @param {*} index The potential iteratee index or key argument.
 * @param {*} object The potential iteratee object argument.
 * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
 *  else `false`.
 */
function isIterateeCall(value, index, object) {
  if (!isObject(object)) {
    return false;
  }
  var type = typeof index;
  if (type == 'number'
        ? (isArrayLike(object) && isIndex(index, object.length))
        : (type == 'string' && index in object)
      ) {
    return eq(object[index], value);
  }
  return false;
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Assigns own enumerable string keyed properties of source objects to the
 * destination object. Source objects are applied from left to right.
 * Subsequent sources overwrite property assignments of previous sources.
 *
 * **Note:** This method mutates `object` and is loosely based on
 * [`Object.assign`](https://mdn.io/Object/assign).
 *
 * @static
 * @memberOf _
 * @since 0.10.0
 * @category Object
 * @param {Object} object The destination object.
 * @param {...Object} [sources] The source objects.
 * @returns {Object} Returns `object`.
 * @see _.assignIn
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 * }
 *
 * function Bar() {
 *   this.c = 3;
 * }
 *
 * Foo.prototype.b = 2;
 * Bar.prototype.d = 4;
 *
 * _.assign({ 'a': 0 }, new Foo, new Bar);
 * // => { 'a': 1, 'c': 3 }
 */
var assign = createAssigner(function(object, source) {
  if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) {
    copyObject(source, keys(source), object);
    return;
  }
  for (var key in source) {
    if (hasOwnProperty.call(source, key)) {
      assignValue(object, key, source[key]);
    }
  }
});

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

module.exports = assign;


/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var isObject = __webpack_require__(32);
function isStringValue(value) {
    return value.kind === 'StringValue';
}
function isBooleanValue(value) {
    return value.kind === 'BooleanValue';
}
function isIntValue(value) {
    return value.kind === 'IntValue';
}
function isFloatValue(value) {
    return value.kind === 'FloatValue';
}
function isVariable(value) {
    return value.kind === 'Variable';
}
function isObjectValue(value) {
    return value.kind === 'ObjectValue';
}
function isListValue(value) {
    return value.kind === 'ListValue';
}
function isEnumValue(value) {
    return value.kind === 'EnumValue';
}
function valueToObjectRepresentation(argObj, name, value, variables) {
    if (isIntValue(value) || isFloatValue(value)) {
        argObj[name.value] = Number(value.value);
    }
    else if (isBooleanValue(value) || isStringValue(value)) {
        argObj[name.value] = value.value;
    }
    else if (isObjectValue(value)) {
        var nestedArgObj_1 = {};
        value.fields.map(function (obj) { return valueToObjectRepresentation(nestedArgObj_1, obj.name, obj.value, variables); });
        argObj[name.value] = nestedArgObj_1;
    }
    else if (isVariable(value)) {
        if (!variables || !(value.name.value in variables)) {
            throw new Error("The inline argument \"" + value.name.value + "\" is expected as a variable but was not provided.");
        }
        var variableValue = variables[value.name.value];
        argObj[name.value] = variableValue;
    }
    else if (isListValue(value)) {
        argObj[name.value] = value.values.map(function (listValue) {
            var nestedArgArrayObj = {};
            valueToObjectRepresentation(nestedArgArrayObj, name, listValue, variables);
            return nestedArgArrayObj[name.value];
        });
    }
    else if (isEnumValue(value)) {
        argObj[name.value] = value.value;
    }
    else {
        throw new Error("The inline argument \"" + name.value + "\" of kind \"" + value.kind + "\" is not supported.\n                    Use variables instead of inline arguments to overcome this limitation.");
    }
}
function storeKeyNameFromField(field, variables) {
    if (field.arguments && field.arguments.length) {
        var argObj_1 = {};
        field.arguments.forEach(function (_a) {
            var name = _a.name, value = _a.value;
            return valueToObjectRepresentation(argObj_1, name, value, variables);
        });
        return storeKeyNameFromFieldNameAndArgs(field.name.value, argObj_1);
    }
    return field.name.value;
}
exports.storeKeyNameFromField = storeKeyNameFromField;
function storeKeyNameFromFieldNameAndArgs(fieldName, args) {
    if (args) {
        var stringifiedArgs = JSON.stringify(args);
        return fieldName + "(" + stringifiedArgs + ")";
    }
    return fieldName;
}
exports.storeKeyNameFromFieldNameAndArgs = storeKeyNameFromFieldNameAndArgs;
function resultKeyNameFromField(field) {
    return field.alias ?
        field.alias.value :
        field.name.value;
}
exports.resultKeyNameFromField = resultKeyNameFromField;
function isField(selection) {
    return selection.kind === 'Field';
}
exports.isField = isField;
function isInlineFragment(selection) {
    return selection.kind === 'InlineFragment';
}
exports.isInlineFragment = isInlineFragment;
function graphQLResultHasError(result) {
    return result.errors && result.errors.length;
}
exports.graphQLResultHasError = graphQLResultHasError;
function isIdValue(idObject) {
    return (isObject(idObject) && idObject.type === 'id');
}
exports.isIdValue = isIdValue;
function toIdValue(id, generated) {
    if (generated === void 0) { generated = false; }
    return {
        type: 'id',
        id: id,
        generated: generated,
    };
}
exports.toIdValue = toIdValue;
function isJsonValue(jsonObject) {
    return (isObject(jsonObject) && jsonObject.type === 'json');
}
exports.isJsonValue = isJsonValue;
//# sourceMappingURL=storeUtils.js.map

/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var assign = __webpack_require__(2);
var countBy = __webpack_require__(111);
var identity = __webpack_require__(114);
var uniq = __webpack_require__(117);
function getMutationDefinition(doc) {
    checkDocument(doc);
    var mutationDef = null;
    doc.definitions.forEach(function (definition) {
        if (definition.kind === 'OperationDefinition'
            && definition.operation === 'mutation') {
            mutationDef = definition;
        }
    });
    if (!mutationDef) {
        throw new Error('Must contain a mutation definition.');
    }
    return mutationDef;
}
exports.getMutationDefinition = getMutationDefinition;
function checkDocument(doc) {
    if (doc.kind !== 'Document') {
        throw new Error("Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a \"gql\" tag? http://docs.apollostack.com/apollo-client/core.html#gql");
    }
    var definitionTypes = doc.definitions.map(function (definition) {
        if (definition.kind !== 'OperationDefinition' && definition.kind !== 'FragmentDefinition') {
            throw new Error("Schema type definitions not allowed in queries. Found: \"" + definition.kind + "\"");
        }
        return definition.kind;
    });
    var typeCounts = countBy(definitionTypes, identity);
    if (typeCounts['OperationDefinition'] > 1) {
        throw new Error('Queries must have exactly one operation definition.');
    }
}
exports.checkDocument = checkDocument;
function getOperationName(doc) {
    var res = '';
    doc.definitions.forEach(function (definition) {
        if (definition.kind === 'OperationDefinition'
            && definition.name) {
            res = definition.name.value;
        }
    });
    return res;
}
exports.getOperationName = getOperationName;
function getFragmentDefinitions(doc) {
    var fragmentDefinitions = doc.definitions.filter(function (definition) {
        if (definition.kind === 'FragmentDefinition') {
            return true;
        }
        else {
            return false;
        }
    });
    return fragmentDefinitions;
}
exports.getFragmentDefinitions = getFragmentDefinitions;
function getQueryDefinition(doc) {
    checkDocument(doc);
    var queryDef = null;
    doc.definitions.map(function (definition) {
        if (definition.kind === 'OperationDefinition'
            && definition.operation === 'query') {
            queryDef = definition;
        }
    });
    if (!queryDef) {
        throw new Error('Must contain a query definition.');
    }
    return queryDef;
}
exports.getQueryDefinition = getQueryDefinition;
function getOperationDefinition(doc) {
    checkDocument(doc);
    var opDef = null;
    doc.definitions.map(function (definition) {
        if (definition.kind === 'OperationDefinition') {
            opDef = definition;
        }
    });
    if (!opDef) {
        throw new Error('Must contain a query definition.');
    }
    return opDef;
}
exports.getOperationDefinition = getOperationDefinition;
function getFragmentDefinition(doc) {
    if (doc.kind !== 'Document') {
        throw new Error("Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a \"gql\" tag? http://docs.apollostack.com/apollo-client/core.html#gql");
    }
    if (doc.definitions.length > 1) {
        throw new Error('Fragment must have exactly one definition.');
    }
    var fragmentDef = doc.definitions[0];
    if (fragmentDef.kind !== 'FragmentDefinition') {
        throw new Error('Must be a fragment definition.');
    }
    return fragmentDef;
}
exports.getFragmentDefinition = getFragmentDefinition;
function createFragmentMap(fragments) {
    if (fragments === void 0) { fragments = []; }
    var symTable = {};
    fragments.forEach(function (fragment) {
        symTable[fragment.name.value] = fragment;
    });
    return symTable;
}
exports.createFragmentMap = createFragmentMap;
function addFragmentsToDocument(queryDoc, fragments) {
    if (!fragments) {
        return queryDoc;
    }
    checkDocument(queryDoc);
    return assign({}, queryDoc, {
        definitions: uniq(queryDoc.definitions.concat(fragments)),
    });
}
exports.addFragmentsToDocument = addFragmentsToDocument;
//# sourceMappingURL=getFromAST.js.map

/***/ }),
/* 5 */
/***/ (function(module, exports) {

var g;

// This works in non-strict mode
g = (function() {
	return this;
})();

try {
	// This works if eval is allowed (see CSP)
	g = g || Function("return this")() || (1,eval)("this");
} catch(e) {
	// This works if the window reference is available
	if(typeof window === "object")
		g = window;
}

// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}

module.exports = g;


/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var isNull = __webpack_require__(115);
var isUndefined = __webpack_require__(34);
var isObject = __webpack_require__(32);
var assign = __webpack_require__(2);
var getFromAST_1 = __webpack_require__(4);
var storeUtils_1 = __webpack_require__(3);
var storeUtils_2 = __webpack_require__(3);
var directives_1 = __webpack_require__(47);
function writeQueryToStore(_a) {
    var result = _a.result, query = _a.query, _b = _a.store, store = _b === void 0 ? {} : _b, variables = _a.variables, _c = _a.dataIdFromObject, dataIdFromObject = _c === void 0 ? null : _c, _d = _a.fragmentMap, fragmentMap = _d === void 0 ? {} : _d;
    var queryDefinition = getFromAST_1.getQueryDefinition(query);
    return writeSelectionSetToStore({
        dataId: 'ROOT_QUERY',
        result: result,
        selectionSet: queryDefinition.selectionSet,
        context: {
            store: store,
            variables: variables,
            dataIdFromObject: dataIdFromObject,
            fragmentMap: fragmentMap,
        },
    });
}
exports.writeQueryToStore = writeQueryToStore;
function writeResultToStore(_a) {
    var result = _a.result, dataId = _a.dataId, document = _a.document, _b = _a.store, store = _b === void 0 ? {} : _b, variables = _a.variables, _c = _a.dataIdFromObject, dataIdFromObject = _c === void 0 ? null : _c;
    var selectionSet = getFromAST_1.getOperationDefinition(document).selectionSet;
    var fragmentMap = getFromAST_1.createFragmentMap(getFromAST_1.getFragmentDefinitions(document));
    return writeSelectionSetToStore({
        result: result,
        dataId: dataId,
        selectionSet: selectionSet,
        context: {
            store: store,
            variables: variables,
            dataIdFromObject: dataIdFromObject,
            fragmentMap: fragmentMap,
        },
    });
}
exports.writeResultToStore = writeResultToStore;
function writeSelectionSetToStore(_a) {
    var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context;
    var variables = context.variables, store = context.store, dataIdFromObject = context.dataIdFromObject, fragmentMap = context.fragmentMap;
    selectionSet.selections.forEach(function (selection) {
        var included = directives_1.shouldInclude(selection, variables);
        if (storeUtils_1.isField(selection)) {
            var resultFieldKey = storeUtils_1.resultKeyNameFromField(selection);
            var value = result[resultFieldKey];
            if (!isUndefined(value)) {
                writeFieldToStore({
                    dataId: dataId,
                    value: value,
                    field: selection,
                    context: context,
                });
            }
        }
        else if (storeUtils_1.isInlineFragment(selection)) {
            if (included) {
                writeSelectionSetToStore({
                    result: result,
                    selectionSet: selection.selectionSet,
                    dataId: dataId,
                    context: context,
                });
            }
        }
        else {
            var fragment = void 0;
            if (storeUtils_1.isInlineFragment(selection)) {
                fragment = selection;
            }
            else {
                fragment = fragmentMap[selection.name.value];
                if (!fragment) {
                    throw new Error("No fragment named " + selection.name.value + ".");
                }
            }
            if (included) {
                writeSelectionSetToStore({
                    result: result,
                    selectionSet: fragment.selectionSet,
                    dataId: dataId,
                    context: context,
                });
            }
        }
    });
    return store;
}
exports.writeSelectionSetToStore = writeSelectionSetToStore;
function isGeneratedId(id) {
    return (id[0] === '$');
}
function mergeWithGenerated(generatedKey, realKey, cache) {
    var generated = cache[generatedKey];
    var real = cache[realKey];
    Object.keys(generated).forEach(function (key) {
        var value = generated[key];
        var realValue = real[key];
        if (storeUtils_2.isIdValue(value)
            && isGeneratedId(value.id)
            && storeUtils_2.isIdValue(realValue)) {
            mergeWithGenerated(value.id, realValue.id, cache);
        }
        delete cache[generatedKey];
        cache[realKey] = assign({}, generated, real);
    });
}
function writeFieldToStore(_a) {
    var field = _a.field, value = _a.value, dataId = _a.dataId, context = _a.context;
    var variables = context.variables, dataIdFromObject = context.dataIdFromObject, store = context.store, fragmentMap = context.fragmentMap;
    var storeValue;
    var storeFieldName = storeUtils_1.storeKeyNameFromField(field, variables);
    var shouldMerge = false;
    var generatedKey;
    if ((!field.selectionSet || isNull(value)) && !isObject(value)) {
        storeValue = value;
    }
    else if ((!field.selectionSet || isNull(value)) && isObject(value)) {
        storeValue = {
            type: 'json',
            json: value,
        };
    }
    else if (Array.isArray(value)) {
        var generatedId = dataId + "." + storeFieldName;
        storeValue = processArrayValue(value, generatedId, field.selectionSet, context);
    }
    else {
        var valueDataId = dataId + "." + storeFieldName;
        var generated = true;
        if (!isGeneratedId(valueDataId)) {
            valueDataId = '$' + valueDataId;
        }
        if (dataIdFromObject) {
            var semanticId = dataIdFromObject(value);
            if (semanticId && isGeneratedId(semanticId)) {
                throw new Error('IDs returned by dataIdFromObject cannot begin with the "$" character.');
            }
            if (semanticId) {
                valueDataId = semanticId;
                generated = false;
            }
        }
        writeSelectionSetToStore({
            dataId: valueDataId,
            result: value,
            selectionSet: field.selectionSet,
            context: context,
        });
        storeValue = {
            type: 'id',
            id: valueDataId,
            generated: generated,
        };
        if (store[dataId] && store[dataId][storeFieldName] !== storeValue) {
            var escapedId = store[dataId][storeFieldName];
            if (storeUtils_2.isIdValue(storeValue) && storeValue.generated
                && storeUtils_2.isIdValue(escapedId) && !escapedId.generated) {
                throw new Error("Store error: the application attempted to write an object with no provided id" +
                    (" but the store already contains an id of " + escapedId.id + " for this object."));
            }
            if (storeUtils_2.isIdValue(escapedId) && escapedId.generated) {
                generatedKey = escapedId.id;
                shouldMerge = true;
            }
        }
    }
    var newStoreObj = assign({}, store[dataId], (_b = {},
        _b[storeFieldName] = storeValue,
        _b
    ));
    if (shouldMerge) {
        mergeWithGenerated(generatedKey, storeValue.id, store);
    }
    if (!store[dataId] || storeValue !== store[dataId][storeFieldName]) {
        store[dataId] = newStoreObj;
    }
    var _b;
}
function processArrayValue(value, generatedId, selectionSet, context) {
    return value.map(function (item, index) {
        if (isNull(item)) {
            return null;
        }
        var itemDataId = generatedId + "." + index;
        if (Array.isArray(item)) {
            return processArrayValue(item, itemDataId, selectionSet, context);
        }
        var generated = true;
        if (context.dataIdFromObject) {
            var semanticId = context.dataIdFromObject(item);
            if (semanticId) {
                itemDataId = semanticId;
                generated = false;
            }
        }
        writeSelectionSetToStore({
            dataId: itemDataId,
            result: item,
            selectionSet: selectionSet,
            context: context,
        });
        var idStoreValue = {
            type: 'id',
            id: itemDataId,
            generated: generated,
        };
        return idStoreValue;
    });
}
//# sourceMappingURL=writeToStore.js.map

/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

function isQueryResultAction(action) {
    return action.type === 'APOLLO_QUERY_RESULT';
}
exports.isQueryResultAction = isQueryResultAction;
function isQueryErrorAction(action) {
    return action.type === 'APOLLO_QUERY_ERROR';
}
exports.isQueryErrorAction = isQueryErrorAction;
function isQueryInitAction(action) {
    return action.type === 'APOLLO_QUERY_INIT';
}
exports.isQueryInitAction = isQueryInitAction;
function isQueryResultClientAction(action) {
    return action.type === 'APOLLO_QUERY_RESULT_CLIENT';
}
exports.isQueryResultClientAction = isQueryResultClientAction;
function isQueryStopAction(action) {
    return action.type === 'APOLLO_QUERY_STOP';
}
exports.isQueryStopAction = isQueryStopAction;
function isMutationInitAction(action) {
    return action.type === 'APOLLO_MUTATION_INIT';
}
exports.isMutationInitAction = isMutationInitAction;
function isMutationResultAction(action) {
    return action.type === 'APOLLO_MUTATION_RESULT';
}
exports.isMutationResultAction = isMutationResultAction;
;
function isMutationErrorAction(action) {
    return action.type === 'APOLLO_MUTATION_ERROR';
}
exports.isMutationErrorAction = isMutationErrorAction;
function isUpdateQueryResultAction(action) {
    return action.type === 'APOLLO_UPDATE_QUERY_RESULT';
}
exports.isUpdateQueryResultAction = isUpdateQueryResultAction;
function isStoreResetAction(action) {
    return action.type === 'APOLLO_STORE_RESET';
}
exports.isStoreResetAction = isStoreResetAction;
function isSubscriptionResultAction(action) {
    return action.type === 'APOLLO_SUBSCRIPTION_RESULT';
}
exports.isSubscriptionResultAction = isSubscriptionResultAction;
//# sourceMappingURL=actions.js.map

/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(process) {
var graphql_anywhere_1 = __webpack_require__(27);
var storeUtils_1 = __webpack_require__(3);
var storeUtils_2 = __webpack_require__(3);
var getFromAST_1 = __webpack_require__(4);
function readQueryFromStore(_a) {
    var store = _a.store, query = _a.query, variables = _a.variables, _b = _a.returnPartialData, returnPartialData = _b === void 0 ? false : _b, config = _a.config;
    var result = diffQueryAgainstStore({
        query: query,
        store: store,
        returnPartialData: returnPartialData,
        variables: variables,
        config: config,
    }).result;
    return result;
}
exports.readQueryFromStore = readQueryFromStore;
var haveWarned = false;
var fragmentMatcher = function (idValue, typeCondition, context) {
    assertIdValue(idValue);
    var obj = context.store[idValue.id];
    if (!obj) {
        return false;
    }
    if (!obj.__typename) {
        if (!haveWarned) {
            console.warn("You're using fragments in your queries, but don't have the addTypename:\ntrue option set in Apollo Client. Please turn on that option so that we can accurately\nmatch fragments.");
            if (process.env.NODE_ENV !== 'test') {
                haveWarned = true;
            }
        }
        context.returnPartialData = true;
        return true;
    }
    if (obj.__typename === typeCondition) {
        return true;
    }
    context.returnPartialData = true;
    return true;
};
var readStoreResolver = function (fieldName, idValue, args, context) {
    assertIdValue(idValue);
    var objId = idValue.id;
    var obj = context.store[objId];
    var storeKeyName = storeUtils_2.storeKeyNameFromFieldNameAndArgs(fieldName, args);
    var fieldValue = (obj || {})[storeKeyName];
    if (typeof fieldValue === 'undefined') {
        if (context.customResolvers && obj && (obj.__typename || objId === 'ROOT_QUERY')) {
            var typename = obj.__typename || 'Query';
            var type = context.customResolvers[typename];
            if (type) {
                var resolver = type[fieldName];
                if (resolver) {
                    return resolver(obj, args);
                }
            }
        }
        if (!context.returnPartialData) {
            throw new Error("Can't find field " + storeKeyName + " on object (" + objId + ") " + JSON.stringify(obj, null, 2) + ".\nPerhaps you want to use the `returnPartialData` option?");
        }
        context.hasMissingField = true;
        return fieldValue;
    }
    if (storeUtils_1.isJsonValue(fieldValue)) {
        return fieldValue.json;
    }
    return fieldValue;
};
function diffQueryAgainstStore(_a) {
    var store = _a.store, query = _a.query, variables = _a.variables, _b = _a.returnPartialData, returnPartialData = _b === void 0 ? true : _b, config = _a.config;
    getFromAST_1.getQueryDefinition(query);
    var context = {
        store: store,
        returnPartialData: returnPartialData,
        customResolvers: config && config.customResolvers,
        hasMissingField: false,
    };
    var rootIdValue = {
        type: 'id',
        id: 'ROOT_QUERY',
    };
    var result = graphql_anywhere_1.default(readStoreResolver, query, rootIdValue, context, variables, {
        fragmentMatcher: fragmentMatcher,
    });
    return {
        result: result,
        isMissing: context.hasMissingField,
    };
}
exports.diffQueryAgainstStore = diffQueryAgainstStore;
function assertIdValue(idValue) {
    if (!storeUtils_1.isIdValue(idValue)) {
        throw new Error("Encountered a sub-selection on the query, but the store doesn't have an object reference. This should never happen during normal use unless you have custom code that is directly manipulating the store; please file an issue.");
    }
}
//# sourceMappingURL=readFromStore.js.map
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(11)))

/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var actions_1 = __webpack_require__(7);
var storeUtils_1 = __webpack_require__(3);
var assign = __webpack_require__(2);
var isEqual = __webpack_require__(20);
(function (NetworkStatus) {
    NetworkStatus[NetworkStatus["loading"] = 1] = "loading";
    NetworkStatus[NetworkStatus["setVariables"] = 2] = "setVariables";
    NetworkStatus[NetworkStatus["fetchMore"] = 3] = "fetchMore";
    NetworkStatus[NetworkStatus["refetch"] = 4] = "refetch";
    NetworkStatus[NetworkStatus["poll"] = 6] = "poll";
    NetworkStatus[NetworkStatus["ready"] = 7] = "ready";
    NetworkStatus[NetworkStatus["error"] = 8] = "error";
})(exports.NetworkStatus || (exports.NetworkStatus = {}));
var NetworkStatus = exports.NetworkStatus;
function queries(previousState, action) {
    if (previousState === void 0) { previousState = {}; }
    if (actions_1.isQueryInitAction(action)) {
        var newState = assign({}, previousState);
        var previousQuery = previousState[action.queryId];
        if (previousQuery && previousQuery.queryString !== action.queryString) {
            throw new Error('Internal Error: may not update existing query string in store');
        }
        var isSetVariables = false;
        var previousVariables = void 0;
        if (action.storePreviousVariables &&
            previousQuery &&
            previousQuery.networkStatus !== NetworkStatus.loading) {
            if (!isEqual(previousQuery.variables, action.variables)) {
                isSetVariables = true;
                previousVariables = previousQuery.variables;
            }
        }
        var newNetworkStatus = NetworkStatus.loading;
        if (isSetVariables) {
            newNetworkStatus = NetworkStatus.setVariables;
        }
        else if (action.isPoll) {
            newNetworkStatus = NetworkStatus.poll;
        }
        else if (action.isRefetch) {
            newNetworkStatus = NetworkStatus.refetch;
        }
        else if (action.isPoll) {
            newNetworkStatus = NetworkStatus.poll;
        }
        newState[action.queryId] = {
            queryString: action.queryString,
            variables: action.variables,
            previousVariables: previousVariables,
            stopped: false,
            loading: true,
            networkError: null,
            graphQLErrors: null,
            networkStatus: newNetworkStatus,
            forceFetch: action.forceFetch,
            returnPartialData: action.returnPartialData,
            lastRequestId: action.requestId,
        };
        return newState;
    }
    else if (actions_1.isQueryResultAction(action)) {
        if (!previousState[action.queryId]) {
            return previousState;
        }
        if (action.requestId < previousState[action.queryId].lastRequestId) {
            return previousState;
        }
        var newState = assign({}, previousState);
        var resultHasGraphQLErrors = storeUtils_1.graphQLResultHasError(action.result);
        newState[action.queryId] = assign({}, previousState[action.queryId], {
            loading: false,
            networkError: null,
            graphQLErrors: resultHasGraphQLErrors ? action.result.errors : null,
            previousVariables: null,
            networkStatus: NetworkStatus.ready,
        });
        return newState;
    }
    else if (actions_1.isQueryErrorAction(action)) {
        if (!previousState[action.queryId]) {
            return previousState;
        }
        if (action.requestId < previousState[action.queryId].lastRequestId) {
            return previousState;
        }
        var newState = assign({}, previousState);
        newState[action.queryId] = assign({}, previousState[action.queryId], {
            loading: false,
            networkError: action.error,
            networkStatus: NetworkStatus.error,
        });
        return newState;
    }
    else if (actions_1.isQueryResultClientAction(action)) {
        if (!previousState[action.queryId]) {
            return previousState;
        }
        var newState = assign({}, previousState);
        newState[action.queryId] = assign({}, previousState[action.queryId], {
            loading: !action.complete,
            networkError: null,
            previousVariables: null,
            networkStatus: action.complete ? NetworkStatus.ready : NetworkStatus.loading,
        });
        return newState;
    }
    else if (actions_1.isQueryStopAction(action)) {
        var newState = assign({}, previousState);
        newState[action.queryId] = assign({}, previousState[action.queryId], {
            loading: false,
            stopped: true,
            networkStatus: NetworkStatus.ready,
        });
        return newState;
    }
    else if (actions_1.isStoreResetAction(action)) {
        return resetQueryState(previousState, action);
    }
    return previousState;
}
exports.queries = queries;
function resetQueryState(state, action) {
    var observableQueryIds = action.observableQueryIds;
    var newQueries = Object.keys(state).filter(function (queryId) {
        return (observableQueryIds.indexOf(queryId) > -1);
    }).reduce(function (res, key) {
        res[key] = assign({}, state[key], { loading: true, networkStatus: NetworkStatus.loading });
        return res;
    }, {});
    return newQueries;
}
//# sourceMappingURL=store.js.map

/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var redux_1 = __webpack_require__(122);
var store_1 = __webpack_require__(23);
var store_2 = __webpack_require__(9);
var store_3 = __webpack_require__(45);
var store_4 = __webpack_require__(46);
var assign = __webpack_require__(2);
var crashReporter = function (store) { return function (next) { return function (action) {
    try {
        return next(action);
    }
    catch (err) {
        console.error('Caught an exception!', err);
        console.error(err.stack);
        throw err;
    }
}; }; };
function createApolloReducer(config) {
    return function apolloReducer(state, action) {
        if (state === void 0) { state = {}; }
        try {
            var newState = {
                queries: store_2.queries(state.queries, action),
                mutations: store_3.mutations(state.mutations, action),
                data: store_1.data(state.data, action, state.queries, state.mutations, config),
                optimistic: [],
                reducerError: null,
            };
            newState.optimistic = store_4.optimistic(state.optimistic, action, newState, config);
            return newState;
        }
        catch (reducerError) {
            return Object.assign({}, state, {
                reducerError: reducerError,
            });
        }
    };
}
exports.createApolloReducer = createApolloReducer;
function createApolloStore(_a) {
    var _b = _a === void 0 ? {} : _a, _c = _b.reduxRootKey, reduxRootKey = _c === void 0 ? 'apollo' : _c, initialState = _b.initialState, _d = _b.config, config = _d === void 0 ? {} : _d, reportCrashes = _b.reportCrashes;
    var enhancers = [];
    if (reportCrashes === undefined) {
        reportCrashes = true;
    }
    if (typeof window !== 'undefined') {
        var anyWindow = window;
        if (anyWindow.devToolsExtension) {
            enhancers.push(anyWindow.devToolsExtension());
        }
    }
    if (reportCrashes) {
        enhancers.push(redux_1.applyMiddleware(crashReporter));
    }
    var compose = redux_1.compose;
    if (initialState && initialState[reduxRootKey] && initialState[reduxRootKey]['queries']) {
        throw new Error('Apollo initial state may not contain queries, only data');
    }
    if (initialState && initialState[reduxRootKey] && initialState[reduxRootKey]['mutations']) {
        throw new Error('Apollo initial state may not contain mutations, only data');
    }
    return redux_1.createStore(redux_1.combineReducers((_e = {}, _e[reduxRootKey] = createApolloReducer(config), _e)), initialState, compose.apply(void 0, enhancers));
    var _e;
}
exports.createApolloStore = createApolloStore;
function getDataWithOptimisticResults(store) {
    if (store.optimistic.length === 0) {
        return store.data;
    }
    var patches = store.optimistic.map(function (opt) { return opt.data; });
    return assign.apply(void 0, [{}, store.data].concat(patches));
}
exports.getDataWithOptimisticResults = getDataWithOptimisticResults;
//# sourceMappingURL=store.js.map

/***/ }),
/* 11 */
/***/ (function(module, exports) {

// shim for using process in browser
var process = module.exports = {};

// cached from whatever global is present so that test runners that stub it
// don't break things.  But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals.  It's inside a
// function because try/catches deoptimize in certain engines.

var cachedSetTimeout;
var cachedClearTimeout;

function defaultSetTimout() {
    throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
    throw new Error('clearTimeout has not been defined');
}
(function () {
    try {
        if (typeof setTimeout === 'function') {
            cachedSetTimeout = setTimeout;
        } else {
            cachedSetTimeout = defaultSetTimout;
        }
    } catch (e) {
        cachedSetTimeout = defaultSetTimout;
    }
    try {
        if (typeof clearTimeout === 'function') {
            cachedClearTimeout = clearTimeout;
        } else {
            cachedClearTimeout = defaultClearTimeout;
        }
    } catch (e) {
        cachedClearTimeout = defaultClearTimeout;
    }
} ())
function runTimeout(fun) {
    if (cachedSetTimeout === setTimeout) {
        //normal enviroments in sane situations
        return setTimeout(fun, 0);
    }
    // if setTimeout wasn't available but was latter defined
    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
        cachedSetTimeout = setTimeout;
        return setTimeout(fun, 0);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedSetTimeout(fun, 0);
    } catch(e){
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
            return cachedSetTimeout.call(null, fun, 0);
        } catch(e){
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
            return cachedSetTimeout.call(this, fun, 0);
        }
    }


}
function runClearTimeout(marker) {
    if (cachedClearTimeout === clearTimeout) {
        //normal enviroments in sane situations
        return clearTimeout(marker);
    }
    // if clearTimeout wasn't available but was latter defined
    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
        cachedClearTimeout = clearTimeout;
        return clearTimeout(marker);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedClearTimeout(marker);
    } catch (e){
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
            return cachedClearTimeout.call(null, marker);
        } catch (e){
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
            return cachedClearTimeout.call(this, marker);
        }
    }



}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;

function cleanUpNextTick() {
    if (!draining || !currentQueue) {
        return;
    }
    draining = false;
    if (currentQueue.length) {
        queue = currentQueue.concat(queue);
    } else {
        queueIndex = -1;
    }
    if (queue.length) {
        drainQueue();
    }
}

function drainQueue() {
    if (draining) {
        return;
    }
    var timeout = runTimeout(cleanUpNextTick);
    draining = true;

    var len = queue.length;
    while(len) {
        currentQueue = queue;
        queue = [];
        while (++queueIndex < len) {
            if (currentQueue) {
                currentQueue[queueIndex].run();
            }
        }
        queueIndex = -1;
        len = queue.length;
    }
    currentQueue = null;
    draining = false;
    runClearTimeout(timeout);
}

process.nextTick = function (fun) {
    var args = new Array(arguments.length - 1);
    if (arguments.length > 1) {
        for (var i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i];
        }
    }
    queue.push(new Item(fun, args));
    if (queue.length === 1 && !draining) {
        runTimeout(drainQueue);
    }
};

// v8 likes predictible objects
function Item(fun, array) {
    this.fun = fun;
    this.array = array;
}
Item.prototype.run = function () {
    this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};

function noop() {}

process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;

process.listeners = function (name) { return [] }

process.binding = function (name) {
    throw new Error('process.binding is not supported');
};

process.cwd = function () { return '/' };
process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };


/***/ }),
/* 12 */
/***/ (function(module, exports) {

module.exports = function(module) {
	if(!module.webpackPolyfill) {
		module.deprecate = function() {};
		module.paths = [];
		// module.parent = undefined by default
		if(!module.children) module.children = [];
		Object.defineProperty(module, "loaded", {
			enumerable: true,
			get: function() {
				return module.l;
			}
		});
		Object.defineProperty(module, "id", {
			enumerable: true,
			get: function() {
				return module.i;
			}
		});
		module.webpackPolyfill = 1;
	}
	return module;
};


/***/ }),
/* 13 */
/***/ (function(module, exports) {

(function(self) {
  'use strict';

  if (self.fetch) {
    return
  }

  var support = {
    searchParams: 'URLSearchParams' in self,
    iterable: 'Symbol' in self && 'iterator' in Symbol,
    blob: 'FileReader' in self && 'Blob' in self && (function() {
      try {
        new Blob()
        return true
      } catch(e) {
        return false
      }
    })(),
    formData: 'FormData' in self,
    arrayBuffer: 'ArrayBuffer' in self
  }

  if (support.arrayBuffer) {
    var viewClasses = [
      '[object Int8Array]',
      '[object Uint8Array]',
      '[object Uint8ClampedArray]',
      '[object Int16Array]',
      '[object Uint16Array]',
      '[object Int32Array]',
      '[object Uint32Array]',
      '[object Float32Array]',
      '[object Float64Array]'
    ]

    var isDataView = function(obj) {
      return obj && DataView.prototype.isPrototypeOf(obj)
    }

    var isArrayBufferView = ArrayBuffer.isView || function(obj) {
      return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
    }
  }

  function normalizeName(name) {
    if (typeof name !== 'string') {
      name = String(name)
    }
    if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
      throw new TypeError('Invalid character in header field name')
    }
    return name.toLowerCase()
  }

  function normalizeValue(value) {
    if (typeof value !== 'string') {
      value = String(value)
    }
    return value
  }

  // Build a destructive iterator for the value list
  function iteratorFor(items) {
    var iterator = {
      next: function() {
        var value = items.shift()
        return {done: value === undefined, value: value}
      }
    }

    if (support.iterable) {
      iterator[Symbol.iterator] = function() {
        return iterator
      }
    }

    return iterator
  }

  function Headers(headers) {
    this.map = {}

    if (headers instanceof Headers) {
      headers.forEach(function(value, name) {
        this.append(name, value)
      }, this)
    } else if (Array.isArray(headers)) {
      headers.forEach(function(header) {
        this.append(header[0], header[1])
      }, this)
    } else if (headers) {
      Object.getOwnPropertyNames(headers).forEach(function(name) {
        this.append(name, headers[name])
      }, this)
    }
  }

  Headers.prototype.append = function(name, value) {
    name = normalizeName(name)
    value = normalizeValue(value)
    var oldValue = this.map[name]
    this.map[name] = oldValue ? oldValue+','+value : value
  }

  Headers.prototype['delete'] = function(name) {
    delete this.map[normalizeName(name)]
  }

  Headers.prototype.get = function(name) {
    name = normalizeName(name)
    return this.has(name) ? this.map[name] : null
  }

  Headers.prototype.has = function(name) {
    return this.map.hasOwnProperty(normalizeName(name))
  }

  Headers.prototype.set = function(name, value) {
    this.map[normalizeName(name)] = normalizeValue(value)
  }

  Headers.prototype.forEach = function(callback, thisArg) {
    for (var name in this.map) {
      if (this.map.hasOwnProperty(name)) {
        callback.call(thisArg, this.map[name], name, this)
      }
    }
  }

  Headers.prototype.keys = function() {
    var items = []
    this.forEach(function(value, name) { items.push(name) })
    return iteratorFor(items)
  }

  Headers.prototype.values = function() {
    var items = []
    this.forEach(function(value) { items.push(value) })
    return iteratorFor(items)
  }

  Headers.prototype.entries = function() {
    var items = []
    this.forEach(function(value, name) { items.push([name, value]) })
    return iteratorFor(items)
  }

  if (support.iterable) {
    Headers.prototype[Symbol.iterator] = Headers.prototype.entries
  }

  function consumed(body) {
    if (body.bodyUsed) {
      return Promise.reject(new TypeError('Already read'))
    }
    body.bodyUsed = true
  }

  function fileReaderReady(reader) {
    return new Promise(function(resolve, reject) {
      reader.onload = function() {
        resolve(reader.result)
      }
      reader.onerror = function() {
        reject(reader.error)
      }
    })
  }

  function readBlobAsArrayBuffer(blob) {
    var reader = new FileReader()
    var promise = fileReaderReady(reader)
    reader.readAsArrayBuffer(blob)
    return promise
  }

  function readBlobAsText(blob) {
    var reader = new FileReader()
    var promise = fileReaderReady(reader)
    reader.readAsText(blob)
    return promise
  }

  function readArrayBufferAsText(buf) {
    var view = new Uint8Array(buf)
    var chars = new Array(view.length)

    for (var i = 0; i < view.length; i++) {
      chars[i] = String.fromCharCode(view[i])
    }
    return chars.join('')
  }

  function bufferClone(buf) {
    if (buf.slice) {
      return buf.slice(0)
    } else {
      var view = new Uint8Array(buf.byteLength)
      view.set(new Uint8Array(buf))
      return view.buffer
    }
  }

  function Body() {
    this.bodyUsed = false

    this._initBody = function(body) {
      this._bodyInit = body
      if (!body) {
        this._bodyText = ''
      } else if (typeof body === 'string') {
        this._bodyText = body
      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
        this._bodyBlob = body
      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
        this._bodyFormData = body
      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
        this._bodyText = body.toString()
      } else if (support.arrayBuffer && support.blob && isDataView(body)) {
        this._bodyArrayBuffer = bufferClone(body.buffer)
        // IE 10-11 can't handle a DataView body.
        this._bodyInit = new Blob([this._bodyArrayBuffer])
      } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
        this._bodyArrayBuffer = bufferClone(body)
      } else {
        throw new Error('unsupported BodyInit type')
      }

      if (!this.headers.get('content-type')) {
        if (typeof body === 'string') {
          this.headers.set('content-type', 'text/plain;charset=UTF-8')
        } else if (this._bodyBlob && this._bodyBlob.type) {
          this.headers.set('content-type', this._bodyBlob.type)
        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
        }
      }
    }

    if (support.blob) {
      this.blob = function() {
        var rejected = consumed(this)
        if (rejected) {
          return rejected
        }

        if (this._bodyBlob) {
          return Promise.resolve(this._bodyBlob)
        } else if (this._bodyArrayBuffer) {
          return Promise.resolve(new Blob([this._bodyArrayBuffer]))
        } else if (this._bodyFormData) {
          throw new Error('could not read FormData body as blob')
        } else {
          return Promise.resolve(new Blob([this._bodyText]))
        }
      }

      this.arrayBuffer = function() {
        if (this._bodyArrayBuffer) {
          return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
        } else {
          return this.blob().then(readBlobAsArrayBuffer)
        }
      }
    }

    this.text = function() {
      var rejected = consumed(this)
      if (rejected) {
        return rejected
      }

      if (this._bodyBlob) {
        return readBlobAsText(this._bodyBlob)
      } else if (this._bodyArrayBuffer) {
        return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
      } else if (this._bodyFormData) {
        throw new Error('could not read FormData body as text')
      } else {
        return Promise.resolve(this._bodyText)
      }
    }

    if (support.formData) {
      this.formData = function() {
        return this.text().then(decode)
      }
    }

    this.json = function() {
      return this.text().then(JSON.parse)
    }

    return this
  }

  // HTTP methods whose capitalization should be normalized
  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']

  function normalizeMethod(method) {
    var upcased = method.toUpperCase()
    return (methods.indexOf(upcased) > -1) ? upcased : method
  }

  function Request(input, options) {
    options = options || {}
    var body = options.body

    if (input instanceof Request) {
      if (input.bodyUsed) {
        throw new TypeError('Already read')
      }
      this.url = input.url
      this.credentials = input.credentials
      if (!options.headers) {
        this.headers = new Headers(input.headers)
      }
      this.method = input.method
      this.mode = input.mode
      if (!body && input._bodyInit != null) {
        body = input._bodyInit
        input.bodyUsed = true
      }
    } else {
      this.url = String(input)
    }

    this.credentials = options.credentials || this.credentials || 'omit'
    if (options.headers || !this.headers) {
      this.headers = new Headers(options.headers)
    }
    this.method = normalizeMethod(options.method || this.method || 'GET')
    this.mode = options.mode || this.mode || null
    this.referrer = null

    if ((this.method === 'GET' || this.method === 'HEAD') && body) {
      throw new TypeError('Body not allowed for GET or HEAD requests')
    }
    this._initBody(body)
  }

  Request.prototype.clone = function() {
    return new Request(this, { body: this._bodyInit })
  }

  function decode(body) {
    var form = new FormData()
    body.trim().split('&').forEach(function(bytes) {
      if (bytes) {
        var split = bytes.split('=')
        var name = split.shift().replace(/\+/g, ' ')
        var value = split.join('=').replace(/\+/g, ' ')
        form.append(decodeURIComponent(name), decodeURIComponent(value))
      }
    })
    return form
  }

  function parseHeaders(rawHeaders) {
    var headers = new Headers()
    // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
    // https://tools.ietf.org/html/rfc7230#section-3.2
    var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ')
    preProcessedHeaders.split(/\r?\n/).forEach(function(line) {
      var parts = line.split(':')
      var key = parts.shift().trim()
      if (key) {
        var value = parts.join(':').trim()
        headers.append(key, value)
      }
    })
    return headers
  }

  Body.call(Request.prototype)

  function Response(bodyInit, options) {
    if (!options) {
      options = {}
    }

    this.type = 'default'
    this.status = options.status === undefined ? 200 : options.status
    this.ok = this.status >= 200 && this.status < 300
    this.statusText = 'statusText' in options ? options.statusText : 'OK'
    this.headers = new Headers(options.headers)
    this.url = options.url || ''
    this._initBody(bodyInit)
  }

  Body.call(Response.prototype)

  Response.prototype.clone = function() {
    return new Response(this._bodyInit, {
      status: this.status,
      statusText: this.statusText,
      headers: new Headers(this.headers),
      url: this.url
    })
  }

  Response.error = function() {
    var response = new Response(null, {status: 0, statusText: ''})
    response.type = 'error'
    return response
  }

  var redirectStatuses = [301, 302, 303, 307, 308]

  Response.redirect = function(url, status) {
    if (redirectStatuses.indexOf(status) === -1) {
      throw new RangeError('Invalid status code')
    }

    return new Response(null, {status: status, headers: {location: url}})
  }

  self.Headers = Headers
  self.Request = Request
  self.Response = Response

  self.fetch = function(input, init) {
    return new Promise(function(resolve, reject) {
      var request = new Request(input, init)
      var xhr = new XMLHttpRequest()

      xhr.onload = function() {
        var options = {
          status: xhr.status,
          statusText: xhr.statusText,
          headers: parseHeaders(xhr.getAllResponseHeaders() || '')
        }
        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
        var body = 'response' in xhr ? xhr.response : xhr.responseText
        resolve(new Response(body, options))
      }

      xhr.onerror = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.ontimeout = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.open(request.method, request.url, true)

      if (request.credentials === 'include') {
        xhr.withCredentials = true
      } else if (request.credentials === 'omit') {
        xhr.withCredentials = false
      }

      if ('responseType' in xhr && support.blob) {
        xhr.responseType = 'blob'
      }

      request.headers.forEach(function(value, name) {
        xhr.setRequestHeader(name, value)
      })

      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
    })
  }
  self.fetch.polyfill = true
})(typeof self !== 'undefined' ? self : this);


/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _timeUtil = __webpack_require__(96);

var _timeUtil2 = _interopRequireDefault(_timeUtil);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _timeUtil2.default;

/***/ }),
/* 15 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Observable_1 = __webpack_require__(25);
var ApolloError_1 = __webpack_require__(17);
var QueryManager_1 = __webpack_require__(16);
var errorHandling_1 = __webpack_require__(26);
var store_1 = __webpack_require__(9);
var getFromAST_1 = __webpack_require__(4);
var assign = __webpack_require__(2);
var isEqual = __webpack_require__(20);
var ObservableQuery = (function (_super) {
    __extends(ObservableQuery, _super);
    function ObservableQuery(_a) {
        var _this = this;
        var scheduler = _a.scheduler, options = _a.options, _b = _a.shouldSubscribe, shouldSubscribe = _b === void 0 ? true : _b;
        var queryManager = scheduler.queryManager;
        var queryId = queryManager.generateQueryId();
        var subscriberFunction = function (observer) {
            return _this.onSubscribe(observer);
        };
        _super.call(this, subscriberFunction);
        this.isCurrentlyPolling = false;
        this.options = options;
        this.variables = this.options.variables || {};
        this.scheduler = scheduler;
        this.queryManager = queryManager;
        this.queryId = queryId;
        this.shouldSubscribe = shouldSubscribe;
        this.observers = [];
        this.subscriptionHandles = [];
    }
    ObservableQuery.prototype.result = function () {
        var _this = this;
        return new Promise(function (resolve, reject) {
            var subscription = _this.subscribe({
                next: function (result) {
                    resolve(result);
                    setTimeout(function () {
                        subscription.unsubscribe();
                    }, 0);
                },
                error: function (error) {
                    reject(error);
                },
            });
        });
    };
    ObservableQuery.prototype.currentResult = function () {
        var _a = this.queryManager.getCurrentQueryResult(this, true), data = _a.data, partial = _a.partial;
        var queryStoreValue = this.queryManager.getApolloState().queries[this.queryId];
        if (queryStoreValue && (queryStoreValue.graphQLErrors || queryStoreValue.networkError)) {
            var error = new ApolloError_1.ApolloError({
                graphQLErrors: queryStoreValue.graphQLErrors,
                networkError: queryStoreValue.networkError,
            });
            return { data: {}, loading: false, networkStatus: queryStoreValue.networkStatus, error: error };
        }
        var queryLoading = !queryStoreValue || queryStoreValue.loading;
        var loading = (this.options.forceFetch && queryLoading)
            || (partial && !this.options.noFetch);
        var networkStatus;
        if (queryStoreValue) {
            networkStatus = queryStoreValue.networkStatus;
        }
        else {
            networkStatus = loading ? store_1.NetworkStatus.loading : store_1.NetworkStatus.ready;
        }
        return { data: data, loading: loading, networkStatus: networkStatus };
    };
    ObservableQuery.prototype.refetch = function (variables) {
        var _this = this;
        this.variables = assign({}, this.variables, variables);
        if (this.options.noFetch) {
            throw new Error('noFetch option should not use query refetch.');
        }
        assign(this.options, {
            variables: this.variables,
        });
        var combinedOptions = assign({}, this.options, {
            forceFetch: true,
        });
        return this.queryManager.fetchQuery(this.queryId, combinedOptions, QueryManager_1.FetchType.refetch)
            .then(function (result) { return _this.queryManager.transformResult(result); });
    };
    ObservableQuery.prototype.fetchMore = function (fetchMoreOptions) {
        var _this = this;
        return Promise.resolve()
            .then(function () {
            var qid = _this.queryManager.generateQueryId();
            var combinedOptions = null;
            if (fetchMoreOptions.query) {
                combinedOptions = fetchMoreOptions;
            }
            else {
                var variables = assign({}, _this.variables, fetchMoreOptions.variables);
                combinedOptions = assign({}, _this.options, fetchMoreOptions, {
                    variables: variables,
                });
            }
            var fullQuery = getFromAST_1.addFragmentsToDocument(combinedOptions.query, combinedOptions.fragments);
            combinedOptions = assign({}, combinedOptions, {
                query: fullQuery,
                forceFetch: true,
            });
            return _this.queryManager.fetchQuery(qid, combinedOptions);
        })
            .then(function (fetchMoreResult) {
            var reducer = fetchMoreOptions.updateQuery;
            var mapFn = function (previousResult, _a) {
                var variables = _a.variables;
                var queryVariables = variables;
                return reducer(previousResult, {
                    fetchMoreResult: fetchMoreResult,
                    queryVariables: queryVariables,
                });
            };
            _this.updateQuery(mapFn);
            return fetchMoreResult;
        });
    };
    ObservableQuery.prototype.subscribeToMore = function (options) {
        var _this = this;
        var observable = this.queryManager.startGraphQLSubscription({
            document: options.document,
            variables: options.variables,
        });
        var reducer = options.updateQuery;
        var subscription = observable.subscribe({
            next: function (data) {
                var mapFn = function (previousResult, _a) {
                    var variables = _a.variables;
                    return reducer(previousResult, {
                        subscriptionData: { data: data },
                        variables: variables,
                    });
                };
                _this.updateQuery(mapFn);
            },
            error: function (err) {
                if (options.onError) {
                    options.onError(err);
                }
                else {
                    console.error('Unhandled GraphQL subscription errror', err);
                }
            },
        });
        this.subscriptionHandles.push(subscription);
        return function () {
            var i = _this.subscriptionHandles.indexOf(subscription);
            if (i >= 0) {
                _this.subscriptionHandles.splice(i, 1);
                subscription.unsubscribe();
            }
        };
    };
    ObservableQuery.prototype.setOptions = function (opts) {
        var _this = this;
        var oldOptions = this.options;
        this.options = assign({}, this.options, opts);
        if (opts.pollInterval) {
            this.startPolling(opts.pollInterval);
        }
        else if (opts.pollInterval === 0) {
            this.stopPolling();
        }
        if (!oldOptions.forceFetch && opts.forceFetch) {
            return this.queryManager.fetchQuery(this.queryId, this.options)
                .then(function (result) { return _this.queryManager.transformResult(result); });
        }
        return this.setVariables(this.options.variables);
    };
    ObservableQuery.prototype.setVariables = function (variables) {
        var _this = this;
        var newVariables = assign({}, this.variables, variables);
        if (isEqual(newVariables, this.variables)) {
            return this.result();
        }
        else {
            this.variables = newVariables;
            return this.queryManager.fetchQuery(this.queryId, assign(this.options, {
                variables: this.variables,
            }))
                .then(function (result) { return _this.queryManager.transformResult(result); });
        }
    };
    ObservableQuery.prototype.updateQuery = function (mapFn) {
        var _a = this.queryManager.getQueryWithPreviousResult(this.queryId), previousResult = _a.previousResult, variables = _a.variables, document = _a.document;
        var newResult = errorHandling_1.tryFunctionOrLogError(function () { return mapFn(previousResult, { variables: variables }); });
        if (newResult) {
            this.queryManager.store.dispatch({
                type: 'APOLLO_UPDATE_QUERY_RESULT',
                newResult: newResult,
                variables: variables,
                document: document,
            });
        }
    };
    ObservableQuery.prototype.stopPolling = function () {
        if (this.isCurrentlyPolling) {
            this.scheduler.stopPollingQuery(this.queryId);
            this.isCurrentlyPolling = false;
        }
    };
    ObservableQuery.prototype.startPolling = function (pollInterval) {
        if (this.options.noFetch) {
            throw new Error('noFetch option should not use query polling.');
        }
        if (this.isCurrentlyPolling) {
            this.scheduler.stopPollingQuery(this.queryId);
            this.isCurrentlyPolling = false;
        }
        this.options.pollInterval = pollInterval;
        this.isCurrentlyPolling = true;
        this.scheduler.startPollingQuery(this.options, this.queryId);
    };
    ObservableQuery.prototype.onSubscribe = function (observer) {
        var _this = this;
        this.observers.push(observer);
        if (observer.next && this.lastResult) {
            observer.next(this.lastResult);
        }
        if (observer.error && this.lastError) {
            observer.error(this.lastError);
        }
        if (this.observers.length === 1) {
            this.setUpQuery();
        }
        var retQuerySubscription = {
            unsubscribe: function () {
                _this.observers = _this.observers.filter(function (obs) { return obs !== observer; });
                if (_this.observers.length === 0) {
                    _this.tearDownQuery();
                }
            },
        };
        return retQuerySubscription;
    };
    ObservableQuery.prototype.setUpQuery = function () {
        var _this = this;
        if (this.shouldSubscribe) {
            this.queryManager.addObservableQuery(this.queryId, this);
        }
        if (!!this.options.pollInterval) {
            if (this.options.noFetch) {
                throw new Error('noFetch option should not use query polling.');
            }
            this.isCurrentlyPolling = true;
            this.scheduler.startPollingQuery(this.options, this.queryId);
        }
        var observer = {
            next: function (result) {
                _this.observers.forEach(function (obs) {
                    if (obs.next) {
                        obs.next(result);
                    }
                });
                _this.lastResult = result;
            },
            error: function (error) {
                _this.observers.forEach(function (obs) {
                    if (obs.error) {
                        obs.error(error);
                    }
                    else {
                        console.error('Unhandled error', error.message, error.stack);
                    }
                });
                _this.lastError = error;
            },
        };
        this.queryManager.startQuery(this.queryId, this.options, this.queryManager.queryListenerForObserver(this.queryId, this.options, observer));
    };
    ObservableQuery.prototype.tearDownQuery = function () {
        if (this.isCurrentlyPolling) {
            this.scheduler.stopPollingQuery(this.queryId);
            this.isCurrentlyPolling = false;
        }
        this.subscriptionHandles.forEach(function (sub) { return sub.unsubscribe(); });
        this.subscriptionHandles = [];
        this.queryManager.stopQuery(this.queryId);
        this.observers = [];
    };
    return ObservableQuery;
}(Observable_1.Observable));
exports.ObservableQuery = ObservableQuery;
//# sourceMappingURL=ObservableQuery.js.map

/***/ }),
/* 16 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(process) {
var forOwn = __webpack_require__(113);
var isEqual = __webpack_require__(20);
var store_1 = __webpack_require__(10);
var getFromAST_1 = __webpack_require__(4);
var queryTransform_1 = __webpack_require__(48);
var resultReducers_1 = __webpack_require__(42);
var printer_1 = __webpack_require__(19);
var readFromStore_1 = __webpack_require__(8);
var readFromStore_2 = __webpack_require__(8);
var scheduler_1 = __webpack_require__(49);
var Observable_1 = __webpack_require__(25);
var store_2 = __webpack_require__(9);
var errorHandling_1 = __webpack_require__(26);
var ApolloError_1 = __webpack_require__(17);
var ObservableQuery_1 = __webpack_require__(15);
;
(function (FetchType) {
    FetchType[FetchType["normal"] = 1] = "normal";
    FetchType[FetchType["refetch"] = 2] = "refetch";
    FetchType[FetchType["poll"] = 3] = "poll";
})(exports.FetchType || (exports.FetchType = {}));
var FetchType = exports.FetchType;
var QueryManager = (function () {
    function QueryManager(_a) {
        var _this = this;
        var networkInterface = _a.networkInterface, store = _a.store, reduxRootSelector = _a.reduxRootSelector, _b = _a.reducerConfig, reducerConfig = _b === void 0 ? { mutationBehaviorReducers: {} } : _b, resultTransformer = _a.resultTransformer, resultComparator = _a.resultComparator, _c = _a.addTypename, addTypename = _c === void 0 ? true : _c;
        this.idCounter = 0;
        this.networkInterface = networkInterface;
        this.store = store;
        this.reduxRootSelector = reduxRootSelector;
        this.reducerConfig = reducerConfig;
        this.resultTransformer = resultTransformer;
        this.resultComparator = resultComparator;
        this.pollingTimers = {};
        this.queryListeners = {};
        this.queryDocuments = {};
        this.addTypename = addTypename;
        this.scheduler = new scheduler_1.QueryScheduler({
            queryManager: this,
        });
        this.fetchQueryPromises = {};
        this.observableQueries = {};
        this.queryIdsByName = {};
        if (this.store['subscribe']) {
            var currentStoreData_1;
            this.store['subscribe'](function () {
                var previousStoreData = currentStoreData_1 || {};
                var previousStoreHasData = Object.keys(previousStoreData).length;
                currentStoreData_1 = _this.getApolloState();
                if (isEqual(previousStoreData, currentStoreData_1) && previousStoreHasData) {
                    return;
                }
                _this.broadcastQueries();
            });
        }
    }
    QueryManager.prototype.broadcastNewStore = function (store) {
        this.broadcastQueries();
    };
    QueryManager.prototype.mutate = function (_a) {
        var _this = this;
        var mutation = _a.mutation, variables = _a.variables, _b = _a.resultBehaviors, resultBehaviors = _b === void 0 ? [] : _b, optimisticResponse = _a.optimisticResponse, updateQueries = _a.updateQueries, _c = _a.refetchQueries, refetchQueries = _c === void 0 ? [] : _c;
        var mutationId = this.generateQueryId();
        if (this.addTypename) {
            mutation = queryTransform_1.addTypenameToDocument(mutation);
        }
        getFromAST_1.checkDocument(mutation);
        var mutationString = printer_1.print(mutation);
        var request = {
            query: mutation,
            variables: variables,
            operationName: getFromAST_1.getOperationName(mutation),
        };
        var updateQueriesResultBehaviors = !optimisticResponse ? [] :
            this.collectResultBehaviorsFromUpdateQueries(updateQueries, { data: optimisticResponse }, true);
        this.queryDocuments[mutationId] = mutation;
        var extraReducers = Object.keys(this.observableQueries).map(function (queryId) {
            var queryOptions = _this.observableQueries[queryId].observableQuery.options;
            if (queryOptions.reducer) {
                return resultReducers_1.createStoreReducer(queryOptions.reducer, queryOptions.query, queryOptions.variables, _this.reducerConfig);
            }
            return null;
        }).filter(function (reducer) { return reducer !== null; });
        this.store.dispatch({
            type: 'APOLLO_MUTATION_INIT',
            mutationString: mutationString,
            mutation: mutation,
            variables: variables,
            operationName: getFromAST_1.getOperationName(mutation),
            mutationId: mutationId,
            optimisticResponse: optimisticResponse,
            resultBehaviors: resultBehaviors.concat(updateQueriesResultBehaviors),
            extraReducers: extraReducers,
        });
        return new Promise(function (resolve, reject) {
            _this.networkInterface.query(request)
                .then(function (result) {
                if (result.errors) {
                    reject(new ApolloError_1.ApolloError({
                        graphQLErrors: result.errors,
                    }));
                }
                _this.store.dispatch({
                    type: 'APOLLO_MUTATION_RESULT',
                    result: result,
                    mutationId: mutationId,
                    document: mutation,
                    operationName: getFromAST_1.getOperationName(mutation),
                    resultBehaviors: resultBehaviors.concat(_this.collectResultBehaviorsFromUpdateQueries(updateQueries, result)),
                    extraReducers: extraReducers,
                });
                refetchQueries.forEach(function (name) { _this.refetchQueryByName(name); });
                delete _this.queryDocuments[mutationId];
                resolve(_this.transformResult(result));
            })
                .catch(function (err) {
                _this.store.dispatch({
                    type: 'APOLLO_MUTATION_ERROR',
                    error: err,
                    mutationId: mutationId,
                });
                delete _this.queryDocuments[mutationId];
                reject(new ApolloError_1.ApolloError({
                    networkError: err,
                }));
            });
        });
    };
    QueryManager.prototype.queryListenerForObserver = function (queryId, options, observer) {
        var _this = this;
        var lastResult;
        return function (queryStoreValue) {
            if (!queryStoreValue) {
                return;
            }
            var shouldNotifyIfLoading = queryStoreValue.returnPartialData
                || queryStoreValue.previousVariables;
            var networkStatusChanged = lastResult && queryStoreValue.networkStatus !== lastResult.networkStatus;
            if (!queryStoreValue.loading ||
                (networkStatusChanged && options.notifyOnNetworkStatusChange) ||
                shouldNotifyIfLoading) {
                if (queryStoreValue.graphQLErrors || queryStoreValue.networkError) {
                    var apolloError = new ApolloError_1.ApolloError({
                        graphQLErrors: queryStoreValue.graphQLErrors,
                        networkError: queryStoreValue.networkError,
                    });
                    if (observer.error) {
                        try {
                            observer.error(apolloError);
                        }
                        catch (e) {
                            console.error("Error in observer.error \n" + e.stack);
                        }
                    }
                    else {
                        console.error('Unhandled error', apolloError, apolloError.stack);
                        if (process.env.NODE_ENV !== 'production') {
                            console.info('An unhandled error was thrown because no error handler is registered ' +
                                'for the query ' + options.query.loc.source);
                        }
                    }
                }
                else {
                    try {
                        var resultFromStore = {
                            data: readFromStore_1.readQueryFromStore({
                                store: _this.getDataWithOptimisticResults(),
                                query: _this.queryDocuments[queryId],
                                variables: queryStoreValue.previousVariables || queryStoreValue.variables,
                                returnPartialData: options.returnPartialData || options.noFetch,
                                config: _this.reducerConfig,
                            }),
                            loading: queryStoreValue.loading,
                            networkStatus: queryStoreValue.networkStatus,
                        };
                        if (observer.next) {
                            if (_this.isDifferentResult(lastResult, resultFromStore)) {
                                lastResult = resultFromStore;
                                try {
                                    observer.next(_this.transformResult(resultFromStore));
                                }
                                catch (e) {
                                    console.error("Error in observer.next \n" + e.stack);
                                }
                            }
                        }
                    }
                    catch (error) {
                        if (observer.error) {
                            observer.error(new ApolloError_1.ApolloError({
                                networkError: error,
                            }));
                        }
                        return;
                    }
                }
            }
        };
    };
    QueryManager.prototype.watchQuery = function (options, shouldSubscribe) {
        if (shouldSubscribe === void 0) { shouldSubscribe = true; }
        getFromAST_1.getQueryDefinition(options.query);
        var transformedOptions = Object.assign({}, options);
        if (this.addTypename) {
            transformedOptions.query = queryTransform_1.addTypenameToDocument(transformedOptions.query);
        }
        var observableQuery = new ObservableQuery_1.ObservableQuery({
            scheduler: this.scheduler,
            options: transformedOptions,
            shouldSubscribe: shouldSubscribe,
        });
        return observableQuery;
    };
    QueryManager.prototype.query = function (options) {
        var _this = this;
        if (options.returnPartialData) {
            throw new Error('returnPartialData option only supported on watchQuery.');
        }
        if (options.query.kind !== 'Document') {
            throw new Error('You must wrap the query string in a "gql" tag.');
        }
        var requestId = this.idCounter;
        var resPromise = new Promise(function (resolve, reject) {
            _this.addFetchQueryPromise(requestId, resPromise, resolve, reject);
            return _this.watchQuery(options, false).result().then(function (result) {
                _this.removeFetchQueryPromise(requestId);
                resolve(result);
            }).catch(function (error) {
                _this.removeFetchQueryPromise(requestId);
                reject(error);
            });
        });
        return resPromise;
    };
    QueryManager.prototype.fetchQuery = function (queryId, options, fetchType) {
        var variables = options.variables, _a = options.forceFetch, forceFetch = _a === void 0 ? false : _a, _b = options.returnPartialData, returnPartialData = _b === void 0 ? false : _b, _c = options.noFetch, noFetch = _c === void 0 ? false : _c;
        var queryDoc = this.transformQueryDocument(options).queryDoc;
        var queryString = printer_1.print(queryDoc);
        var storeResult;
        var needToFetch = forceFetch;
        if (!forceFetch) {
            var _d = readFromStore_2.diffQueryAgainstStore({
                query: queryDoc,
                store: this.reduxRootSelector(this.store.getState()).data,
                returnPartialData: true,
                variables: variables,
                config: this.reducerConfig,
            }), isMissing = _d.isMissing, result = _d.result;
            needToFetch = isMissing;
            storeResult = result;
        }
        var requestId = this.generateRequestId();
        var shouldFetch = needToFetch && !noFetch;
        this.queryDocuments[queryId] = queryDoc;
        this.store.dispatch({
            type: 'APOLLO_QUERY_INIT',
            queryString: queryString,
            document: queryDoc,
            variables: variables,
            forceFetch: forceFetch,
            returnPartialData: returnPartialData || noFetch,
            queryId: queryId,
            requestId: requestId,
            storePreviousVariables: shouldFetch,
            isPoll: fetchType === FetchType.poll,
            isRefetch: fetchType === FetchType.refetch,
        });
        if (!shouldFetch || returnPartialData) {
            this.store.dispatch({
                type: 'APOLLO_QUERY_RESULT_CLIENT',
                result: { data: storeResult },
                variables: variables,
                document: queryDoc,
                complete: !shouldFetch,
                queryId: queryId,
            });
        }
        if (shouldFetch) {
            return this.fetchRequest({
                requestId: requestId,
                queryId: queryId,
                document: queryDoc,
                options: options,
            });
        }
        return Promise.resolve({ data: storeResult });
    };
    QueryManager.prototype.generateQueryId = function () {
        var queryId = this.idCounter.toString();
        this.idCounter++;
        return queryId;
    };
    QueryManager.prototype.stopQueryInStore = function (queryId) {
        this.store.dispatch({
            type: 'APOLLO_QUERY_STOP',
            queryId: queryId,
        });
    };
    ;
    QueryManager.prototype.getApolloState = function () {
        return this.reduxRootSelector(this.store.getState());
    };
    QueryManager.prototype.getInitialState = function () {
        return { data: this.getApolloState().data };
    };
    QueryManager.prototype.getDataWithOptimisticResults = function () {
        return store_1.getDataWithOptimisticResults(this.getApolloState());
    };
    QueryManager.prototype.addQueryListener = function (queryId, listener) {
        this.queryListeners[queryId] = this.queryListeners[queryId] || [];
        this.queryListeners[queryId].push(listener);
    };
    QueryManager.prototype.addFetchQueryPromise = function (requestId, promise, resolve, reject) {
        this.fetchQueryPromises[requestId.toString()] = { promise: promise, resolve: resolve, reject: reject };
    };
    QueryManager.prototype.removeFetchQueryPromise = function (requestId) {
        delete this.fetchQueryPromises[requestId.toString()];
    };
    QueryManager.prototype.addObservableQuery = function (queryId, observableQuery) {
        this.observableQueries[queryId] = { observableQuery: observableQuery };
        var queryDef = getFromAST_1.getQueryDefinition(observableQuery.options.query);
        if (queryDef.name && queryDef.name.value) {
            var queryName = getFromAST_1.getQueryDefinition(observableQuery.options.query).name.value;
            this.queryIdsByName[queryName] = this.queryIdsByName[queryName] || [];
            this.queryIdsByName[queryName].push(observableQuery.queryId);
        }
    };
    QueryManager.prototype.removeObservableQuery = function (queryId) {
        var observableQuery = this.observableQueries[queryId].observableQuery;
        var queryName = getFromAST_1.getQueryDefinition(observableQuery.options.query).name.value;
        delete this.observableQueries[queryId];
        this.queryIdsByName[queryName] = this.queryIdsByName[queryName].filter(function (val) {
            return !(observableQuery.queryId === val);
        });
    };
    QueryManager.prototype.resetStore = function () {
        var _this = this;
        Object.keys(this.fetchQueryPromises).forEach(function (key) {
            var reject = _this.fetchQueryPromises[key].reject;
            reject(new Error('Store reset while query was in flight.'));
        });
        this.store.dispatch({
            type: 'APOLLO_STORE_RESET',
            observableQueryIds: Object.keys(this.observableQueries),
        });
        Object.keys(this.observableQueries).forEach(function (queryId) {
            if (!_this.observableQueries[queryId].observableQuery.options.noFetch) {
                _this.observableQueries[queryId].observableQuery.refetch();
            }
        });
    };
    QueryManager.prototype.startQuery = function (queryId, options, listener) {
        this.addQueryListener(queryId, listener);
        this.fetchQuery(queryId, options)
            .catch(function (error) { return undefined; });
        return queryId;
    };
    QueryManager.prototype.startGraphQLSubscription = function (options) {
        var _this = this;
        var document = options.document, variables = options.variables;
        var transformedDoc = document;
        if (this.addTypename) {
            transformedDoc = queryTransform_1.addTypenameToDocument(transformedDoc);
        }
        var request = {
            query: transformedDoc,
            variables: variables,
            operationName: getFromAST_1.getOperationName(transformedDoc),
        };
        var subId;
        var observers = [];
        return new Observable_1.Observable(function (observer) {
            observers.push(observer);
            if (observers.length === 1) {
                var handler = function (error, result) {
                    if (error) {
                        observers.forEach(function (obs) {
                            obs.error(error);
                        });
                    }
                    else {
                        _this.store.dispatch({
                            type: 'APOLLO_SUBSCRIPTION_RESULT',
                            document: transformedDoc,
                            operationName: getFromAST_1.getOperationName(transformedDoc),
                            result: { data: result },
                            variables: variables,
                            subscriptionId: subId,
                            extraReducers: _this.getExtraReducers(),
                        });
                        observers.forEach(function (obs) {
                            obs.next(result);
                        });
                    }
                };
                subId = _this.networkInterface.subscribe(request, handler);
            }
            return {
                unsubscribe: function () {
                    observers = observers.filter(function (obs) { return obs !== observer; });
                    if (observers.length === 0) {
                        _this.networkInterface.unsubscribe(subId);
                    }
                },
                _networkSubscriptionId: subId,
            };
        });
    };
    ;
    QueryManager.prototype.stopQuery = function (queryId) {
        delete this.queryListeners[queryId];
        delete this.queryDocuments[queryId];
        this.stopQueryInStore(queryId);
    };
    QueryManager.prototype.getCurrentQueryResult = function (observableQuery, isOptimistic) {
        if (isOptimistic === void 0) { isOptimistic = false; }
        var _a = this.getQueryParts(observableQuery), variables = _a.variables, document = _a.document;
        var queryOptions = observableQuery.options;
        var readOptions = {
            store: isOptimistic ? this.getDataWithOptimisticResults() : this.getApolloState().data,
            query: document,
            variables: variables,
            returnPartialData: false,
            config: this.reducerConfig,
        };
        try {
            var data = readFromStore_1.readQueryFromStore(readOptions);
            return { data: data, partial: false };
        }
        catch (e) {
            if (queryOptions.returnPartialData || queryOptions.noFetch) {
                try {
                    readOptions.returnPartialData = true;
                    var data = readFromStore_1.readQueryFromStore(readOptions);
                    return { data: data, partial: true };
                }
                catch (e) {
                }
            }
            return { data: {}, partial: true };
        }
    };
    QueryManager.prototype.getQueryWithPreviousResult = function (queryIdOrObservable, isOptimistic) {
        if (isOptimistic === void 0) { isOptimistic = false; }
        var observableQuery;
        if (typeof queryIdOrObservable === 'string') {
            if (!this.observableQueries[queryIdOrObservable]) {
                throw new Error("ObservableQuery with this id doesn't exist: " + queryIdOrObservable);
            }
            observableQuery = this.observableQueries[queryIdOrObservable].observableQuery;
        }
        else {
            observableQuery = queryIdOrObservable;
        }
        var _a = this.getQueryParts(observableQuery), variables = _a.variables, document = _a.document;
        var data = this.getCurrentQueryResult(observableQuery, isOptimistic).data;
        return {
            previousResult: data,
            variables: variables,
            document: document,
        };
    };
    QueryManager.prototype.transformResult = function (result) {
        if (!this.resultTransformer) {
            return result;
        }
        else {
            return this.resultTransformer(result);
        }
    };
    QueryManager.prototype.getQueryParts = function (observableQuery) {
        var queryOptions = observableQuery.options;
        var transformedDoc = observableQuery.options.query;
        if (this.addTypename) {
            transformedDoc = queryTransform_1.addTypenameToDocument(transformedDoc);
        }
        return {
            variables: queryOptions.variables,
            document: transformedDoc,
        };
    };
    QueryManager.prototype.collectResultBehaviorsFromUpdateQueries = function (updateQueries, mutationResult, isOptimistic) {
        var _this = this;
        if (isOptimistic === void 0) { isOptimistic = false; }
        if (!updateQueries) {
            return [];
        }
        var resultBehaviors = [];
        Object.keys(updateQueries).forEach(function (queryName) {
            var reducer = updateQueries[queryName];
            var queryIds = _this.queryIdsByName[queryName];
            if (!queryIds) {
                return;
            }
            queryIds.forEach(function (queryId) {
                var _a = _this.getQueryWithPreviousResult(queryId, isOptimistic), previousResult = _a.previousResult, variables = _a.variables, document = _a.document;
                var newResult = errorHandling_1.tryFunctionOrLogError(function () { return reducer(previousResult, {
                    mutationResult: mutationResult,
                    queryName: queryName,
                    queryVariables: variables,
                }); });
                if (newResult) {
                    resultBehaviors.push({
                        type: 'QUERY_RESULT',
                        newResult: newResult,
                        variables: variables,
                        document: document,
                    });
                }
            });
        });
        return resultBehaviors;
    };
    QueryManager.prototype.transformQueryDocument = function (options) {
        var queryDoc = options.query;
        if (this.addTypename) {
            queryDoc = queryTransform_1.addTypenameToDocument(queryDoc);
        }
        return {
            queryDoc: queryDoc,
        };
    };
    QueryManager.prototype.getExtraReducers = function () {
        var _this = this;
        return Object.keys(this.observableQueries).map(function (obsQueryId) {
            var queryOptions = _this.observableQueries[obsQueryId].observableQuery.options;
            if (queryOptions.reducer) {
                return resultReducers_1.createStoreReducer(queryOptions.reducer, queryOptions.query, queryOptions.variables, _this.reducerConfig);
            }
            return null;
        }).filter(function (reducer) { return reducer !== null; });
    };
    QueryManager.prototype.fetchRequest = function (_a) {
        var _this = this;
        var requestId = _a.requestId, queryId = _a.queryId, document = _a.document, options = _a.options;
        var variables = options.variables, noFetch = options.noFetch, returnPartialData = options.returnPartialData;
        var request = {
            query: document,
            variables: variables,
            operationName: getFromAST_1.getOperationName(document),
        };
        var retPromise = new Promise(function (resolve, reject) {
            _this.addFetchQueryPromise(requestId, retPromise, resolve, reject);
            _this.networkInterface.query(request)
                .then(function (result) {
                var extraReducers = _this.getExtraReducers();
                _this.store.dispatch({
                    type: 'APOLLO_QUERY_RESULT',
                    document: document,
                    operationName: getFromAST_1.getOperationName(document),
                    result: result,
                    queryId: queryId,
                    requestId: requestId,
                    extraReducers: extraReducers,
                });
                _this.removeFetchQueryPromise(requestId);
                if (result.errors) {
                    throw new ApolloError_1.ApolloError({
                        graphQLErrors: result.errors,
                    });
                }
                return result;
            }).then(function () {
                var resultFromStore;
                try {
                    resultFromStore = readFromStore_1.readQueryFromStore({
                        store: _this.getApolloState().data,
                        variables: variables,
                        returnPartialData: returnPartialData || noFetch,
                        query: document,
                        config: _this.reducerConfig,
                    });
                }
                catch (e) { }
                var reducerError = _this.getApolloState().reducerError;
                if (!resultFromStore && reducerError) {
                    return Promise.reject(reducerError);
                }
                _this.removeFetchQueryPromise(requestId);
                resolve({ data: resultFromStore, loading: false, networkStatus: store_2.NetworkStatus.ready });
                return null;
            }).catch(function (error) {
                if (error instanceof ApolloError_1.ApolloError) {
                    reject(error);
                }
                else {
                    _this.store.dispatch({
                        type: 'APOLLO_QUERY_ERROR',
                        error: error,
                        queryId: queryId,
                        requestId: requestId,
                    });
                    _this.removeFetchQueryPromise(requestId);
                    reject(new ApolloError_1.ApolloError({
                        networkError: error,
                    }));
                }
            });
        });
        return retPromise;
    };
    QueryManager.prototype.refetchQueryByName = function (queryName) {
        var _this = this;
        var refetchedQueries = this.queryIdsByName[queryName];
        if (refetchedQueries === undefined) {
            console.warn("Warning: unknown query with name " + queryName + " asked to refetch");
        }
        else {
            refetchedQueries.forEach(function (queryId) {
                _this.observableQueries[queryId].observableQuery.refetch();
            });
        }
    };
    QueryManager.prototype.isDifferentResult = function (lastResult, newResult) {
        var comparator = this.resultComparator || isEqual;
        return !comparator(lastResult, newResult);
    };
    QueryManager.prototype.broadcastQueries = function () {
        var queries = this.getApolloState().queries;
        forOwn(this.queryListeners, function (listeners, queryId) {
            if (listeners) {
                listeners.forEach(function (listener) {
                    if (listener) {
                        var queryStoreValue = queries[queryId];
                        listener(queryStoreValue);
                    }
                });
            }
        });
    };
    QueryManager.prototype.generateRequestId = function () {
        var requestId = this.idCounter;
        this.idCounter++;
        return requestId;
    };
    return QueryManager;
}());
exports.QueryManager = QueryManager;
//# sourceMappingURL=QueryManager.js.map
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(11)))

/***/ }),
/* 17 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var ApolloError = (function (_super) {
    __extends(ApolloError, _super);
    function ApolloError(_a) {
        var graphQLErrors = _a.graphQLErrors, networkError = _a.networkError, errorMessage = _a.errorMessage, extraInfo = _a.extraInfo;
        _super.call(this, errorMessage);
        this.graphQLErrors = graphQLErrors;
        this.networkError = networkError;
        this.stack = new Error().stack;
        if (!errorMessage) {
            this.generateErrorMessage();
        }
        else {
            this.message = errorMessage;
        }
        this.extraInfo = extraInfo;
    }
    ApolloError.prototype.generateErrorMessage = function () {
        if (typeof this.message !== 'undefined' &&
            this.message !== '') {
            return;
        }
        var message = '';
        if (Array.isArray(this.graphQLErrors) && this.graphQLErrors.length !== 0) {
            this.graphQLErrors.forEach(function (graphQLError) {
                message += 'GraphQL error: ' + graphQLError.message + '\n';
            });
        }
        if (this.networkError) {
            message += 'Network error: ' + this.networkError.message + '\n';
        }
        message = message.replace(/\n$/, '');
        this.message = message;
    };
    return ApolloError;
}(Error));
exports.ApolloError = ApolloError;
//# sourceMappingURL=ApolloError.js.map

/***/ }),
/* 18 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var isString = __webpack_require__(33);
var assign = __webpack_require__(2);
var mapValues = __webpack_require__(35);
__webpack_require__(13);
var printer_1 = __webpack_require__(19);
function printRequest(request) {
    return mapValues(request, function (val, key) {
        return key === 'query' ? printer_1.print(val) : val;
    });
}
exports.printRequest = printRequest;
var HTTPFetchNetworkInterface = (function () {
    function HTTPFetchNetworkInterface(uri, opts) {
        if (opts === void 0) { opts = {}; }
        if (!uri) {
            throw new Error('A remote enpdoint is required for a network layer');
        }
        if (!isString(uri)) {
            throw new Error('Remote endpoint must be a string');
        }
        this._uri = uri;
        this._opts = assign({}, opts);
        this._middlewares = [];
        this._afterwares = [];
    }
    HTTPFetchNetworkInterface.prototype.applyMiddlewares = function (_a) {
        var _this = this;
        var request = _a.request, options = _a.options;
        return new Promise(function (resolve, reject) {
            var queue = function (funcs, scope) {
                var next = function () {
                    if (funcs.length > 0) {
                        var f = funcs.shift();
                        f.applyMiddleware.apply(scope, [{ request: request, options: options }, next]);
                    }
                    else {
                        resolve({
                            request: request,
                            options: options,
                        });
                    }
                };
                next();
            };
            queue(_this._middlewares.slice(), _this);
        });
    };
    HTTPFetchNetworkInterface.prototype.applyAfterwares = function (_a) {
        var _this = this;
        var response = _a.response, options = _a.options;
        return new Promise(function (resolve, reject) {
            var queue = function (funcs, scope) {
                var next = function () {
                    if (funcs.length > 0) {
                        var f = funcs.shift();
                        f.applyAfterware.apply(scope, [{ response: response, options: options }, next]);
                    }
                    else {
                        resolve({
                            response: response,
                            options: options,
                        });
                    }
                };
                next();
            };
            queue(_this._afterwares.slice(), _this);
        });
    };
    HTTPFetchNetworkInterface.prototype.fetchFromRemoteEndpoint = function (_a) {
        var request = _a.request, options = _a.options;
        return fetch(this._uri, assign({}, this._opts, {
            body: JSON.stringify(printRequest(request)),
            method: 'POST',
        }, options, {
            headers: assign({}, {
                Accept: '*/*',
                'Content-Type': 'application/json',
            }, options.headers),
        }));
    };
    ;
    HTTPFetchNetworkInterface.prototype.query = function (request) {
        var _this = this;
        var options = assign({}, this._opts);
        return this.applyMiddlewares({
            request: request,
            options: options,
        }).then(this.fetchFromRemoteEndpoint.bind(this))
            .then(function (response) {
            _this.applyAfterwares({
                response: response,
                options: options,
            });
            return response;
        })
            .then(function (result) { return result.json(); })
            .then(function (payload) {
            if (!payload.hasOwnProperty('data') && !payload.hasOwnProperty('errors')) {
                throw new Error("Server response was missing for query '" + request.debugName + "'.");
            }
            else {
                return payload;
            }
        });
    };
    ;
    HTTPFetchNetworkInterface.prototype.use = function (middlewares) {
        var _this = this;
        middlewares.map(function (middleware) {
            if (typeof middleware.applyMiddleware === 'function') {
                _this._middlewares.push(middleware);
            }
            else {
                throw new Error('Middleware must implement the applyMiddleware function');
            }
        });
        return this;
    };
    HTTPFetchNetworkInterface.prototype.useAfter = function (afterwares) {
        var _this = this;
        afterwares.map(function (afterware) {
            if (typeof afterware.applyAfterware === 'function') {
                _this._afterwares.push(afterware);
            }
            else {
                throw new Error('Afterware must implement the applyAfterware function');
            }
        });
        return this;
    };
    return HTTPFetchNetworkInterface;
}());
exports.HTTPFetchNetworkInterface = HTTPFetchNetworkInterface;
function createNetworkInterface(uriOrInterfaceOpts, secondArgOpts) {
    if (secondArgOpts === void 0) { secondArgOpts = {}; }
    if (!uriOrInterfaceOpts) {
        throw new Error('You must pass an options argument to createNetworkInterface.');
    }
    var uri;
    var opts;
    if (isString(uriOrInterfaceOpts)) {
        console.warn("Passing the URI as the first argument to createNetworkInterface is deprecated as of Apollo Client 0.5. Please pass it as the \"uri\" property of the network interface options.");
        opts = secondArgOpts;
        uri = uriOrInterfaceOpts;
    }
    else {
        opts = uriOrInterfaceOpts.opts;
        uri = uriOrInterfaceOpts.uri;
    }
    return new HTTPFetchNetworkInterface(uri, opts);
}
exports.createNetworkInterface = createNetworkInterface;
//# sourceMappingURL=networkInterface.js.map

/***/ }),
/* 19 */
/***/ (function(module, exports, __webpack_require__) {

var printer = __webpack_require__(102);

console.warn(
  "Warning - the `printer` exports from `graphql-tag` will be removed in the next major version." +
  "\nSee https://github.com/apollographql/graphql-tag/issues/54 for more information."
);

module.exports = printer;


/***/ }),
/* 20 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global, module) {/**
 * Lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright JS Foundation and other contributors <https://js.foundation/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    asyncTag = '[object AsyncFunction]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    nullTag = '[object Null]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    proxyTag = '[object Proxy]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]',
    undefinedTag = '[object Undefined]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && freeGlobal.process;

/** Used to access faster Node.js helpers. */
var nodeUtil = (function() {
  try {
    return freeProcess && freeProcess.binding && freeProcess.binding('util');
  } catch (e) {}
}());

/* Node.js helper references. */
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

/**
 * A specialized version of `_.filter` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length,
      resIndex = 0,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[resIndex++] = value;
    }
  }
  return result;
}

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

/**
 * A specialized version of `_.some` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * The base implementation of `_.unary` without support for storing metadata.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @returns {Function} Returns the new capped function.
 */
function baseUnary(func) {
  return function(value) {
    return func(value);
  };
}

/**
 * Checks if a `cache` value for `key` exists.
 *
 * @private
 * @param {Object} cache The cache to query.
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function cacheHas(cache, key) {
  return cache.has(key);
}

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function(value, key) {
    result[++index] = [key, value];
  });
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/** Built-in value references. */
var Buffer = moduleExports ? root.Buffer : undefined,
    Symbol = root.Symbol,
    Uint8Array = root.Uint8Array,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    splice = arrayProto.splice,
    symToStringTag = Symbol ? Symbol.toStringTag : undefined;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols,
    nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
    nativeKeys = overArg(Object.keys, Object);

/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView'),
    Map = getNative(root, 'Map'),
    Promise = getNative(root, 'Promise'),
    Set = getNative(root, 'Set'),
    WeakMap = getNative(root, 'WeakMap'),
    nativeCreate = getNative(Object, 'create');

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
    mapCtorString = toSource(Map),
    promiseCtorString = toSource(Promise),
    setCtorString = toSource(Set),
    weakMapCtorString = toSource(WeakMap);

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
  this.size = 0;
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  var result = this.has(key) && delete this.__data__[key];
  this.size -= result ? 1 : 0;
  return result;
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  this.size += this.has(key) ? 0 : 1;
  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
  this.size = 0;
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  --this.size;
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    ++this.size;
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.size = 0;
  this.__data__ = {
    'hash': new Hash,
    'map': new (Map || ListCache),
    'string': new Hash
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  var result = getMapData(this, key)['delete'](key);
  this.size -= result ? 1 : 0;
  return result;
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  var data = getMapData(this, key),
      size = data.size;

  data.set(key, value);
  this.size += data.size == size ? 0 : 1;
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
  var index = -1,
      length = values == null ? 0 : values.length;

  this.__data__ = new MapCache;
  while (++index < length) {
    this.add(values[index]);
  }
}

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;

/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  var data = this.__data__ = new ListCache(entries);
  this.size = data.size;
}

/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new ListCache;
  this.size = 0;
}

/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  var data = this.__data__,
      result = data['delete'](key);

  this.size = data.size;
  return result;
}

/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var data = this.__data__;
  if (data instanceof ListCache) {
    var pairs = data.__data__;
    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
      pairs.push([key, value]);
      this.size = ++data.size;
      return this;
    }
    data = this.__data__ = new MapCache(pairs);
  }
  data.set(key, value);
  this.size = data.size;
  return this;
}

// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  var isArr = isArray(value),
      isArg = !isArr && isArguments(value),
      isBuff = !isArr && !isArg && isBuffer(value),
      isType = !isArr && !isArg && !isBuff && isTypedArray(value),
      skipIndexes = isArr || isArg || isBuff || isType,
      result = skipIndexes ? baseTimes(value.length, String) : [],
      length = result.length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (
           // Safari 9 has enumerable `arguments.length` in strict mode.
           key == 'length' ||
           // Node.js 0.10 has enumerable non-index properties on buffers.
           (isBuff && (key == 'offset' || key == 'parent')) ||
           // PhantomJS 2 has enumerable non-index properties on typed arrays.
           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
           // Skip index properties.
           isIndex(key, length)
        ))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
 * symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @param {Function} symbolsFunc The function to get the symbols of `object`.
 * @returns {Array} Returns the array of property names and symbols.
 */
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
  var result = keysFunc(object);
  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}

/**
 * The base implementation of `getTag` without fallbacks for buggy environments.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  if (value == null) {
    return value === undefined ? undefinedTag : nullTag;
  }
  return (symToStringTag && symToStringTag in Object(value))
    ? getRawTag(value)
    : objectToString(value);
}

/**
 * The base implementation of `_.isArguments`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 */
function baseIsArguments(value) {
  return isObjectLike(value) && baseGetTag(value) == argsTag;
}

/**
 * The base implementation of `_.isEqual` which supports partial comparisons
 * and tracks traversed objects.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {boolean} bitmask The bitmask flags.
 *  1 - Unordered comparison
 *  2 - Partial comparison
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, bitmask, customizer, stack) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
    return value !== value && other !== other;
  }
  return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
  var objIsArr = isArray(object),
      othIsArr = isArray(other),
      objTag = objIsArr ? arrayTag : getTag(object),
      othTag = othIsArr ? arrayTag : getTag(other);

  objTag = objTag == argsTag ? objectTag : objTag;
  othTag = othTag == argsTag ? objectTag : othTag;

  var objIsObj = objTag == objectTag,
      othIsObj = othTag == objectTag,
      isSameTag = objTag == othTag;

  if (isSameTag && isBuffer(object)) {
    if (!isBuffer(other)) {
      return false;
    }
    objIsArr = true;
    objIsObj = false;
  }
  if (isSameTag && !objIsObj) {
    stack || (stack = new Stack);
    return (objIsArr || isTypedArray(object))
      ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
      : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
  }
  if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      var objUnwrapped = objIsWrapped ? object.value() : object,
          othUnwrapped = othIsWrapped ? other.value() : other;

      stack || (stack = new Stack);
      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
    }
  }
  if (!isSameTag) {
    return false;
  }
  stack || (stack = new Stack);
  return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 */
function baseIsTypedArray(value) {
  return isObjectLike(value) &&
    isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `array` and `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
    return false;
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(array);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var index = -1,
      result = true,
      seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;

  stack.set(array, other);
  stack.set(other, array);

  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, arrValue, index, other, array, stack)
        : customizer(arrValue, othValue, index, array, other, stack);
    }
    if (compared !== undefined) {
      if (compared) {
        continue;
      }
      result = false;
      break;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (seen) {
      if (!arraySome(other, function(othValue, othIndex) {
            if (!cacheHas(seen, othIndex) &&
                (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
              return seen.push(othIndex);
            }
          })) {
        result = false;
        break;
      }
    } else if (!(
          arrValue === othValue ||
            equalFunc(arrValue, othValue, bitmask, customizer, stack)
        )) {
      result = false;
      break;
    }
  }
  stack['delete'](array);
  stack['delete'](other);
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
  switch (tag) {
    case dataViewTag:
      if ((object.byteLength != other.byteLength) ||
          (object.byteOffset != other.byteOffset)) {
        return false;
      }
      object = object.buffer;
      other = other.buffer;

    case arrayBufferTag:
      if ((object.byteLength != other.byteLength) ||
          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
        return false;
      }
      return true;

    case boolTag:
    case dateTag:
    case numberTag:
      // Coerce booleans to `1` or `0` and dates to milliseconds.
      // Invalid dates are coerced to `NaN`.
      return eq(+object, +other);

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings, primitives and objects,
      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
      // for more details.
      return object == (other + '');

    case mapTag:
      var convert = mapToArray;

    case setTag:
      var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
      convert || (convert = setToArray);

      if (object.size != other.size && !isPartial) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked) {
        return stacked == other;
      }
      bitmask |= COMPARE_UNORDERED_FLAG;

      // Recursively compare objects (susceptible to call stack limits).
      stack.set(object, other);
      var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
      stack['delete'](object);
      return result;

    case symbolTag:
      if (symbolValueOf) {
        return symbolValueOf.call(object) == symbolValueOf.call(other);
      }
  }
  return false;
}

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      objProps = getAllKeys(object),
      objLength = objProps.length,
      othProps = getAllKeys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isPartial) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(object);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var result = true;
  stack.set(object, other);
  stack.set(other, object);

  var skipCtor = isPartial;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, objValue, key, other, object, stack)
        : customizer(objValue, othValue, key, object, other, stack);
    }
    // Recursively compare objects (susceptible to call stack limits).
    if (!(compared === undefined
          ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
          : compared
        )) {
      result = false;
      break;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (result && !skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor &&
        ('constructor' in object && 'constructor' in other) &&
        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      result = false;
    }
  }
  stack['delete'](object);
  stack['delete'](other);
  return result;
}

/**
 * Creates an array of own enumerable property names and symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names and symbols.
 */
function getAllKeys(object) {
  return baseGetAllKeys(object, keys, getSymbols);
}

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the raw `toStringTag`.
 */
function getRawTag(value) {
  var isOwn = hasOwnProperty.call(value, symToStringTag),
      tag = value[symToStringTag];

  try {
    value[symToStringTag] = undefined;
    var unmasked = true;
  } catch (e) {}

  var result = nativeObjectToString.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag;
    } else {
      delete value[symToStringTag];
    }
  }
  return result;
}

/**
 * Creates an array of the own enumerable symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of symbols.
 */
var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
  if (object == null) {
    return [];
  }
  object = Object(object);
  return arrayFilter(nativeGetSymbols(object), function(symbol) {
    return propertyIsEnumerable.call(object, symbol);
  });
};

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = baseGetTag;

// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
    (Map && getTag(new Map) != mapTag) ||
    (Promise && getTag(Promise.resolve()) != promiseTag) ||
    (Set && getTag(new Set) != setTag) ||
    (WeakMap && getTag(new WeakMap) != weakMapTag)) {
  getTag = function(value) {
    var result = baseGetTag(value),
        Ctor = result == objectTag ? value.constructor : undefined,
        ctorString = Ctor ? toSource(Ctor) : '';

    if (ctorString) {
      switch (ctorString) {
        case dataViewCtorString: return dataViewTag;
        case mapCtorString: return mapTag;
        case promiseCtorString: return promiseTag;
        case setCtorString: return setTag;
        case weakMapCtorString: return weakMapTag;
      }
    }
    return result;
  };
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Converts `value` to a string using `Object.prototype.toString`.
 *
 * @private
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 */
function objectToString(value) {
  return nativeObjectToString.call(value);
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to convert.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
  return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
    !propertyIsEnumerable.call(value, 'callee');
};

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * Checks if `value` is a buffer.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
 * @example
 *
 * _.isBuffer(new Buffer(2));
 * // => true
 *
 * _.isBuffer(new Uint8Array(2));
 * // => false
 */
var isBuffer = nativeIsBuffer || stubFalse;

/**
 * Performs a deep comparison between two values to determine if they are
 * equivalent.
 *
 * **Note:** This method supports comparing arrays, array buffers, booleans,
 * date objects, error objects, maps, numbers, `Object` objects, regexes,
 * sets, strings, symbols, and typed arrays. `Object` objects are compared
 * by their own, not inherited, enumerable properties. Functions and DOM
 * nodes are compared by strict equality, i.e. `===`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.isEqual(object, other);
 * // => true
 *
 * object === other;
 * // => false
 */
function isEqual(value, other) {
  return baseIsEqual(value, other);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  if (!isObject(value)) {
    return false;
  }
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 9 which returns 'object' for typed arrays and other constructors.
  var tag = baseGetTag(value);
  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return value != null && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

/**
 * This method returns a new empty array.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {Array} Returns the new empty array.
 * @example
 *
 * var arrays = _.times(2, _.stubArray);
 *
 * console.log(arrays);
 * // => [[], []]
 *
 * console.log(arrays[0] === arrays[1]);
 * // => false
 */
function stubArray() {
  return [];
}

/**
 * This method returns `false`.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {boolean} Returns `false`.
 * @example
 *
 * _.times(2, _.stubFalse);
 * // => [false, false]
 */
function stubFalse() {
  return false;
}

module.exports = isEqual;

/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5), __webpack_require__(12)(module)))

/***/ }),
/* 21 */
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_21__;

/***/ }),
/* 22 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var writeToStore_1 = __webpack_require__(6);
var assign = __webpack_require__(2);
function replaceQueryResults(state, _a, config) {
    var variables = _a.variables, document = _a.document, newResult = _a.newResult;
    var clonedState = assign({}, state);
    return writeToStore_1.writeResultToStore({
        result: newResult,
        dataId: 'ROOT_QUERY',
        variables: variables,
        document: document,
        store: clonedState,
        dataIdFromObject: config.dataIdFromObject,
    });
}
exports.replaceQueryResults = replaceQueryResults;
//# sourceMappingURL=replaceQueryResults.js.map

/***/ }),
/* 23 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var actions_1 = __webpack_require__(7);
var writeToStore_1 = __webpack_require__(6);
var assign = __webpack_require__(2);
var storeUtils_1 = __webpack_require__(3);
var mutationResults_1 = __webpack_require__(41);
var replaceQueryResults_1 = __webpack_require__(22);
function data(previousState, action, queries, mutations, config) {
    if (previousState === void 0) { previousState = {}; }
    var constAction = action;
    if (actions_1.isQueryResultAction(action)) {
        if (!queries[action.queryId]) {
            return previousState;
        }
        if (action.requestId < queries[action.queryId].lastRequestId) {
            return previousState;
        }
        if (!storeUtils_1.graphQLResultHasError(action.result)) {
            var queryStoreValue = queries[action.queryId];
            var clonedState = assign({}, previousState);
            var newState_1 = writeToStore_1.writeResultToStore({
                result: action.result.data,
                dataId: 'ROOT_QUERY',
                document: action.document,
                variables: queryStoreValue.variables,
                store: clonedState,
                dataIdFromObject: config.dataIdFromObject,
            });
            if (action.extraReducers) {
                action.extraReducers.forEach(function (reducer) {
                    newState_1 = reducer(newState_1, constAction);
                });
            }
            return newState_1;
        }
    }
    else if (actions_1.isSubscriptionResultAction(action)) {
        if (!storeUtils_1.graphQLResultHasError(action.result)) {
            var clonedState = assign({}, previousState);
            var newState_2 = writeToStore_1.writeResultToStore({
                result: action.result.data,
                dataId: 'ROOT_QUERY',
                document: action.document,
                variables: action.variables,
                store: clonedState,
                dataIdFromObject: config.dataIdFromObject,
            });
            if (action.extraReducers) {
                action.extraReducers.forEach(function (reducer) {
                    newState_2 = reducer(newState_2, constAction);
                });
            }
            return newState_2;
        }
    }
    else if (actions_1.isMutationResultAction(constAction)) {
        if (!constAction.result.errors) {
            var queryStoreValue_1 = mutations[constAction.mutationId];
            var clonedState = assign({}, previousState);
            var newState_3 = writeToStore_1.writeResultToStore({
                result: constAction.result.data,
                dataId: 'ROOT_MUTATION',
                document: constAction.document,
                variables: queryStoreValue_1.variables,
                store: clonedState,
                dataIdFromObject: config.dataIdFromObject,
            });
            if (constAction.resultBehaviors) {
                constAction.resultBehaviors.forEach(function (behavior) {
                    var args = {
                        behavior: behavior,
                        result: constAction.result,
                        variables: queryStoreValue_1.variables,
                        document: constAction.document,
                        config: config,
                    };
                    if (mutationResults_1.defaultMutationBehaviorReducers[behavior.type]) {
                        newState_3 = mutationResults_1.defaultMutationBehaviorReducers[behavior.type](newState_3, args);
                    }
                    else if (config.mutationBehaviorReducers[behavior.type]) {
                        newState_3 = config.mutationBehaviorReducers[behavior.type](newState_3, args);
                    }
                    else {
                        throw new Error("No mutation result reducer defined for type " + behavior.type);
                    }
                });
            }
            if (constAction.extraReducers) {
                constAction.extraReducers.forEach(function (reducer) {
                    newState_3 = reducer(newState_3, constAction);
                });
            }
            return newState_3;
        }
    }
    else if (actions_1.isUpdateQueryResultAction(constAction)) {
        return replaceQueryResults_1.replaceQueryResults(previousState, constAction, config);
    }
    else if (actions_1.isStoreResetAction(action)) {
        return {};
    }
    return previousState;
}
exports.data = data;
//# sourceMappingURL=store.js.map

/***/ }),
/* 24 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var flatten = __webpack_require__(112);
var getFromAST_1 = __webpack_require__(4);
exports.fragmentDefinitionsMap = {};
var printFragmentWarnings = true;
function createFragment(doc, fragments) {
    if (fragments === void 0) { fragments = []; }
    fragments = flatten(fragments);
    var fragmentDefinitions = getFromAST_1.getFragmentDefinitions(doc);
    fragmentDefinitions.forEach(function (fragmentDefinition) {
        var fragmentName = fragmentDefinition.name.value;
        if (exports.fragmentDefinitionsMap.hasOwnProperty(fragmentName) &&
            exports.fragmentDefinitionsMap[fragmentName].indexOf(fragmentDefinition) === -1) {
            if (printFragmentWarnings) {
                console.warn("Warning: fragment with name " + fragmentDefinition.name.value + " already exists.\nApollo Client enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://docs.apollostack.com/");
            }
            exports.fragmentDefinitionsMap[fragmentName].push(fragmentDefinition);
        }
        else if (!exports.fragmentDefinitionsMap.hasOwnProperty(fragmentName)) {
            exports.fragmentDefinitionsMap[fragmentName] = [fragmentDefinition];
        }
    });
    return fragments.concat(fragmentDefinitions);
}
exports.createFragment = createFragment;
function disableFragmentWarnings() {
    printFragmentWarnings = false;
}
exports.disableFragmentWarnings = disableFragmentWarnings;
function enableFragmentWarnings() {
    printFragmentWarnings = true;
}
exports.enableFragmentWarnings = enableFragmentWarnings;
function clearFragmentDefinitions() {
    exports.fragmentDefinitionsMap = {};
}
exports.clearFragmentDefinitions = clearFragmentDefinitions;
//# sourceMappingURL=fragments.js.map

/***/ }),
/* 25 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var symbol_observable_1 = __webpack_require__(39);
function isSubscription(subscription) {
    return subscription.unsubscribe !== undefined;
}
var Observable = (function () {
    function Observable(subscriberFunction) {
        this.subscriberFunction = subscriberFunction;
    }
    Observable.prototype[symbol_observable_1.default] = function () {
        return this;
    };
    Observable.prototype.subscribe = function (observer) {
        var subscriptionOrCleanupFunction = this.subscriberFunction(observer);
        if (isSubscription(subscriptionOrCleanupFunction)) {
            return subscriptionOrCleanupFunction;
        }
        else {
            return {
                unsubscribe: subscriptionOrCleanupFunction,
            };
        }
    };
    return Observable;
}());
exports.Observable = Observable;
//# sourceMappingURL=Observable.js.map

/***/ }),
/* 26 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

function tryFunctionOrLogError(f) {
    try {
        return f();
    }
    catch (e) {
        if (console.error) {
            console.error(e);
        }
    }
}
exports.tryFunctionOrLogError = tryFunctionOrLogError;
//# sourceMappingURL=errorHandling.js.map

/***/ }),
/* 27 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var getFromAST_1 = __webpack_require__(98);
var directives_1 = __webpack_require__(97);
var storeUtils_1 = __webpack_require__(99);
var utilities_1 = __webpack_require__(100);
exports.filter = utilities_1.filter;
exports.check = utilities_1.check;
exports.propType = utilities_1.propType;
function graphql(resolver, document, rootValue, contextValue, variableValues, execOptions) {
    if (execOptions === void 0) { execOptions = {}; }
    var mainDefinition = getFromAST_1.getMainDefinition(document);
    var fragments = getFromAST_1.getFragmentDefinitions(document);
    var fragmentMap = getFromAST_1.createFragmentMap(fragments) || {};
    var resultMapper = execOptions.resultMapper;
    var fragmentMatcher = execOptions.fragmentMatcher || (function () { return true; });
    var execContext = {
        fragmentMap: fragmentMap,
        contextValue: contextValue,
        variableValues: variableValues,
        resultMapper: resultMapper,
        resolver: resolver,
        fragmentMatcher: fragmentMatcher,
    };
    return executeSelectionSet(mainDefinition.selectionSet, rootValue, execContext);
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = graphql;
function executeSelectionSet(selectionSet, rootValue, execContext) {
    var fragmentMap = execContext.fragmentMap, contextValue = execContext.contextValue, variables = execContext.variableValues;
    var result = {};
    selectionSet.selections.forEach(function (selection) {
        if (!directives_1.shouldInclude(selection, variables)) {
            return;
        }
        if (storeUtils_1.isField(selection)) {
            var fieldResult = executeField(selection, rootValue, execContext);
            var resultFieldKey = storeUtils_1.resultKeyNameFromField(selection);
            if (fieldResult !== undefined) {
                result[resultFieldKey] = fieldResult;
            }
        }
        else {
            var fragment = void 0;
            if (storeUtils_1.isInlineFragment(selection)) {
                fragment = selection;
            }
            else {
                fragment = fragmentMap[selection.name.value];
                if (!fragment) {
                    throw new Error("No fragment named " + selection.name.value);
                }
            }
            var typeCondition = fragment.typeCondition.name.value;
            if (execContext.fragmentMatcher(rootValue, typeCondition, contextValue)) {
                var fragmentResult = executeSelectionSet(fragment.selectionSet, rootValue, execContext);
                merge(result, fragmentResult);
            }
        }
    });
    if (execContext.resultMapper) {
        return execContext.resultMapper(result, rootValue);
    }
    return result;
}
function executeField(field, rootValue, execContext) {
    var variables = execContext.variableValues, contextValue = execContext.contextValue, resolver = execContext.resolver;
    var fieldName = field.name.value;
    var args = storeUtils_1.argumentsObjectFromField(field, variables);
    var info = {
        isLeaf: !field.selectionSet,
        resultKey: storeUtils_1.resultKeyNameFromField(field),
    };
    var result = resolver(fieldName, rootValue, args, contextValue, info);
    if (!field.selectionSet) {
        return result;
    }
    if (result === null || typeof result === 'undefined') {
        return result;
    }
    if (Array.isArray(result)) {
        return executeSubSelectedArray(field, result, execContext);
    }
    return executeSelectionSet(field.selectionSet, result, execContext);
}
function executeSubSelectedArray(field, result, execContext) {
    return result.map(function (item) {
        if (item === null) {
            return null;
        }
        if (Array.isArray(item)) {
            return executeSubSelectedArray(field, item, execContext);
        }
        return executeSelectionSet(field.selectionSet, item, execContext);
    });
}
function merge(dest, src) {
    if (src === null ||
        typeof src === 'undefined' ||
        typeof src === 'string' ||
        typeof src === 'number' ||
        typeof src === 'boolean' ||
        Array.isArray(src)) {
        return src;
    }
    Object.keys(dest).forEach(function (destKey) {
        if (src.hasOwnProperty(destKey)) {
            merge(dest[destKey], src[destKey]);
        }
    });
    Object.keys(src).forEach(function (srcKey) {
        if (!dest.hasOwnProperty(srcKey)) {
            dest[srcKey] = src[srcKey];
        }
    });
}
//# sourceMappingURL=index.js.map

/***/ }),
/* 28 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__root_js__ = __webpack_require__(109);


/** Built-in value references. */
var Symbol = __WEBPACK_IMPORTED_MODULE_0__root_js__["a" /* default */].Symbol;

/* harmony default export */ __webpack_exports__["a"] = (Symbol);


/***/ }),
/* 29 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__baseGetTag_js__ = __webpack_require__(103);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__getPrototype_js__ = __webpack_require__(105);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__isObjectLike_js__ = __webpack_require__(110);




/** `Object#toString` result references. */
var objectTag = '[object Object]';

/** Used for built-in method references. */
var funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to infer the `Object` constructor. */
var objectCtorString = funcToString.call(Object);

/**
 * Checks if `value` is a plain object, that is, an object created by the
 * `Object` constructor or one with a `[[Prototype]]` of `null`.
 *
 * @static
 * @memberOf _
 * @since 0.8.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 * }
 *
 * _.isPlainObject(new Foo);
 * // => false
 *
 * _.isPlainObject([1, 2, 3]);
 * // => false
 *
 * _.isPlainObject({ 'x': 0, 'y': 0 });
 * // => true
 *
 * _.isPlainObject(Object.create(null));
 * // => true
 */
function isPlainObject(value) {
  if (!__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__isObjectLike_js__["a" /* default */])(value) || __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__baseGetTag_js__["a" /* default */])(value) != objectTag) {
    return false;
  }
  var proto = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__getPrototype_js__["a" /* default */])(value);
  if (proto === null) {
    return true;
  }
  var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
  return typeof Ctor == 'function' && Ctor instanceof Ctor &&
    funcToString.call(Ctor) == objectCtorString;
}

/* harmony default export */ __webpack_exports__["a"] = (isPlainObject);


/***/ }),
/* 30 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global, module) {/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to match `RegExp` flags from their coerced string values. */
var reFlags = /\w*$/;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/** Used to identify `toStringTag` values supported by `_.clone`. */
var cloneableTags = {};
cloneableTags[argsTag] = cloneableTags[arrayTag] =
cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
cloneableTags[boolTag] = cloneableTags[dateTag] =
cloneableTags[float32Tag] = cloneableTags[float64Tag] =
cloneableTags[int8Tag] = cloneableTags[int16Tag] =
cloneableTags[int32Tag] = cloneableTags[mapTag] =
cloneableTags[numberTag] = cloneableTags[objectTag] =
cloneableTags[regexpTag] = cloneableTags[setTag] =
cloneableTags[stringTag] = cloneableTags[symbolTag] =
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
cloneableTags[errorTag] = cloneableTags[funcTag] =
cloneableTags[weakMapTag] = false;

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/**
 * Adds the key-value `pair` to `map`.
 *
 * @private
 * @param {Object} map The map to modify.
 * @param {Array} pair The key-value pair to add.
 * @returns {Object} Returns `map`.
 */
function addMapEntry(map, pair) {
  // Don't return `map.set` because it's not chainable in IE 11.
  map.set(pair[0], pair[1]);
  return map;
}

/**
 * Adds `value` to `set`.
 *
 * @private
 * @param {Object} set The set to modify.
 * @param {*} value The value to add.
 * @returns {Object} Returns `set`.
 */
function addSetEntry(set, value) {
  // Don't return `set.add` because it's not chainable in IE 11.
  set.add(value);
  return set;
}

/**
 * A specialized version of `_.forEach` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns `array`.
 */
function arrayEach(array, iteratee) {
  var index = -1,
      length = array ? array.length : 0;

  while (++index < length) {
    if (iteratee(array[index], index, array) === false) {
      break;
    }
  }
  return array;
}

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

/**
 * A specialized version of `_.reduce` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {*} [accumulator] The initial value.
 * @param {boolean} [initAccum] Specify using the first element of `array` as
 *  the initial value.
 * @returns {*} Returns the accumulated value.
 */
function arrayReduce(array, iteratee, accumulator, initAccum) {
  var index = -1,
      length = array ? array.length : 0;

  if (initAccum && length) {
    accumulator = array[++index];
  }
  while (++index < length) {
    accumulator = iteratee(accumulator, array[index], index, array);
  }
  return accumulator;
}

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Checks if `value` is a host object in IE < 9.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
 */
function isHostObject(value) {
  // Many host objects are `Object` objects that can coerce to strings
  // despite having improperly defined `toString` methods.
  var result = false;
  if (value != null && typeof value.toString != 'function') {
    try {
      result = !!(value + '');
    } catch (e) {}
  }
  return result;
}

/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function(value, key) {
    result[++index] = [key, value];
  });
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/** Built-in value references. */
var Buffer = moduleExports ? root.Buffer : undefined,
    Symbol = root.Symbol,
    Uint8Array = root.Uint8Array,
    getPrototype = overArg(Object.getPrototypeOf, Object),
    objectCreate = Object.create,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    splice = arrayProto.splice;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols,
    nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
    nativeKeys = overArg(Object.keys, Object);

/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView'),
    Map = getNative(root, 'Map'),
    Promise = getNative(root, 'Promise'),
    Set = getNative(root, 'Set'),
    WeakMap = getNative(root, 'WeakMap'),
    nativeCreate = getNative(Object, 'create');

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
    mapCtorString = toSource(Map),
    promiseCtorString = toSource(Promise),
    setCtorString = toSource(Set),
    weakMapCtorString = toSource(WeakMap);

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  return this.has(key) && delete this.__data__[key];
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.__data__ = {
    'hash': new Hash,
    'map': new (Map || ListCache),
    'string': new Hash
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  return getMapData(this, key)['delete'](key);
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  getMapData(this, key).set(key, value);
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  this.__data__ = new ListCache(entries);
}

/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new ListCache;
}

/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  return this.__data__['delete'](key);
}

/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var cache = this.__data__;
  if (cache instanceof ListCache) {
    var pairs = cache.__data__;
    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
      pairs.push([key, value]);
      return this;
    }
    cache = this.__data__ = new MapCache(pairs);
  }
  cache.set(key, value);
  return this;
}

// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  // Safari 9 makes `arguments.length` enumerable in strict mode.
  var result = (isArray(value) || isArguments(value))
    ? baseTimes(value.length, String)
    : [];

  var length = result.length,
      skipIndexes = !!length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * Assigns `value` to `key` of `object` if the existing value is not equivalent
 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * for equality comparisons.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function assignValue(object, key, value) {
  var objValue = object[key];
  if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
      (value === undefined && !(key in object))) {
    object[key] = value;
  }
}

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * The base implementation of `_.assign` without support for multiple sources
 * or `customizer` functions.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @returns {Object} Returns `object`.
 */
function baseAssign(object, source) {
  return object && copyObject(source, keys(source), object);
}

/**
 * The base implementation of `_.clone` and `_.cloneDeep` which tracks
 * traversed objects.
 *
 * @private
 * @param {*} value The value to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @param {boolean} [isFull] Specify a clone including symbols.
 * @param {Function} [customizer] The function to customize cloning.
 * @param {string} [key] The key of `value`.
 * @param {Object} [object] The parent object of `value`.
 * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
 * @returns {*} Returns the cloned value.
 */
function baseClone(value, isDeep, isFull, customizer, key, object, stack) {
  var result;
  if (customizer) {
    result = object ? customizer(value, key, object, stack) : customizer(value);
  }
  if (result !== undefined) {
    return result;
  }
  if (!isObject(value)) {
    return value;
  }
  var isArr = isArray(value);
  if (isArr) {
    result = initCloneArray(value);
    if (!isDeep) {
      return copyArray(value, result);
    }
  } else {
    var tag = getTag(value),
        isFunc = tag == funcTag || tag == genTag;

    if (isBuffer(value)) {
      return cloneBuffer(value, isDeep);
    }
    if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
      if (isHostObject(value)) {
        return object ? value : {};
      }
      result = initCloneObject(isFunc ? {} : value);
      if (!isDeep) {
        return copySymbols(value, baseAssign(result, value));
      }
    } else {
      if (!cloneableTags[tag]) {
        return object ? value : {};
      }
      result = initCloneByTag(value, tag, baseClone, isDeep);
    }
  }
  // Check for circular references and return its corresponding clone.
  stack || (stack = new Stack);
  var stacked = stack.get(value);
  if (stacked) {
    return stacked;
  }
  stack.set(value, result);

  if (!isArr) {
    var props = isFull ? getAllKeys(value) : keys(value);
  }
  arrayEach(props || value, function(subValue, key) {
    if (props) {
      key = subValue;
      subValue = value[key];
    }
    // Recursively populate clone (susceptible to call stack limits).
    assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack));
  });
  return result;
}

/**
 * The base implementation of `_.create` without support for assigning
 * properties to the created object.
 *
 * @private
 * @param {Object} prototype The object to inherit from.
 * @returns {Object} Returns the new object.
 */
function baseCreate(proto) {
  return isObject(proto) ? objectCreate(proto) : {};
}

/**
 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
 * symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @param {Function} symbolsFunc The function to get the symbols of `object`.
 * @returns {Array} Returns the array of property names and symbols.
 */
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
  var result = keysFunc(object);
  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}

/**
 * The base implementation of `getTag`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  return objectToString.call(value);
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * Creates a clone of  `buffer`.
 *
 * @private
 * @param {Buffer} buffer The buffer to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Buffer} Returns the cloned buffer.
 */
function cloneBuffer(buffer, isDeep) {
  if (isDeep) {
    return buffer.slice();
  }
  var result = new buffer.constructor(buffer.length);
  buffer.copy(result);
  return result;
}

/**
 * Creates a clone of `arrayBuffer`.
 *
 * @private
 * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
 * @returns {ArrayBuffer} Returns the cloned array buffer.
 */
function cloneArrayBuffer(arrayBuffer) {
  var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
  new Uint8Array(result).set(new Uint8Array(arrayBuffer));
  return result;
}

/**
 * Creates a clone of `dataView`.
 *
 * @private
 * @param {Object} dataView The data view to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned data view.
 */
function cloneDataView(dataView, isDeep) {
  var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
  return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
}

/**
 * Creates a clone of `map`.
 *
 * @private
 * @param {Object} map The map to clone.
 * @param {Function} cloneFunc The function to clone values.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned map.
 */
function cloneMap(map, isDeep, cloneFunc) {
  var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map);
  return arrayReduce(array, addMapEntry, new map.constructor);
}

/**
 * Creates a clone of `regexp`.
 *
 * @private
 * @param {Object} regexp The regexp to clone.
 * @returns {Object} Returns the cloned regexp.
 */
function cloneRegExp(regexp) {
  var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
  result.lastIndex = regexp.lastIndex;
  return result;
}

/**
 * Creates a clone of `set`.
 *
 * @private
 * @param {Object} set The set to clone.
 * @param {Function} cloneFunc The function to clone values.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned set.
 */
function cloneSet(set, isDeep, cloneFunc) {
  var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set);
  return arrayReduce(array, addSetEntry, new set.constructor);
}

/**
 * Creates a clone of the `symbol` object.
 *
 * @private
 * @param {Object} symbol The symbol object to clone.
 * @returns {Object} Returns the cloned symbol object.
 */
function cloneSymbol(symbol) {
  return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
}

/**
 * Creates a clone of `typedArray`.
 *
 * @private
 * @param {Object} typedArray The typed array to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned typed array.
 */
function cloneTypedArray(typedArray, isDeep) {
  var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
  return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
}

/**
 * Copies the values of `source` to `array`.
 *
 * @private
 * @param {Array} source The array to copy values from.
 * @param {Array} [array=[]] The array to copy values to.
 * @returns {Array} Returns `array`.
 */
function copyArray(source, array) {
  var index = -1,
      length = source.length;

  array || (array = Array(length));
  while (++index < length) {
    array[index] = source[index];
  }
  return array;
}

/**
 * Copies properties of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy properties from.
 * @param {Array} props The property identifiers to copy.
 * @param {Object} [object={}] The object to copy properties to.
 * @param {Function} [customizer] The function to customize copied values.
 * @returns {Object} Returns `object`.
 */
function copyObject(source, props, object, customizer) {
  object || (object = {});

  var index = -1,
      length = props.length;

  while (++index < length) {
    var key = props[index];

    var newValue = customizer
      ? customizer(object[key], source[key], key, object, source)
      : undefined;

    assignValue(object, key, newValue === undefined ? source[key] : newValue);
  }
  return object;
}

/**
 * Copies own symbol properties of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy symbols from.
 * @param {Object} [object={}] The object to copy symbols to.
 * @returns {Object} Returns `object`.
 */
function copySymbols(source, object) {
  return copyObject(source, getSymbols(source), object);
}

/**
 * Creates an array of own enumerable property names and symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names and symbols.
 */
function getAllKeys(object) {
  return baseGetAllKeys(object, keys, getSymbols);
}

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * Creates an array of the own enumerable symbol properties of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of symbols.
 */
var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = baseGetTag;

// Fallback for data views, maps, sets, and weak maps in IE 11,
// for data views in Edge < 14, and promises in Node.js.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
    (Map && getTag(new Map) != mapTag) ||
    (Promise && getTag(Promise.resolve()) != promiseTag) ||
    (Set && getTag(new Set) != setTag) ||
    (WeakMap && getTag(new WeakMap) != weakMapTag)) {
  getTag = function(value) {
    var result = objectToString.call(value),
        Ctor = result == objectTag ? value.constructor : undefined,
        ctorString = Ctor ? toSource(Ctor) : undefined;

    if (ctorString) {
      switch (ctorString) {
        case dataViewCtorString: return dataViewTag;
        case mapCtorString: return mapTag;
        case promiseCtorString: return promiseTag;
        case setCtorString: return setTag;
        case weakMapCtorString: return weakMapTag;
      }
    }
    return result;
  };
}

/**
 * Initializes an array clone.
 *
 * @private
 * @param {Array} array The array to clone.
 * @returns {Array} Returns the initialized clone.
 */
function initCloneArray(array) {
  var length = array.length,
      result = array.constructor(length);

  // Add properties assigned by `RegExp#exec`.
  if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
    result.index = array.index;
    result.input = array.input;
  }
  return result;
}

/**
 * Initializes an object clone.
 *
 * @private
 * @param {Object} object The object to clone.
 * @returns {Object} Returns the initialized clone.
 */
function initCloneObject(object) {
  return (typeof object.constructor == 'function' && !isPrototype(object))
    ? baseCreate(getPrototype(object))
    : {};
}

/**
 * Initializes an object clone based on its `toStringTag`.
 *
 * **Note:** This function only supports cloning values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to clone.
 * @param {string} tag The `toStringTag` of the object to clone.
 * @param {Function} cloneFunc The function to clone values.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the initialized clone.
 */
function initCloneByTag(object, tag, cloneFunc, isDeep) {
  var Ctor = object.constructor;
  switch (tag) {
    case arrayBufferTag:
      return cloneArrayBuffer(object);

    case boolTag:
    case dateTag:
      return new Ctor(+object);

    case dataViewTag:
      return cloneDataView(object, isDeep);

    case float32Tag: case float64Tag:
    case int8Tag: case int16Tag: case int32Tag:
    case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
      return cloneTypedArray(object, isDeep);

    case mapTag:
      return cloneMap(object, isDeep, cloneFunc);

    case numberTag:
    case stringTag:
      return new Ctor(object);

    case regexpTag:
      return cloneRegExp(object);

    case setTag:
      return cloneSet(object, isDeep, cloneFunc);

    case symbolTag:
      return cloneSymbol(object);
  }
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to process.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/**
 * This method is like `_.clone` except that it recursively clones `value`.
 *
 * @static
 * @memberOf _
 * @since 1.0.0
 * @category Lang
 * @param {*} value The value to recursively clone.
 * @returns {*} Returns the deep cloned value.
 * @see _.clone
 * @example
 *
 * var objects = [{ 'a': 1 }, { 'b': 2 }];
 *
 * var deep = _.cloneDeep(objects);
 * console.log(deep[0] === objects[0]);
 * // => false
 */
function cloneDeep(value) {
  return baseClone(value, true, true);
}

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

/**
 * Checks if `value` is a buffer.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
 * @example
 *
 * _.isBuffer(new Buffer(2));
 * // => true
 *
 * _.isBuffer(new Uint8Array(2));
 * // => false
 */
var isBuffer = nativeIsBuffer || stubFalse;

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

/**
 * This method returns a new empty array.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {Array} Returns the new empty array.
 * @example
 *
 * var arrays = _.times(2, _.stubArray);
 *
 * console.log(arrays);
 * // => [[], []]
 *
 * console.log(arrays[0] === arrays[1]);
 * // => false
 */
function stubArray() {
  return [];
}

/**
 * This method returns `false`.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {boolean} Returns `false`.
 * @example
 *
 * _.times(2, _.stubFalse);
 * // => [false, false]
 */
function stubFalse() {
  return false;
}

module.exports = cloneDeep;

/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5), __webpack_require__(12)(module)))

/***/ }),
/* 31 */
/***/ (function(module, exports) {

/**
 * lodash 3.0.3 (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 * Available under MIT license <https://lodash.com/license>
 */

/** `Object#toString` result references. */
var numberTag = '[object Number]';

/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a `Number` primitive or object.
 *
 * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
 * as numbers, use the `_.isFinite` method.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isNumber(3);
 * // => true
 *
 * _.isNumber(Number.MIN_VALUE);
 * // => true
 *
 * _.isNumber(Infinity);
 * // => true
 *
 * _.isNumber('3');
 * // => false
 */
function isNumber(value) {
  return typeof value == 'number' ||
    (isObjectLike(value) && objectToString.call(value) == numberTag);
}

module.exports = isNumber;


/***/ }),
/* 32 */
/***/ (function(module, exports) {

/**
 * lodash 3.0.2 (Custom Build) <https://lodash.com/>
 * Build: `lodash modern modularize exports="npm" -o ./`
 * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 * Available under MIT license <https://lodash.com/license>
 */

/**
 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(1);
 * // => false
 */
function isObject(value) {
  // Avoid a V8 JIT bug in Chrome 19-20.
  // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

module.exports = isObject;


/***/ }),
/* 33 */
/***/ (function(module, exports) {

/**
 * lodash 4.0.1 (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 * Available under MIT license <https://lodash.com/license>
 */

/** `Object#toString` result references. */
var stringTag = '[object String]';

/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @type Function
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a `String` primitive or object.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
 * @example
 *
 * _.isString('abc');
 * // => true
 *
 * _.isString(1);
 * // => false
 */
function isString(value) {
  return typeof value == 'string' ||
    (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
}

module.exports = isString;


/***/ }),
/* 34 */
/***/ (function(module, exports) {

/**
 * lodash 3.0.1 (Custom Build) <https://lodash.com/>
 * Build: `lodash modern modularize exports="npm" -o ./`
 * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 * Available under MIT license <https://lodash.com/license>
 */

/**
 * Checks if `value` is `undefined`.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
 * @example
 *
 * _.isUndefined(void 0);
 * // => true
 *
 * _.isUndefined(null);
 * // => false
 */
function isUndefined(value) {
  return value === undefined;
}

module.exports = isUndefined;


/***/ }),
/* 35 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global, module) {/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used to compose bitmasks for comparison styles. */
var UNORDERED_COMPARE_FLAG = 1,
    PARTIAL_COMPARE_FLAG = 2;

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0,
    MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
    reIsPlainProp = /^\w*$/,
    reLeadingDot = /^\./,
    rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && freeGlobal.process;

/** Used to access faster Node.js helpers. */
var nodeUtil = (function() {
  try {
    return freeProcess && freeProcess.binding('util');
  } catch (e) {}
}());

/* Node.js helper references. */
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

/**
 * A specialized version of `_.some` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array ? array.length : 0;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

/**
 * The base implementation of `_.property` without support for deep paths.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function baseProperty(key) {
  return function(object) {
    return object == null ? undefined : object[key];
  };
}

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * The base implementation of `_.unary` without support for storing metadata.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @returns {Function} Returns the new capped function.
 */
function baseUnary(func) {
  return function(value) {
    return func(value);
  };
}

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Checks if `value` is a host object in IE < 9.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
 */
function isHostObject(value) {
  // Many host objects are `Object` objects that can coerce to strings
  // despite having improperly defined `toString` methods.
  var result = false;
  if (value != null && typeof value.toString != 'function') {
    try {
      result = !!(value + '');
    } catch (e) {}
  }
  return result;
}

/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function(value, key) {
    result[++index] = [key, value];
  });
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/** Built-in value references. */
var Symbol = root.Symbol,
    Uint8Array = root.Uint8Array,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    splice = arrayProto.splice;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeKeys = overArg(Object.keys, Object);

/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView'),
    Map = getNative(root, 'Map'),
    Promise = getNative(root, 'Promise'),
    Set = getNative(root, 'Set'),
    WeakMap = getNative(root, 'WeakMap'),
    nativeCreate = getNative(Object, 'create');

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
    mapCtorString = toSource(Map),
    promiseCtorString = toSource(Promise),
    setCtorString = toSource(Set),
    weakMapCtorString = toSource(WeakMap);

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
    symbolToString = symbolProto ? symbolProto.toString : undefined;

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  return this.has(key) && delete this.__data__[key];
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.__data__ = {
    'hash': new Hash,
    'map': new (Map || ListCache),
    'string': new Hash
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  return getMapData(this, key)['delete'](key);
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  getMapData(this, key).set(key, value);
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
  var index = -1,
      length = values ? values.length : 0;

  this.__data__ = new MapCache;
  while (++index < length) {
    this.add(values[index]);
  }
}

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;

/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  this.__data__ = new ListCache(entries);
}

/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new ListCache;
}

/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  return this.__data__['delete'](key);
}

/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var cache = this.__data__;
  if (cache instanceof ListCache) {
    var pairs = cache.__data__;
    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
      pairs.push([key, value]);
      return this;
    }
    cache = this.__data__ = new MapCache(pairs);
  }
  cache.set(key, value);
  return this;
}

// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  // Safari 9 makes `arguments.length` enumerable in strict mode.
  var result = (isArray(value) || isArguments(value))
    ? baseTimes(value.length, String)
    : [];

  var length = result.length,
      skipIndexes = !!length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * The base implementation of `baseForOwn` which iterates over `object`
 * properties returned by `keysFunc` and invokes `iteratee` for each property.
 * Iteratee functions may exit iteration early by explicitly returning `false`.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @returns {Object} Returns `object`.
 */
var baseFor = createBaseFor();

/**
 * The base implementation of `_.forOwn` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function baseForOwn(object, iteratee) {
  return object && baseFor(object, iteratee, keys);
}

/**
 * The base implementation of `_.get` without support for default values.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @returns {*} Returns the resolved value.
 */
function baseGet(object, path) {
  path = isKey(path, object) ? [path] : castPath(path);

  var index = 0,
      length = path.length;

  while (object != null && index < length) {
    object = object[toKey(path[index++])];
  }
  return (index && index == length) ? object : undefined;
}

/**
 * The base implementation of `getTag`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  return objectToString.call(value);
}

/**
 * The base implementation of `_.hasIn` without support for deep paths.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {Array|string} key The key to check.
 * @returns {boolean} Returns `true` if `key` exists, else `false`.
 */
function baseHasIn(object, key) {
  return object != null && key in Object(object);
}

/**
 * The base implementation of `_.isEqual` which supports partial comparisons
 * and tracks traversed objects.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {boolean} [bitmask] The bitmask of comparison flags.
 *  The bitmask may be composed of the following flags:
 *     1 - Unordered comparison
 *     2 - Partial comparison
 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, customizer, bitmask, stack) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
    return value !== value && other !== other;
  }
  return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
}

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
  var objIsArr = isArray(object),
      othIsArr = isArray(other),
      objTag = arrayTag,
      othTag = arrayTag;

  if (!objIsArr) {
    objTag = getTag(object);
    objTag = objTag == argsTag ? objectTag : objTag;
  }
  if (!othIsArr) {
    othTag = getTag(other);
    othTag = othTag == argsTag ? objectTag : othTag;
  }
  var objIsObj = objTag == objectTag && !isHostObject(object),
      othIsObj = othTag == objectTag && !isHostObject(other),
      isSameTag = objTag == othTag;

  if (isSameTag && !objIsObj) {
    stack || (stack = new Stack);
    return (objIsArr || isTypedArray(object))
      ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
      : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
  }
  if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      var objUnwrapped = objIsWrapped ? object.value() : object,
          othUnwrapped = othIsWrapped ? other.value() : other;

      stack || (stack = new Stack);
      return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
    }
  }
  if (!isSameTag) {
    return false;
  }
  stack || (stack = new Stack);
  return equalObjects(object, other, equalFunc, customizer, bitmask, stack);
}

/**
 * The base implementation of `_.isMatch` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to inspect.
 * @param {Object} source The object of property values to match.
 * @param {Array} matchData The property names, values, and compare flags to match.
 * @param {Function} [customizer] The function to customize comparisons.
 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
 */
function baseIsMatch(object, source, matchData, customizer) {
  var index = matchData.length,
      length = index,
      noCustomizer = !customizer;

  if (object == null) {
    return !length;
  }
  object = Object(object);
  while (index--) {
    var data = matchData[index];
    if ((noCustomizer && data[2])
          ? data[1] !== object[data[0]]
          : !(data[0] in object)
        ) {
      return false;
    }
  }
  while (++index < length) {
    data = matchData[index];
    var key = data[0],
        objValue = object[key],
        srcValue = data[1];

    if (noCustomizer && data[2]) {
      if (objValue === undefined && !(key in object)) {
        return false;
      }
    } else {
      var stack = new Stack;
      if (customizer) {
        var result = customizer(objValue, srcValue, key, object, source, stack);
      }
      if (!(result === undefined
            ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
            : result
          )) {
        return false;
      }
    }
  }
  return true;
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 */
function baseIsTypedArray(value) {
  return isObjectLike(value) &&
    isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
}

/**
 * The base implementation of `_.iteratee`.
 *
 * @private
 * @param {*} [value=_.identity] The value to convert to an iteratee.
 * @returns {Function} Returns the iteratee.
 */
function baseIteratee(value) {
  // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
  // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
  if (typeof value == 'function') {
    return value;
  }
  if (value == null) {
    return identity;
  }
  if (typeof value == 'object') {
    return isArray(value)
      ? baseMatchesProperty(value[0], value[1])
      : baseMatches(value);
  }
  return property(value);
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * The base implementation of `_.matches` which doesn't clone `source`.
 *
 * @private
 * @param {Object} source The object of property values to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatches(source) {
  var matchData = getMatchData(source);
  if (matchData.length == 1 && matchData[0][2]) {
    return matchesStrictComparable(matchData[0][0], matchData[0][1]);
  }
  return function(object) {
    return object === source || baseIsMatch(object, source, matchData);
  };
}

/**
 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
 *
 * @private
 * @param {string} path The path of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatchesProperty(path, srcValue) {
  if (isKey(path) && isStrictComparable(srcValue)) {
    return matchesStrictComparable(toKey(path), srcValue);
  }
  return function(object) {
    var objValue = get(object, path);
    return (objValue === undefined && objValue === srcValue)
      ? hasIn(object, path)
      : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
  };
}

/**
 * A specialized version of `baseProperty` which supports deep paths.
 *
 * @private
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function basePropertyDeep(path) {
  return function(object) {
    return baseGet(object, path);
  };
}

/**
 * The base implementation of `_.toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value;
  }
  if (isSymbol(value)) {
    return symbolToString ? symbolToString.call(value) : '';
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/**
 * Casts `value` to a path array if it's not one.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {Array} Returns the cast property path array.
 */
function castPath(value) {
  return isArray(value) ? value : stringToPath(value);
}

/**
 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
 *
 * @private
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseFor(fromRight) {
  return function(object, iteratee, keysFunc) {
    var index = -1,
        iterable = Object(object),
        props = keysFunc(object),
        length = props.length;

    while (length--) {
      var key = props[fromRight ? length : ++index];
      if (iteratee(iterable[key], key, iterable) === false) {
        break;
      }
    }
    return object;
  };
}

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} customizer The function to customize comparisons.
 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} stack Tracks traversed `array` and `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
  var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
    return false;
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(array);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var index = -1,
      result = true,
      seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined;

  stack.set(array, other);
  stack.set(other, array);

  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, arrValue, index, other, array, stack)
        : customizer(arrValue, othValue, index, array, other, stack);
    }
    if (compared !== undefined) {
      if (compared) {
        continue;
      }
      result = false;
      break;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (seen) {
      if (!arraySome(other, function(othValue, othIndex) {
            if (!seen.has(othIndex) &&
                (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
              return seen.add(othIndex);
            }
          })) {
        result = false;
        break;
      }
    } else if (!(
          arrValue === othValue ||
            equalFunc(arrValue, othValue, customizer, bitmask, stack)
        )) {
      result = false;
      break;
    }
  }
  stack['delete'](array);
  stack['delete'](other);
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} customizer The function to customize comparisons.
 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {
  switch (tag) {
    case dataViewTag:
      if ((object.byteLength != other.byteLength) ||
          (object.byteOffset != other.byteOffset)) {
        return false;
      }
      object = object.buffer;
      other = other.buffer;

    case arrayBufferTag:
      if ((object.byteLength != other.byteLength) ||
          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
        return false;
      }
      return true;

    case boolTag:
    case dateTag:
    case numberTag:
      // Coerce booleans to `1` or `0` and dates to milliseconds.
      // Invalid dates are coerced to `NaN`.
      return eq(+object, +other);

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings, primitives and objects,
      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
      // for more details.
      return object == (other + '');

    case mapTag:
      var convert = mapToArray;

    case setTag:
      var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
      convert || (convert = setToArray);

      if (object.size != other.size && !isPartial) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked) {
        return stacked == other;
      }
      bitmask |= UNORDERED_COMPARE_FLAG;

      // Recursively compare objects (susceptible to call stack limits).
      stack.set(object, other);
      var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);
      stack['delete'](object);
      return result;

    case symbolTag:
      if (symbolValueOf) {
        return symbolValueOf.call(object) == symbolValueOf.call(other);
      }
  }
  return false;
}

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} customizer The function to customize comparisons.
 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
  var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
      objProps = keys(object),
      objLength = objProps.length,
      othProps = keys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isPartial) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(object);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var result = true;
  stack.set(object, other);
  stack.set(other, object);

  var skipCtor = isPartial;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, objValue, key, other, object, stack)
        : customizer(objValue, othValue, key, object, other, stack);
    }
    // Recursively compare objects (susceptible to call stack limits).
    if (!(compared === undefined
          ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
          : compared
        )) {
      result = false;
      break;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (result && !skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor &&
        ('constructor' in object && 'constructor' in other) &&
        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      result = false;
    }
  }
  stack['delete'](object);
  stack['delete'](other);
  return result;
}

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/**
 * Gets the property names, values, and compare flags of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the match data of `object`.
 */
function getMatchData(object) {
  var result = keys(object),
      length = result.length;

  while (length--) {
    var key = result[length],
        value = object[key];

    result[length] = [key, value, isStrictComparable(value)];
  }
  return result;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = baseGetTag;

// Fallback for data views, maps, sets, and weak maps in IE 11,
// for data views in Edge < 14, and promises in Node.js.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
    (Map && getTag(new Map) != mapTag) ||
    (Promise && getTag(Promise.resolve()) != promiseTag) ||
    (Set && getTag(new Set) != setTag) ||
    (WeakMap && getTag(new WeakMap) != weakMapTag)) {
  getTag = function(value) {
    var result = objectToString.call(value),
        Ctor = result == objectTag ? value.constructor : undefined,
        ctorString = Ctor ? toSource(Ctor) : undefined;

    if (ctorString) {
      switch (ctorString) {
        case dataViewCtorString: return dataViewTag;
        case mapCtorString: return mapTag;
        case promiseCtorString: return promiseTag;
        case setCtorString: return setTag;
        case weakMapCtorString: return weakMapTag;
      }
    }
    return result;
  };
}

/**
 * Checks if `path` exists on `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @param {Function} hasFunc The function to check properties.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 */
function hasPath(object, path, hasFunc) {
  path = isKey(path, object) ? [path] : castPath(path);

  var result,
      index = -1,
      length = path.length;

  while (++index < length) {
    var key = toKey(path[index]);
    if (!(result = object != null && hasFunc(object, key))) {
      break;
    }
    object = object[key];
  }
  if (result) {
    return result;
  }
  var length = object ? object.length : 0;
  return !!length && isLength(length) && isIndex(key, length) &&
    (isArray(object) || isArguments(object));
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if `value` is a property name and not a property path.
 *
 * @private
 * @param {*} value The value to check.
 * @param {Object} [object] The object to query keys on.
 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 */
function isKey(value, object) {
  if (isArray(value)) {
    return false;
  }
  var type = typeof value;
  if (type == 'number' || type == 'symbol' || type == 'boolean' ||
      value == null || isSymbol(value)) {
    return true;
  }
  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
    (object != null && value in Object(object));
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` if suitable for strict
 *  equality comparisons, else `false`.
 */
function isStrictComparable(value) {
  return value === value && !isObject(value);
}

/**
 * A specialized version of `matchesProperty` for source values suitable
 * for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function matchesStrictComparable(key, srcValue) {
  return function(object) {
    if (object == null) {
      return false;
    }
    return object[key] === srcValue &&
      (srcValue !== undefined || (key in Object(object)));
  };
}

/**
 * Converts `string` to a property path array.
 *
 * @private
 * @param {string} string The string to convert.
 * @returns {Array} Returns the property path array.
 */
var stringToPath = memoize(function(string) {
  string = toString(string);

  var result = [];
  if (reLeadingDot.test(string)) {
    result.push('');
  }
  string.replace(rePropName, function(match, number, quote, string) {
    result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
  });
  return result;
});

/**
 * Converts `value` to a string key if it's not a string or symbol.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {string|symbol} Returns the key.
 */
function toKey(value) {
  if (typeof value == 'string' || isSymbol(value)) {
    return value;
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to process.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/**
 * Creates a function that memoizes the result of `func`. If `resolver` is
 * provided, it determines the cache key for storing the result based on the
 * arguments provided to the memoized function. By default, the first argument
 * provided to the memoized function is used as the map cache key. The `func`
 * is invoked with the `this` binding of the memoized function.
 *
 * **Note:** The cache is exposed as the `cache` property on the memoized
 * function. Its creation may be customized by replacing the `_.memoize.Cache`
 * constructor with one whose instances implement the
 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
 * method interface of `delete`, `get`, `has`, and `set`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to have its output memoized.
 * @param {Function} [resolver] The function to resolve the cache key.
 * @returns {Function} Returns the new memoized function.
 * @example
 *
 * var object = { 'a': 1, 'b': 2 };
 * var other = { 'c': 3, 'd': 4 };
 *
 * var values = _.memoize(_.values);
 * values(object);
 * // => [1, 2]
 *
 * values(other);
 * // => [3, 4]
 *
 * object.a = 2;
 * values(object);
 * // => [1, 2]
 *
 * // Modify the result cache.
 * values.cache.set(object, ['a', 'b']);
 * values(object);
 * // => ['a', 'b']
 *
 * // Replace `_.memoize.Cache`.
 * _.memoize.Cache = WeakMap;
 */
function memoize(func, resolver) {
  if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  var memoized = function() {
    var args = arguments,
        key = resolver ? resolver.apply(this, args) : args[0],
        cache = memoized.cache;

    if (cache.has(key)) {
      return cache.get(key);
    }
    var result = func.apply(this, args);
    memoized.cache = cache.set(key, result);
    return result;
  };
  memoized.cache = new (memoize.Cache || MapCache);
  return memoized;
}

// Assign cache to `_.memoize`.
memoize.Cache = MapCache;

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return typeof value == 'symbol' ||
    (isObjectLike(value) && objectToString.call(value) == symbolTag);
}

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 * @example
 *
 * _.toString(null);
 * // => ''
 *
 * _.toString(-0);
 * // => '-0'
 *
 * _.toString([1, 2, 3]);
 * // => '1,2,3'
 */
function toString(value) {
  return value == null ? '' : baseToString(value);
}

/**
 * Gets the value at `path` of `object`. If the resolved value is
 * `undefined`, the `defaultValue` is returned in its place.
 *
 * @static
 * @memberOf _
 * @since 3.7.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
 * @returns {*} Returns the resolved value.
 * @example
 *
 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
 *
 * _.get(object, 'a[0].b.c');
 * // => 3
 *
 * _.get(object, ['a', '0', 'b', 'c']);
 * // => 3
 *
 * _.get(object, 'a.b.c', 'default');
 * // => 'default'
 */
function get(object, path, defaultValue) {
  var result = object == null ? undefined : baseGet(object, path);
  return result === undefined ? defaultValue : result;
}

/**
 * Checks if `path` is a direct or inherited property of `object`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 * @example
 *
 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
 *
 * _.hasIn(object, 'a');
 * // => true
 *
 * _.hasIn(object, 'a.b');
 * // => true
 *
 * _.hasIn(object, ['a', 'b']);
 * // => true
 *
 * _.hasIn(object, 'b');
 * // => false
 */
function hasIn(object, path) {
  return object != null && hasPath(object, path, baseHasIn);
}

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

/**
 * Creates an object with the same keys as `object` and values generated
 * by running each own enumerable string keyed property of `object` thru
 * `iteratee`. The iteratee is invoked with three arguments:
 * (value, key, object).
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Object
 * @param {Object} object The object to iterate over.
 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 * @returns {Object} Returns the new mapped object.
 * @see _.mapKeys
 * @example
 *
 * var users = {
 *   'fred':    { 'user': 'fred',    'age': 40 },
 *   'pebbles': { 'user': 'pebbles', 'age': 1 }
 * };
 *
 * _.mapValues(users, function(o) { return o.age; });
 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
 *
 * // The `_.property` iteratee shorthand.
 * _.mapValues(users, 'age');
 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
 */
function mapValues(object, iteratee) {
  var result = {};
  iteratee = baseIteratee(iteratee, 3);

  baseForOwn(object, function(value, key, object) {
    result[key] = iteratee(value, key, object);
  });
  return result;
}

/**
 * This method returns the first argument it receives.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Util
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'a': 1 };
 *
 * console.log(_.identity(object) === object);
 * // => true
 */
function identity(value) {
  return value;
}

/**
 * Creates a function that returns the value at `path` of a given object.
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Util
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 * @example
 *
 * var objects = [
 *   { 'a': { 'b': 2 } },
 *   { 'a': { 'b': 1 } }
 * ];
 *
 * _.map(objects, _.property('a.b'));
 * // => [2, 1]
 *
 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
 * // => [1, 2]
 */
function property(path) {
  return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}

module.exports = mapValues;

/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5), __webpack_require__(12)(module)))

/***/ }),
/* 36 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = compose;
/**
 * Composes single-argument functions from right to left. The rightmost
 * function can take multiple arguments as it provides the signature for
 * the resulting composite function.
 *
 * @param {...Function} funcs The functions to compose.
 * @returns {Function} A function obtained by composing the argument functions
 * from right to left. For example, compose(f, g, h) is identical to doing
 * (...args) => f(g(h(...args))).
 */

function compose() {
  for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
    funcs[_key] = arguments[_key];
  }

  if (funcs.length === 0) {
    return function (arg) {
      return arg;
    };
  }

  if (funcs.length === 1) {
    return funcs[0];
  }

  return funcs.reduce(function (a, b) {
    return function () {
      return a(b.apply(undefined, arguments));
    };
  });
}

/***/ }),
/* 37 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return ActionTypes; });
/* harmony export (immutable) */ __webpack_exports__["a"] = createStore;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_es_isPlainObject__ = __webpack_require__(29);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_symbol_observable__ = __webpack_require__(39);



/**
 * These are private action types reserved by Redux.
 * For any unknown actions, you must return the current state.
 * If the current state is undefined, you must return the initial state.
 * Do not reference these action types directly in your code.
 */
var ActionTypes = {
  INIT: '@@redux/INIT'

  /**
   * Creates a Redux store that holds the state tree.
   * The only way to change the data in the store is to call `dispatch()` on it.
   *
   * There should only be a single store in your app. To specify how different
   * parts of the state tree respond to actions, you may combine several reducers
   * into a single reducer function by using `combineReducers`.
   *
   * @param {Function} reducer A function that returns the next state tree, given
   * the current state tree and the action to handle.
   *
   * @param {any} [preloadedState] The initial state. You may optionally specify it
   * to hydrate the state from the server in universal apps, or to restore a
   * previously serialized user session.
   * If you use `combineReducers` to produce the root reducer function, this must be
   * an object with the same shape as `combineReducers` keys.
   *
   * @param {Function} [enhancer] The store enhancer. You may optionally specify it
   * to enhance the store with third-party capabilities such as middleware,
   * time travel, persistence, etc. The only store enhancer that ships with Redux
   * is `applyMiddleware()`.
   *
   * @returns {Store} A Redux store that lets you read the state, dispatch actions
   * and subscribe to changes.
   */
};function createStore(reducer, preloadedState, enhancer) {
  var _ref2;

  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState;
    preloadedState = undefined;
  }

  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.');
    }

    return enhancer(createStore)(reducer, preloadedState);
  }

  if (typeof reducer !== 'function') {
    throw new Error('Expected the reducer to be a function.');
  }

  var currentReducer = reducer;
  var currentState = preloadedState;
  var currentListeners = [];
  var nextListeners = currentListeners;
  var isDispatching = false;

  function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) {
      nextListeners = currentListeners.slice();
    }
  }

  /**
   * Reads the state tree managed by the store.
   *
   * @returns {any} The current state tree of your application.
   */
  function getState() {
    return currentState;
  }

  /**
   * Adds a change listener. It will be called any time an action is dispatched,
   * and some part of the state tree may potentially have changed. You may then
   * call `getState()` to read the current state tree inside the callback.
   *
   * You may call `dispatch()` from a change listener, with the following
   * caveats:
   *
   * 1. The subscriptions are snapshotted just before every `dispatch()` call.
   * If you subscribe or unsubscribe while the listeners are being invoked, this
   * will not have any effect on the `dispatch()` that is currently in progress.
   * However, the next `dispatch()` call, whether nested or not, will use a more
   * recent snapshot of the subscription list.
   *
   * 2. The listener should not expect to see all state changes, as the state
   * might have been updated multiple times during a nested `dispatch()` before
   * the listener is called. It is, however, guaranteed that all subscribers
   * registered before the `dispatch()` started will be called with the latest
   * state by the time it exits.
   *
   * @param {Function} listener A callback to be invoked on every dispatch.
   * @returns {Function} A function to remove this change listener.
   */
  function subscribe(listener) {
    if (typeof listener !== 'function') {
      throw new Error('Expected listener to be a function.');
    }

    var isSubscribed = true;

    ensureCanMutateNextListeners();
    nextListeners.push(listener);

    return function unsubscribe() {
      if (!isSubscribed) {
        return;
      }

      isSubscribed = false;

      ensureCanMutateNextListeners();
      var index = nextListeners.indexOf(listener);
      nextListeners.splice(index, 1);
    };
  }

  /**
   * Dispatches an action. It is the only way to trigger a state change.
   *
   * The `reducer` function, used to create the store, will be called with the
   * current state tree and the given `action`. Its return value will
   * be considered the **next** state of the tree, and the change listeners
   * will be notified.
   *
   * The base implementation only supports plain object actions. If you want to
   * dispatch a Promise, an Observable, a thunk, or something else, you need to
   * wrap your store creating function into the corresponding middleware. For
   * example, see the documentation for the `redux-thunk` package. Even the
   * middleware will eventually dispatch plain object actions using this method.
   *
   * @param {Object} action A plain object representing “what changed”. It is
   * a good idea to keep actions serializable so you can record and replay user
   * sessions, or use the time travelling `redux-devtools`. An action must have
   * a `type` property which may not be `undefined`. It is a good idea to use
   * string constants for action types.
   *
   * @returns {Object} For convenience, the same action object you dispatched.
   *
   * Note that, if you use a custom middleware, it may wrap `dispatch()` to
   * return something else (for example, a Promise you can await).
   */
  function dispatch(action) {
    if (!__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0_lodash_es_isPlainObject__["a" /* default */])(action)) {
      throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.');
    }

    if (typeof action.type === 'undefined') {
      throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?');
    }

    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.');
    }

    try {
      isDispatching = true;
      currentState = currentReducer(currentState, action);
    } finally {
      isDispatching = false;
    }

    var listeners = currentListeners = nextListeners;
    for (var i = 0; i < listeners.length; i++) {
      var listener = listeners[i];
      listener();
    }

    return action;
  }

  /**
   * Replaces the reducer currently used by the store to calculate the state.
   *
   * You might need this if your app implements code splitting and you want to
   * load some of the reducers dynamically. You might also need this if you
   * implement a hot reloading mechanism for Redux.
   *
   * @param {Function} nextReducer The reducer for the store to use instead.
   * @returns {void}
   */
  function replaceReducer(nextReducer) {
    if (typeof nextReducer !== 'function') {
      throw new Error('Expected the nextReducer to be a function.');
    }

    currentReducer = nextReducer;
    dispatch({ type: ActionTypes.INIT });
  }

  /**
   * Interoperability point for observable/reactive libraries.
   * @returns {observable} A minimal observable of state changes.
   * For more information, see the observable proposal:
   * https://github.com/tc39/proposal-observable
   */
  function observable() {
    var _ref;

    var outerSubscribe = subscribe;
    return _ref = {
      /**
       * The minimal observable subscription method.
       * @param {Object} observer Any object that can be used as an observer.
       * The observer object should have a `next` method.
       * @returns {subscription} An object with an `unsubscribe` method that can
       * be used to unsubscribe the observable from the store, and prevent further
       * emission of values from the observable.
       */
      subscribe: function subscribe(observer) {
        if (typeof observer !== 'object') {
          throw new TypeError('Expected the observer to be an object.');
        }

        function observeState() {
          if (observer.next) {
            observer.next(getState());
          }
        }

        observeState();
        var unsubscribe = outerSubscribe(observeState);
        return { unsubscribe: unsubscribe };
      }
    }, _ref[__WEBPACK_IMPORTED_MODULE_1_symbol_observable__["default"]] = function () {
      return this;
    }, _ref;
  }

  // When a store is created, an "INIT" action is dispatched so that every
  // reducer returns their initial state. This effectively populates
  // the initial state tree.
  dispatch({ type: ActionTypes.INIT });

  return _ref2 = {
    dispatch: dispatch,
    subscribe: subscribe,
    getState: getState,
    replaceReducer: replaceReducer
  }, _ref2[__WEBPACK_IMPORTED_MODULE_1_symbol_observable__["default"]] = observable, _ref2;
}

/***/ }),
/* 38 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = warning;
/**
 * Prints a warning in the console if it exists.
 *
 * @param {String} message The warning message.
 * @returns {void}
 */
function warning(message) {
  /* eslint-disable no-console */
  if (typeof console !== 'undefined' && typeof console.error === 'function') {
    console.error(message);
  }
  /* eslint-enable no-console */
  try {
    // This error was thrown as a convenience so that if you enable
    // "break on all exceptions" in your console,
    // it would pause the execution at this line.
    throw new Error(message);
    /* eslint-disable no-empty */
  } catch (e) {}
  /* eslint-enable no-empty */
}

/***/ }),
/* 39 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* WEBPACK VAR INJECTION */(function(global, module) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__ponyfill_js__ = __webpack_require__(123);
/* global window */


var root;

if (typeof self !== 'undefined') {
  root = self;
} else if (typeof window !== 'undefined') {
  root = window;
} else if (typeof global !== 'undefined') {
  root = global;
} else if (true) {
  root = module;
} else {
  root = Function('return this')();
}

var result = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__ponyfill_js__["a" /* default */])(root);
/* harmony default export */ __webpack_exports__["default"] = (result);

/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(5), __webpack_require__(124)(module)))

/***/ }),
/* 40 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var networkInterface_1 = __webpack_require__(18);
var isUndefined = __webpack_require__(34);
var assign = __webpack_require__(2);
var isString = __webpack_require__(33);
var store_1 = __webpack_require__(10);
var QueryManager_1 = __webpack_require__(16);
var storeUtils_1 = __webpack_require__(3);
var fragments_1 = __webpack_require__(24);
var getFromAST_1 = __webpack_require__(4);
var DEFAULT_REDUX_ROOT_KEY = 'apollo';
function defaultReduxRootSelector(state) {
    return state[DEFAULT_REDUX_ROOT_KEY];
}
var ApolloClient = (function () {
    function ApolloClient(_a) {
        var _this = this;
        var _b = _a === void 0 ? {} : _a, networkInterface = _b.networkInterface, reduxRootKey = _b.reduxRootKey, reduxRootSelector = _b.reduxRootSelector, initialState = _b.initialState, dataIdFromObject = _b.dataIdFromObject, resultTransformer = _b.resultTransformer, resultComparator = _b.resultComparator, _c = _b.ssrMode, ssrMode = _c === void 0 ? false : _c, _d = _b.ssrForceFetchDelay, ssrForceFetchDelay = _d === void 0 ? 0 : _d, _e = _b.mutationBehaviorReducers, mutationBehaviorReducers = _e === void 0 ? {} : _e, _f = _b.addTypename, addTypename = _f === void 0 ? true : _f, queryTransformer = _b.queryTransformer, customResolvers = _b.customResolvers;
        this.middleware = function () {
            return function (store) {
                _this.setStore(store);
                return function (next) { return function (action) {
                    var returnValue = next(action);
                    _this.queryManager.broadcastNewStore(store.getState());
                    return returnValue;
                }; };
            };
        };
        if (reduxRootKey && reduxRootSelector) {
            throw new Error('Both "reduxRootKey" and "reduxRootSelector" are configured, but only one of two is allowed.');
        }
        if (reduxRootKey) {
            console.warn('"reduxRootKey" option is deprecated and might be removed in the upcoming versions, ' +
                'please use the "reduxRootSelector" instead.');
            this.reduxRootKey = reduxRootKey;
        }
        if (queryTransformer) {
            throw new Error('queryTransformer option no longer supported in Apollo Client 0.5. ' +
                'Instead, there is a new "addTypename" option, which is on by default.');
        }
        if (!reduxRootSelector && reduxRootKey) {
            this.reduxRootSelector = function (state) { return state[reduxRootKey]; };
        }
        else if (isString(reduxRootSelector)) {
            this.reduxRootKey = reduxRootSelector;
            this.reduxRootSelector = function (state) { return state[reduxRootSelector]; };
        }
        else if (typeof reduxRootSelector === 'function') {
            this.reduxRootSelector = reduxRootSelector;
        }
        else {
            this.reduxRootSelector = null;
        }
        this.initialState = initialState ? initialState : {};
        this.networkInterface = networkInterface ? networkInterface :
            networkInterface_1.createNetworkInterface({ uri: '/graphql' });
        this.addTypename = addTypename;
        this.resultTransformer = resultTransformer;
        this.resultComparator = resultComparator;
        this.shouldForceFetch = !(ssrMode || ssrForceFetchDelay > 0);
        this.dataId = dataIdFromObject;
        this.fieldWithArgs = storeUtils_1.storeKeyNameFromFieldNameAndArgs;
        if (ssrForceFetchDelay) {
            setTimeout(function () { return _this.shouldForceFetch = true; }, ssrForceFetchDelay);
        }
        this.reducerConfig = {
            dataIdFromObject: dataIdFromObject,
            mutationBehaviorReducers: mutationBehaviorReducers,
            customResolvers: customResolvers,
        };
        this.watchQuery = this.watchQuery.bind(this);
        this.query = this.query.bind(this);
        this.mutate = this.mutate.bind(this);
        this.setStore = this.setStore.bind(this);
        this.resetStore = this.resetStore.bind(this);
    }
    ApolloClient.prototype.watchQuery = function (options) {
        this.initStore();
        if (!this.shouldForceFetch && options.forceFetch) {
            options = assign({}, options, {
                forceFetch: false,
            });
        }
        fragments_1.createFragment(options.query);
        var fullDocument = getFromAST_1.addFragmentsToDocument(options.query, options.fragments);
        var realOptions = Object.assign({}, options, {
            query: fullDocument,
        });
        delete realOptions.fragments;
        return this.queryManager.watchQuery(realOptions);
    };
    ;
    ApolloClient.prototype.query = function (options) {
        this.initStore();
        if (!this.shouldForceFetch && options.forceFetch) {
            options = assign({}, options, {
                forceFetch: false,
            });
        }
        fragments_1.createFragment(options.query);
        var fullDocument = getFromAST_1.addFragmentsToDocument(options.query, options.fragments);
        var realOptions = Object.assign({}, options, {
            query: fullDocument,
        });
        delete realOptions.fragments;
        return this.queryManager.query(realOptions);
    };
    ;
    ApolloClient.prototype.mutate = function (options) {
        this.initStore();
        var fullDocument = getFromAST_1.addFragmentsToDocument(options.mutation, options.fragments);
        var realOptions = Object.assign({}, options, {
            mutation: fullDocument,
        });
        delete realOptions.fragments;
        return this.queryManager.mutate(realOptions);
    };
    ;
    ApolloClient.prototype.subscribe = function (options) {
        this.initStore();
        var fullDocument = getFromAST_1.addFragmentsToDocument(options.query, options.fragments);
        var realOptions = Object.assign({}, options, {
            document: fullDocument,
        });
        delete realOptions.fragments;
        delete realOptions.query;
        return this.queryManager.startGraphQLSubscription(realOptions);
    };
    ApolloClient.prototype.reducer = function () {
        return store_1.createApolloReducer(this.reducerConfig);
    };
    ApolloClient.prototype.initStore = function () {
        if (this.store) {
            return;
        }
        if (this.reduxRootSelector) {
            throw new Error('Cannot initialize the store because "reduxRootSelector" or "reduxRootKey" is provided. ' +
                'They should only be used when the store is created outside of the client. ' +
                'This may lead to unexpected results when querying the store internally. ' +
                "Please remove that option from ApolloClient constructor.");
        }
        this.setStore(store_1.createApolloStore({
            reduxRootKey: DEFAULT_REDUX_ROOT_KEY,
            initialState: this.initialState,
            config: this.reducerConfig,
        }));
        this.reduxRootKey = DEFAULT_REDUX_ROOT_KEY;
    };
    ;
    ApolloClient.prototype.resetStore = function () {
        this.queryManager.resetStore();
    };
    ;
    ApolloClient.prototype.getInitialState = function () {
        return this.queryManager.getInitialState();
    };
    ApolloClient.prototype.setStore = function (store) {
        var reduxRootSelector;
        if (this.reduxRootSelector) {
            reduxRootSelector = this.reduxRootSelector;
        }
        else {
            reduxRootSelector = defaultReduxRootSelector;
            this.reduxRootKey = DEFAULT_REDUX_ROOT_KEY;
        }
        if (isUndefined(reduxRootSelector(store.getState()))) {
            throw new Error('Existing store does not use apolloReducer. Please make sure the store ' +
                'is properly configured and "reduxRootSelector" is correctly specified.');
        }
        this.store = store;
        this.queryManager = new QueryManager_1.QueryManager({
            networkInterface: this.networkInterface,
            reduxRootSelector: reduxRootSelector,
            store: store,
            addTypename: this.addTypename,
            resultTransformer: this.resultTransformer,
            resultComparator: this.resultComparator,
            reducerConfig: this.reducerConfig,
        });
    };
    ;
    return ApolloClient;
}());
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = ApolloClient;
//# sourceMappingURL=ApolloClient.js.map

/***/ }),
/* 41 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var mapValues = __webpack_require__(35);
var cloneDeep = __webpack_require__(30);
var assign = __webpack_require__(2);
var replaceQueryResults_1 = __webpack_require__(22);
var writeToStore_1 = __webpack_require__(6);
var getFromAST_1 = __webpack_require__(4);
var scopeQuery_1 = __webpack_require__(43);
function mutationResultArrayInsertReducer(state, _a) {
    var behavior = _a.behavior, result = _a.result, variables = _a.variables, document = _a.document, config = _a.config;
    var _b = behavior, resultPath = _b.resultPath, storePath = _b.storePath, where = _b.where;
    var selectionSet = getFromAST_1.getOperationDefinition(document).selectionSet;
    var fragmentMap = getFromAST_1.createFragmentMap(getFromAST_1.getFragmentDefinitions(document));
    var scopedSelectionSet = scopeQuery_1.scopeSelectionSetToResultPath({
        selectionSet: selectionSet,
        fragmentMap: fragmentMap,
        path: resultPath,
    });
    var scopedResult = scopeQuery_1.scopeJSONToResultPath({
        json: result.data,
        path: resultPath,
    });
    var dataId = config.dataIdFromObject(scopedResult) || generateMutationResultDataId();
    state = writeToStore_1.writeSelectionSetToStore({
        result: scopedResult,
        dataId: dataId,
        selectionSet: scopedSelectionSet,
        context: {
            store: state,
            variables: variables,
            dataIdFromObject: config.dataIdFromObject,
            fragmentMap: fragmentMap,
        },
    });
    var dataIdOfObj = storePath[0], restStorePath = storePath.slice(1);
    var clonedObj = cloneDeep(state[dataIdOfObj]);
    var array = scopeQuery_1.scopeJSONToResultPath({
        json: clonedObj,
        path: restStorePath,
    });
    var idValue = { type: 'id', generated: false, id: dataId };
    if (where === 'PREPEND') {
        array.unshift(idValue);
    }
    else if (where === 'APPEND') {
        array.push(idValue);
    }
    else {
        throw new Error('Unsupported "where" option to ARRAY_INSERT.');
    }
    return assign(state, (_c = {},
        _c[dataIdOfObj] = clonedObj,
        _c
    ));
    var _c;
}
var currId = 0;
function generateMutationResultDataId() {
    currId++;
    return "ARRAY_INSERT-gen-id-" + currId;
}
function mutationResultDeleteReducer(state, _a) {
    var behavior = _a.behavior;
    var dataId = behavior.dataId;
    delete state[dataId];
    var newState = mapValues(state, function (storeObj) {
        return removeRefsFromStoreObj(storeObj, dataId);
    });
    return newState;
}
function removeRefsFromStoreObj(storeObj, dataId) {
    var affected = false;
    var cleanedObj = mapValues(storeObj, function (value) {
        if (value && value.id === dataId) {
            affected = true;
            return null;
        }
        if (Array.isArray(value)) {
            var filteredArray = cleanArray(value, dataId);
            if (filteredArray !== value) {
                affected = true;
                return filteredArray;
            }
        }
        return value;
    });
    if (affected) {
        return cleanedObj;
    }
    else {
        return storeObj;
    }
}
function cleanArray(originalArray, dataId) {
    if (originalArray.length && Array.isArray(originalArray[0])) {
        var modified_1 = false;
        var filteredArray = originalArray.map(function (nestedArray) {
            var nestedFilteredArray = cleanArray(nestedArray, dataId);
            if (nestedFilteredArray !== nestedArray) {
                modified_1 = true;
                return nestedFilteredArray;
            }
            return nestedArray;
        });
        if (!modified_1) {
            return originalArray;
        }
        return filteredArray;
    }
    else {
        var filteredArray = originalArray.filter(function (item) { return item.id !== dataId; });
        if (filteredArray.length === originalArray.length) {
            return originalArray;
        }
        return filteredArray;
    }
}
exports.cleanArray = cleanArray;
function mutationResultArrayDeleteReducer(state, _a) {
    var behavior = _a.behavior;
    var _b = behavior, dataId = _b.dataId, storePath = _b.storePath;
    var dataIdOfObj = storePath[0], restStorePath = storePath.slice(1);
    var clonedObj = cloneDeep(state[dataIdOfObj]);
    var array = scopeQuery_1.scopeJSONToResultPath({
        json: clonedObj,
        path: restStorePath,
    });
    var index = -1;
    array.some(function (item, i) {
        if (item && item.id === dataId) {
            index = i;
            return true;
        }
        return false;
    });
    if (index === -1) {
        return state;
    }
    array.splice(index, 1);
    return assign(state, (_c = {},
        _c[dataIdOfObj] = clonedObj,
        _c
    ));
    var _c;
}
function mutationResultQueryResultReducer(state, _a) {
    var behavior = _a.behavior, config = _a.config;
    return replaceQueryResults_1.replaceQueryResults(state, behavior, config);
}
exports.mutationResultQueryResultReducer = mutationResultQueryResultReducer;
exports.defaultMutationBehaviorReducers = {
    'ARRAY_INSERT': mutationResultArrayInsertReducer,
    'DELETE': mutationResultDeleteReducer,
    'ARRAY_DELETE': mutationResultArrayDeleteReducer,
    'QUERY_RESULT': mutationResultQueryResultReducer,
};
//# sourceMappingURL=mutationResults.js.map

/***/ }),
/* 42 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var readFromStore_1 = __webpack_require__(8);
var writeToStore_1 = __webpack_require__(6);
function createStoreReducer(resultReducer, document, variables, config) {
    return function (store, action) {
        var currentResult = readFromStore_1.readQueryFromStore({
            store: store,
            query: document,
            variables: variables,
            returnPartialData: true,
            config: config,
        });
        var nextResult = resultReducer(currentResult, action);
        if (currentResult !== nextResult) {
            return writeToStore_1.writeResultToStore({
                dataId: 'ROOT_QUERY',
                result: nextResult,
                store: store,
                document: document,
                variables: variables,
                dataIdFromObject: config.dataIdFromObject,
            });
        }
        return store;
    };
}
exports.createStoreReducer = createStoreReducer;
//# sourceMappingURL=resultReducers.js.map

/***/ }),
/* 43 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var storeUtils_1 = __webpack_require__(3);
var isNumber = __webpack_require__(31);
function scopeJSONToResultPath(_a) {
    var json = _a.json, path = _a.path;
    var current = json;
    path.forEach(function (pathSegment) {
        current = current[pathSegment];
    });
    return current;
}
exports.scopeJSONToResultPath = scopeJSONToResultPath;
function scopeSelectionSetToResultPath(_a) {
    var selectionSet = _a.selectionSet, fragmentMap = _a.fragmentMap, path = _a.path;
    var currSelSet = selectionSet;
    path
        .filter(function (pathSegment) { return !isNumber(pathSegment); })
        .forEach(function (pathSegment) {
        currSelSet = followOnePathSegment(currSelSet, pathSegment, fragmentMap);
    });
    return currSelSet;
}
exports.scopeSelectionSetToResultPath = scopeSelectionSetToResultPath;
function followOnePathSegment(currSelSet, pathSegment, fragmentMap) {
    var matchingFields = getMatchingFields(currSelSet, pathSegment, fragmentMap);
    if (matchingFields.length < 1) {
        throw new Error("No matching field found in query for path segment: " + pathSegment);
    }
    if (matchingFields.length > 1) {
        throw new Error("Multiple fields found in query for path segment \"" + pathSegment + "\". Please file an issue on Apollo Client if you run into this situation.");
    }
    return matchingFields[0].selectionSet;
}
function getMatchingFields(currSelSet, pathSegment, fragmentMap) {
    var matching = [];
    currSelSet.selections.forEach(function (selection) {
        if (storeUtils_1.isField(selection)) {
            if (storeUtils_1.resultKeyNameFromField(selection) === pathSegment) {
                matching.push(selection);
            }
        }
        else if (storeUtils_1.isInlineFragment(selection)) {
            matching = matching.concat(getMatchingFields(selection.selectionSet, pathSegment, fragmentMap));
        }
        else {
            var fragment = fragmentMap[selection.name.value];
            matching = matching.concat(getMatchingFields(fragment.selectionSet, pathSegment, fragmentMap));
        }
    });
    return matching;
}
//# sourceMappingURL=scopeQuery.js.map

/***/ }),
/* 44 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var networkInterface_1 = __webpack_require__(18);
exports.createNetworkInterface = networkInterface_1.createNetworkInterface;
exports.HTTPFetchNetworkInterface = networkInterface_1.HTTPFetchNetworkInterface;
var batchedNetworkInterface_1 = __webpack_require__(50);
exports.createBatchingNetworkInterface = batchedNetworkInterface_1.createBatchingNetworkInterface;
var printer_1 = __webpack_require__(19);
exports.printAST = printer_1.print;
var store_1 = __webpack_require__(10);
exports.createApolloStore = store_1.createApolloStore;
exports.createApolloReducer = store_1.createApolloReducer;
var ObservableQuery_1 = __webpack_require__(15);
exports.ObservableQuery = ObservableQuery_1.ObservableQuery;
var readFromStore_1 = __webpack_require__(8);
exports.readQueryFromStore = readFromStore_1.readQueryFromStore;
var writeToStore_1 = __webpack_require__(6);
exports.writeQueryToStore = writeToStore_1.writeQueryToStore;
var getFromAST_1 = __webpack_require__(4);
exports.getQueryDefinition = getFromAST_1.getQueryDefinition;
exports.getFragmentDefinitions = getFromAST_1.getFragmentDefinitions;
exports.createFragmentMap = getFromAST_1.createFragmentMap;
var ApolloError_1 = __webpack_require__(17);
exports.ApolloError = ApolloError_1.ApolloError;
var ApolloClient_1 = __webpack_require__(40);
exports.ApolloClient = ApolloClient_1.default;
var fragments_1 = __webpack_require__(24);
exports.createFragment = fragments_1.createFragment;
exports.clearFragmentDefinitions = fragments_1.clearFragmentDefinitions;
exports.disableFragmentWarnings = fragments_1.disableFragmentWarnings;
exports.enableFragmentWarnings = fragments_1.enableFragmentWarnings;
var storeUtils_1 = __webpack_require__(3);
exports.toIdValue = storeUtils_1.toIdValue;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = ApolloClient_1.default;
//# sourceMappingURL=index.js.map

/***/ }),
/* 45 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var actions_1 = __webpack_require__(7);
var assign = __webpack_require__(2);
function mutations(previousState, action) {
    if (previousState === void 0) { previousState = {}; }
    if (actions_1.isMutationInitAction(action)) {
        var newState = assign({}, previousState);
        newState[action.mutationId] = {
            mutationString: action.mutationString,
            variables: action.variables,
            loading: true,
            error: null,
        };
        return newState;
    }
    else if (actions_1.isMutationResultAction(action)) {
        var newState = assign({}, previousState);
        newState[action.mutationId] = assign({}, previousState[action.mutationId], {
            loading: false,
            error: null,
        });
        return newState;
    }
    else if (actions_1.isMutationErrorAction(action)) {
        var newState = assign({}, previousState);
        newState[action.mutationId] = assign({}, previousState[action.mutationId], {
            loading: false,
            error: action.error,
        });
    }
    else if (actions_1.isStoreResetAction(action)) {
        return {};
    }
    return previousState;
}
exports.mutations = mutations;
//# sourceMappingURL=store.js.map

/***/ }),
/* 46 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var actions_1 = __webpack_require__(7);
var store_1 = __webpack_require__(23);
var store_2 = __webpack_require__(10);
var assign = __webpack_require__(2);
var pick = __webpack_require__(116);
var optimisticDefaultState = [];
function optimistic(previousState, action, store, config) {
    if (previousState === void 0) { previousState = optimisticDefaultState; }
    if (actions_1.isMutationInitAction(action) && action.optimisticResponse) {
        var fakeMutationResultAction = {
            type: 'APOLLO_MUTATION_RESULT',
            result: { data: action.optimisticResponse },
            document: action.mutation,
            operationName: action.operationName,
            mutationId: action.mutationId,
            resultBehaviors: action.resultBehaviors,
            extraReducers: action.extraReducers,
        };
        var fakeStore = assign({}, store, { optimistic: previousState });
        var optimisticData_1 = store_2.getDataWithOptimisticResults(fakeStore);
        var fakeDataResultState_1 = store_1.data(optimisticData_1, fakeMutationResultAction, store.queries, store.mutations, config);
        var changedKeys = Object.keys(fakeDataResultState_1).filter(function (key) { return optimisticData_1[key] !== fakeDataResultState_1[key]; });
        var patch = pick(fakeDataResultState_1, changedKeys);
        var optimisticState = {
            data: patch,
            mutationId: action.mutationId,
        };
        var newState = previousState.concat([optimisticState]);
        return newState;
    }
    else if ((actions_1.isMutationErrorAction(action) || actions_1.isMutationResultAction(action))
        && previousState.some(function (change) { return change.mutationId === action.mutationId; })) {
        var newState = previousState.filter(function (change) { return change.mutationId !== action.mutationId; });
        return newState;
    }
    return previousState;
}
exports.optimistic = optimistic;
//# sourceMappingURL=store.js.map

/***/ }),
/* 47 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

function shouldInclude(selection, variables) {
    if (!variables) {
        variables = {};
    }
    if (!selection.directives) {
        return true;
    }
    var res = true;
    selection.directives.forEach(function (directive) {
        if (directive.name.value !== 'skip' && directive.name.value !== 'include') {
            return;
        }
        var directiveArguments = directive.arguments;
        var directiveName = directive.name.value;
        if (directiveArguments.length !== 1) {
            throw new Error("Incorrect number of arguments for the @" + directiveName + " directive.");
        }
        var ifArgument = directive.arguments[0];
        if (!ifArgument.name || ifArgument.name.value !== 'if') {
            throw new Error("Invalid argument for the @" + directiveName + " directive.");
        }
        var ifValue = directive.arguments[0].value;
        var evaledValue = false;
        if (!ifValue || ifValue.kind !== 'BooleanValue') {
            if (ifValue.kind !== 'Variable') {
                throw new Error("Argument for the @" + directiveName + " directive must be a variable or a bool ean value.");
            }
            else {
                evaledValue = variables[ifValue.name.value];
                if (evaledValue === undefined) {
                    throw new Error("Invalid variable referenced in @" + directiveName + " directive.");
                }
            }
        }
        else {
            evaledValue = ifValue.value;
        }
        if (directiveName === 'skip') {
            evaledValue = !evaledValue;
        }
        if (!evaledValue) {
            res = false;
        }
    });
    return res;
}
exports.shouldInclude = shouldInclude;
//# sourceMappingURL=directives.js.map

/***/ }),
/* 48 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var getFromAST_1 = __webpack_require__(4);
var cloneDeep = __webpack_require__(30);
var TYPENAME_FIELD = {
    kind: 'Field',
    alias: null,
    name: {
        kind: 'Name',
        value: '__typename',
    },
};
function addTypenameToSelectionSet(selectionSet, isRoot) {
    if (isRoot === void 0) { isRoot = false; }
    if (selectionSet && selectionSet.selections) {
        if (!isRoot) {
            var alreadyHasThisField = selectionSet.selections.some(function (selection) {
                return selection.kind === 'Field' && selection.name.value === '__typename';
            });
            if (!alreadyHasThisField) {
                selectionSet.selections.push(TYPENAME_FIELD);
            }
        }
        selectionSet.selections.forEach(function (selection) {
            if (selection.kind === 'Field' || selection.kind === 'InlineFragment') {
                addTypenameToSelectionSet(selection.selectionSet);
            }
        });
    }
}
function addTypenameToDocument(doc) {
    getFromAST_1.checkDocument(doc);
    var docClone = cloneDeep(doc);
    docClone.definitions.forEach(function (definition) {
        var isRoot = definition.kind === 'OperationDefinition';
        addTypenameToSelectionSet(definition.selectionSet, isRoot);
    });
    return docClone;
}
exports.addTypenameToDocument = addTypenameToDocument;
//# sourceMappingURL=queryTransform.js.map

/***/ }),
/* 49 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var QueryManager_1 = __webpack_require__(16);
var ObservableQuery_1 = __webpack_require__(15);
var assign = __webpack_require__(2);
var store_1 = __webpack_require__(9);
var QueryScheduler = (function () {
    function QueryScheduler(_a) {
        var queryManager = _a.queryManager;
        this.queryManager = queryManager;
        this.pollingTimers = {};
        this.inFlightQueries = {};
        this.registeredQueries = {};
        this.intervalQueries = {};
    }
    QueryScheduler.prototype.checkInFlight = function (queryId) {
        var queries = this.queryManager.getApolloState().queries;
        return queries[queryId] && queries[queryId].networkStatus !== store_1.NetworkStatus.ready;
    };
    QueryScheduler.prototype.fetchQuery = function (queryId, options, fetchType) {
        var _this = this;
        return new Promise(function (resolve, reject) {
            _this.queryManager.fetchQuery(queryId, options, fetchType).then(function (result) {
                resolve(result);
            }).catch(function (error) {
                reject(error);
            });
        });
    };
    QueryScheduler.prototype.startPollingQuery = function (options, queryId, listener) {
        if (!options.pollInterval) {
            throw new Error('Attempted to start a polling query without a polling interval.');
        }
        this.registeredQueries[queryId] = options;
        if (listener) {
            this.queryManager.addQueryListener(queryId, listener);
        }
        this.addQueryOnInterval(queryId, options);
        return queryId;
    };
    QueryScheduler.prototype.stopPollingQuery = function (queryId) {
        delete this.registeredQueries[queryId];
    };
    QueryScheduler.prototype.fetchQueriesOnInterval = function (interval) {
        var _this = this;
        this.intervalQueries[interval] = this.intervalQueries[interval].filter(function (queryId) {
            if (!_this.registeredQueries.hasOwnProperty(queryId)) {
                return false;
            }
            if (_this.checkInFlight(queryId)) {
                return true;
            }
            var queryOptions = _this.registeredQueries[queryId];
            var pollingOptions = assign({}, queryOptions);
            pollingOptions.forceFetch = true;
            _this.fetchQuery(queryId, pollingOptions, QueryManager_1.FetchType.poll);
            return true;
        });
        if (this.intervalQueries[interval].length === 0) {
            clearInterval(this.pollingTimers[interval]);
            delete this.intervalQueries[interval];
        }
    };
    QueryScheduler.prototype.addQueryOnInterval = function (queryId, queryOptions) {
        var _this = this;
        var interval = queryOptions.pollInterval;
        if (this.intervalQueries.hasOwnProperty(interval.toString()) && this.intervalQueries[interval].length > 0) {
            this.intervalQueries[interval].push(queryId);
        }
        else {
            this.intervalQueries[interval] = [queryId];
            this.pollingTimers[interval] = setInterval(function () {
                _this.fetchQueriesOnInterval(interval);
            }, interval);
        }
    };
    QueryScheduler.prototype.registerPollingQuery = function (queryOptions) {
        if (!queryOptions.pollInterval) {
            throw new Error('Attempted to register a non-polling query with the scheduler.');
        }
        return new ObservableQuery_1.ObservableQuery({
            scheduler: this,
            options: queryOptions,
        });
    };
    return QueryScheduler;
}());
exports.QueryScheduler = QueryScheduler;
//# sourceMappingURL=scheduler.js.map

/***/ }),
/* 50 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__webpack_require__(13);
var assign = __webpack_require__(2);
var isNumber = __webpack_require__(31);
var networkInterface_1 = __webpack_require__(18);
var batching_1 = __webpack_require__(51);
var HTTPBatchedNetworkInterface = (function (_super) {
    __extends(HTTPBatchedNetworkInterface, _super);
    function HTTPBatchedNetworkInterface(uri, pollInterval, fetchOpts) {
        _super.call(this, uri, fetchOpts);
        if (!isNumber(pollInterval)) {
            throw new Error("pollInterval must be a number, got " + pollInterval);
        }
        this.pollInterval = pollInterval;
        this.batcher = new batching_1.QueryBatcher({
            batchFetchFunction: this.batchQuery.bind(this),
        });
        this.batcher.start(this.pollInterval);
    }
    ;
    HTTPBatchedNetworkInterface.prototype.query = function (request) {
        return this.batcher.enqueueRequest(request);
    };
    HTTPBatchedNetworkInterface.prototype.batchQuery = function (requests) {
        var _this = this;
        var options = assign({}, this._opts);
        var middlewarePromises = [];
        requests.forEach(function (request) {
            middlewarePromises.push(_this.applyMiddlewares({
                request: request,
                options: options,
            }));
        });
        return new Promise(function (resolve, reject) {
            Promise.all(middlewarePromises).then(function (requestsAndOptions) {
                return _this.batchedFetchFromRemoteEndpoint(requestsAndOptions)
                    .then(function (result) {
                    return result.json();
                })
                    .then(function (responses) {
                    if (typeof responses.map !== 'function') {
                        throw new Error('BatchingNetworkInterface: server response is not an array');
                    }
                    var afterwaresPromises = responses.map(function (response, index) {
                        return _this.applyAfterwares({
                            response: response,
                            options: requestsAndOptions[index].options,
                        });
                    });
                    Promise.all(afterwaresPromises).then(function (responsesAndOptions) {
                        var results = [];
                        responsesAndOptions.forEach(function (result) {
                            results.push(result.response);
                        });
                        resolve(results);
                    }).catch(function (error) {
                        reject(error);
                    });
                });
            }).catch(function (error) {
                reject(error);
            });
        });
    };
    HTTPBatchedNetworkInterface.prototype.batchedFetchFromRemoteEndpoint = function (requestsAndOptions) {
        var options = {};
        requestsAndOptions.forEach(function (requestAndOptions) {
            assign(options, requestAndOptions.options);
        });
        var printedRequests = requestsAndOptions.map(function (_a) {
            var request = _a.request;
            return networkInterface_1.printRequest(request);
        });
        return fetch(this._uri, assign({}, this._opts, {
            body: JSON.stringify(printedRequests),
            method: 'POST',
        }, options, {
            headers: assign({}, {
                Accept: '*/*',
                'Content-Type': 'application/json',
            }, options.headers),
        }));
    };
    ;
    return HTTPBatchedNetworkInterface;
}(networkInterface_1.HTTPFetchNetworkInterface));
exports.HTTPBatchedNetworkInterface = HTTPBatchedNetworkInterface;
function createBatchingNetworkInterface(options) {
    if (!options) {
        throw new Error('You must pass an options argument to createNetworkInterface.');
    }
    return new HTTPBatchedNetworkInterface(options.uri, options.batchInterval, options.opts);
}
exports.createBatchingNetworkInterface = createBatchingNetworkInterface;
//# sourceMappingURL=batchedNetworkInterface.js.map

/***/ }),
/* 51 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

;
var QueryBatcher = (function () {
    function QueryBatcher(_a) {
        var batchFetchFunction = _a.batchFetchFunction;
        this.queuedRequests = [];
        this.queuedRequests = [];
        this.batchFetchFunction = batchFetchFunction;
    }
    QueryBatcher.prototype.enqueueRequest = function (request) {
        var fetchRequest = {
            request: request,
        };
        this.queuedRequests.push(fetchRequest);
        fetchRequest.promise = new Promise(function (resolve, reject) {
            fetchRequest.resolve = resolve;
            fetchRequest.reject = reject;
        });
        return fetchRequest.promise;
    };
    QueryBatcher.prototype.consumeQueue = function () {
        if (this.queuedRequests.length < 1) {
            return undefined;
        }
        var requests = this.queuedRequests.map(function (queuedRequest) {
            return {
                query: queuedRequest.request.query,
                variables: queuedRequest.request.variables,
                operationName: queuedRequest.request.operationName,
            };
        });
        var promises = [];
        var resolvers = [];
        var rejecters = [];
        this.queuedRequests.forEach(function (fetchRequest, index) {
            promises.push(fetchRequest.promise);
            resolvers.push(fetchRequest.resolve);
            rejecters.push(fetchRequest.reject);
        });
        this.queuedRequests = [];
        var batchedPromise = this.batchFetchFunction(requests);
        batchedPromise.then(function (results) {
            results.forEach(function (result, index) {
                resolvers[index](result);
            });
        }).catch(function (error) {
            rejecters.forEach(function (rejecter, index) {
                rejecters[index](error);
            });
        });
        return promises;
    };
    QueryBatcher.prototype.start = function (pollInterval) {
        var _this = this;
        if (this.pollTimer) {
            clearInterval(this.pollTimer);
        }
        this.pollInterval = pollInterval;
        this.pollTimer = setInterval(function () {
            _this.consumeQueue();
        }, this.pollInterval);
    };
    QueryBatcher.prototype.stop = function () {
        if (this.pollTimer) {
            clearInterval(this.pollTimer);
        }
    };
    return QueryBatcher;
}());
exports.QueryBatcher = QueryBatcher;
//# sourceMappingURL=batching.js.map

/***/ }),
/* 52 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _templateObject = _taggedTemplateLiteral(['\n      query getCarryOverPools($wagerProfile: String) {\n          carryOverPools(profile: $wagerProfile) {\n            trackCode\n            trackName\n            perfAbbr\n            raceNumber\n            amount\n            race {\n              status {\n                code\n              }\n            }\n            wagerType {\n              name\n              id\n            }\n          }\n        }'], ['\n      query getCarryOverPools($wagerProfile: String) {\n          carryOverPools(profile: $wagerProfile) {\n            trackCode\n            trackName\n            perfAbbr\n            raceNumber\n            amount\n            race {\n              status {\n                code\n              }\n            }\n            wagerType {\n              name\n              id\n            }\n          }\n        }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race Betting Interests Module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Queries the GraphQL to return the betting interests for a particular race
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceBettingInterests
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var CarryOverPools = function (_GraphQLSubscribeInte) {
  _inherits(CarryOverPools, _GraphQLSubscribeInte);

  function CarryOverPools() {
    _classCallCheck(this, CarryOverPools);

    return _possibleConstructorReturn(this, (CarryOverPools.__proto__ || Object.getPrototypeOf(CarryOverPools)).apply(this, arguments));
  }

  _createClass(CarryOverPools, [{
    key: 'get',


    /**
     * Makes the query, one time, and returns the response
     * @param options
     * @returns {Promise}
     */
    value: function get(options) {
      var _this2 = this;

      return Promise.resolve(options).then(CarryOverPools.verifyValidOptions).then(function () {
        var graphQuery = CarryOverPools.buildQuery(options);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables, options.forceFetch);
      }).then(CarryOverPools.verifyNotFoundResult).then(function (result) {
        return result.data;
      });
    }
  }], [{
    key: 'buildQuery',

    /**
     * Builds the query according to the given options
     * @param options
     * @returns {{string: String, variables: Object}}
     */
    value: function buildQuery(options) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      return {
        string: queryString,
        variables: options
      };
    }

    /**
     * Takes the result and verifies if there is any error.
     * @param result
     * @returns {boolean}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (result.errors || !result.data || !result.data.carryOverPools) {
        throw new Error('Error getting Carry over pools');
      }
      return result;
    }

    /**
     * Verifies if the client has the necessary options to perform the query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the options');
      }
    }
  }]);

  return CarryOverPools;
}(_client.GraphQLSubscribeInterface);

exports.default = CarryOverPools;

/***/ }),
/* 53 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _carryOverPools = __webpack_require__(52);

var _carryOverPools2 = _interopRequireDefault(_carryOverPools);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _carryOverPools2.default;

/***/ }),
/* 54 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _apolloClient = __webpack_require__(44);

var _apolloClient2 = _interopRequireDefault(_apolloClient);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var GraphQLClient = function () {
  function GraphQLClient() {
    var _this = this;

    _classCallCheck(this, GraphQLClient);

    /**
     * To initialize the GraphQLClient call this method
     * @param serviceUrl - the URL for the graphql service to be used
     */
    this.configureGraphClient = function (serviceUrl) {
      _this.serviceUrl = serviceUrl || 'https://service.tvg.com/graph/v2/query';
      _this.init((0, _apolloClient.createNetworkInterface)({
        uri: _this.serviceUrl,
        opts: {
          credentials: 'include'
        }
      }));
    };

    this.setCustomInterface = function (networkInterface) {
      _this.client = new _apolloClient2.default({
        networkInterface: networkInterface
      });
    };
  }

  _createClass(GraphQLClient, [{
    key: 'query',


    // queryString :: String -> Promise
    value: function query(_query) {
      var variables = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      var forceFetch = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
      var fragmentList = arguments[3];

      var options = {
        query: _query,
        variables: variables,
        forceFetch: forceFetch
      };

      if (fragmentList) {
        options = Object.assign(options, {
          fragments: GraphQLClient.buildFragments(fragmentList)
        });
      }

      return this.client.query(options);
    }

    // queryString :: String -> Promise

  }, {
    key: 'watch',
    value: function watch(query) {
      var variables = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
      var fragmentList = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;

      var options = {
        query: query,
        variables: variables,
        pollInterval: pollInterval,
        forceFetch: forceFetch
      };

      if (fragmentList) {
        options = Object.assign(options, {
          fragments: GraphQLClient.buildFragments(fragmentList)
        });
      }

      return this.client.watchQuery(options);
    }
  }, {
    key: 'init',
    value: function init(networkInterface) {
      this.client = new _apolloClient2.default({
        networkInterface: networkInterface,
        addTypename: true
      });
    }
  }], [{
    key: 'buildFragments',
    value: function buildFragments(fragmentList) {
      var fragments = null;
      fragmentList.forEach(function (fragment) {
        fragments = (0, _apolloClient.createFragment)(fragment, fragments);
      });
      return fragments;
    }
  }]);

  return GraphQLClient;
}();

exports.default = GraphQLClient;

/***/ }),
/* 55 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var GraphQLSubscribeInterface = function () {

  /**
   *
   * @param {GraphQLClient} graphql
   */
  function GraphQLSubscribeInterface(graphql) {
    _classCallCheck(this, GraphQLSubscribeInterface);

    this.graphql = graphql;
  }

  /**
   * Subscribes to graphql query
   * @param {string} queryString
   * @param {object} queryVariables
   * @param {int} pollInterval in ms
   * @param {boolean} forceFetch
   * @param {array} fragmentList
   * @returns {Function} (success, fail)
   */


  _createClass(GraphQLSubscribeInterface, [{
    key: 'subscribe',
    value: function subscribe(queryString) {
      var queryVariables = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      var pollInterval = arguments[2];

      var _this = this;

      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
      var fragmentList = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;

      this.queryObservable = this.graphql.watch(queryString, queryVariables, pollInterval, forceFetch, fragmentList);

      return function (next, error) {
        _this.queryObserver = { next: next, error: error };
        return _this.queryObservable.subscribe(_this.queryObserver);
      };
    }

    /**
     * Retries fetching of query on network error
     * @param {int} pollInterval
     */

  }, {
    key: 'fetchRetry',
    value: function fetchRetry(pollInterval) {
      var _this2 = this;

      if (!this.fetchRetryEvent) {
        this.queryObservable.stopPolling();
        this.fetchRetryEvent = setTimeout(function () {
          clearTimeout(_this2.fetchRetryEvent);
          _this2.fetchRetryEvent = false;
          _this2.queryObservable.refetch().then(function () {
            _this2.queryObservable.startPolling(pollInterval);
          });
        }, pollInterval);
      }
    }

    /**
     * Refetches query with new query variables from graphql
     * @param {object} queryVariables
     * @returns {Function} (success, fail)
     */

  }, {
    key: 'refetch',
    value: function refetch(queryVariables) {
      var _this3 = this;

      if (this.queryObservable) {
        return function (resolve, reject) {
          return _this3.queryObservable.refetch(queryVariables).then(function (result) {
            return resolve(result);
          }).catch(function (error) {
            return reject(error);
          });
        };
      }
      return function (success, fail) {
        return fail('There is no subscription to refetch');
      };
    }

    /**
     * Verifies if there is any subscription running at the moment
     * @returns {boolean}
     */

  }, {
    key: 'isSubscribed',
    value: function isSubscribed() {
      return !!this.queryObservable;
    }

    /**
     * Unsubscribes a subscription, stoping its associated interval
     * @param subscription
     */

  }, {
    key: 'unsubscribe',
    value: function unsubscribe(subscription) {
      if (!subscription || !subscription.unsubscribe) {
        throw new Error('You need to pass a subscription to unsubscribe');
      }

      if (this.isSubscribed()) {
        subscription.unsubscribe();
        delete this.queryObservable;
      } else {
        throw new Error('There are no subscriptions to unsubscribe');
      }
    }
  }]);

  return GraphQLSubscribeInterface;
}();

exports.default = GraphQLSubscribeInterface;

/***/ }),
/* 56 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['query getFeaturedTracks(\n    $wagerProfile: String,\n    $featured: TrackListFilter,\n    $sortBy: RaceListSort,\n    $filterBy: RaceListFilter\n    ){\n      tracks(\n      filter: $featured,\n      profile: $wagerProfile\n      ) {\n        code\n        name\n        perfAbbr\n        featured\n        location {\n          country\n        }\n        races (\n          sort: $sortBy,\n          filter: $filterBy\n        ) {\n          number\n          mtp\n          postTime\n          status {\n            code\n          }\n        }\n      }\n    }'], ['query getFeaturedTracks(\n    $wagerProfile: String,\n    $featured: TrackListFilter,\n    $sortBy: RaceListSort,\n    $filterBy: RaceListFilter\n    ){\n      tracks(\n      filter: $featured,\n      profile: $wagerProfile\n      ) {\n        code\n        name\n        perfAbbr\n        featured\n        location {\n          country\n        }\n        races (\n          sort: $sortBy,\n          filter: $filterBy\n        ) {\n          number\n          mtp\n          postTime\n          status {\n            code\n          }\n        }\n      }\n    }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _utils = __webpack_require__(14);

var _utils2 = _interopRequireDefault(_utils);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Featured Tracks module
                                                                                                                                                           * @module FeaturedTracks
                                                                                                                                                           */


var FeaturedTrackRace =
/**
 *
 * @param {string} trackName
 * @param {string} trackAbbr
 * @param {string} perfAbbr
 * @param {int} mtp
 * @param {int} raceNumber
 * @param {object} raceStatus
 * @param {object} mtpDisplay
 * @param {date} postTime
 */
function FeaturedTrackRace(trackName, trackAbbr, perfAbbr, country, mtp, raceNumber, raceStatus, mtpDisplay, postTime) {
  _classCallCheck(this, FeaturedTrackRace);

  this.trackName = trackName;
  this.trackAbbr = trackAbbr;
  this.perfAbbr = perfAbbr;
  this.country = country;
  this.mtp = mtp;
  this.raceNumber = raceNumber;
  this.raceStatus = raceStatus;
  this.mtpDisplay = mtpDisplay;
  this.postTime = postTime;
  this.raceId = trackAbbr + '_' + raceNumber;
  this.id = trackAbbr + '_' + perfAbbr + '_' + raceNumber;
};

var FeaturedTrack =
/**
 *
 * @param {string} trackAbbr
 * @param {array} races
 */
function FeaturedTrack(trackAbbr, races) {
  _classCallCheck(this, FeaturedTrack);

  this.trackAbbr = trackAbbr;
  this.races = races;
};

var FeaturedTracks = function (_GraphQLSubscribeInte) {
  _inherits(FeaturedTracks, _GraphQLSubscribeInte);

  function FeaturedTracks() {
    _classCallCheck(this, FeaturedTracks);

    return _possibleConstructorReturn(this, (FeaturedTracks.__proto__ || Object.getPrototypeOf(FeaturedTracks)).apply(this, arguments));
  }

  _createClass(FeaturedTracks, [{
    key: 'get',


    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {array} favorites
     * @returns {Promise.<T>}
     */
    value: function get(wagerProfile, filterBy) {
      var _this2 = this;

      var options = {
        wagerProfile: wagerProfile,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(FeaturedTracks.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = FeaturedTracks.buildQuery(_this2.options.wagerProfile);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(FeaturedTracks.verifyNotFoundResult).then(function (result) {
        return result.data.tracks;
      }).then(function (tracks) {
        return FeaturedTracks.buildFeatureTracks(tracks);
      });
    }

    /**
     * Subscribes to graphql query
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {Object} Observable
     */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        this.options = FeaturedTracks.verifyValidOptions(options);
        graphQuery = FeaturedTracks.buildQuery(this.options.wagerProfile);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(FeaturedTracks.prototype.__proto__ || Object.getPrototypeOf(FeaturedTracks.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(FeaturedTracks.verifyNotFoundResult(results)).then(function (result) {
          return result.data.tracks;
        }).then(FeaturedTracks.buildFeatureTracks).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(FeaturedTracks.prototype.__proto__ || Object.getPrototypeOf(FeaturedTracks.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(FeaturedTracks.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        var queryVariables = {
          filterBy: queryOptions.filterBy,
          wagerProfile: queryOptions.wagerProfile
        };

        return _get(FeaturedTracks.prototype.__proto__ || Object.getPrototypeOf(FeaturedTracks.prototype), 'refetch', _this4).call(_this4, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(FeaturedTracks.verifyNotFoundResult).then(function (result) {
          return result.data.tracks;
        }).then(function (tracks) {
          return FeaturedTracks.buildFeatureTracks(tracks);
        });
      });
    }
  }], [{
    key: 'buildFeatureTracks',


    /**
     *  Builds array with FeaturedTrack from graphql result
     * @param {Array} result
     * @returns {FeaturedTrack|Array}
     */
    value: function buildFeatureTracks(result) {
      var featureTracks = [];
      var _iteratorNormalCompletion = true;
      var _didIteratorError = false;
      var _iteratorError = undefined;

      try {
        for (var _iterator = result[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var track = _step.value;

          if (track.races && track.races.length > 0) {
            var racesArray = [];

            var _iteratorNormalCompletion2 = true;
            var _didIteratorError2 = false;
            var _iteratorError2 = undefined;

            try {
              for (var _iterator2 = track.races[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                var race = _step2.value;

                var featuredTrackRace = new FeaturedTrackRace(track.name, track.code, track.perfAbbr, track.location ? track.location.country : null, race.mtp, race.number, race.status, _utils2.default.mtpDisplay(race.postTime, race.mtp), race.postTime);
                racesArray.push(featuredTrackRace);
              }
            } catch (err) {
              _didIteratorError2 = true;
              _iteratorError2 = err;
            } finally {
              try {
                if (!_iteratorNormalCompletion2 && _iterator2.return) {
                  _iterator2.return();
                }
              } finally {
                if (_didIteratorError2) {
                  throw _iteratorError2;
                }
              }
            }

            var featuredTrack = new FeaturedTrack(track.code, racesArray);
            featureTracks.push(featuredTrack);
          }
        }
      } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator.return) {
            _iterator.return();
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError;
          }
        }
      }

      return featureTracks;
    }

    /**
     * Builds graphql query
     * @param {string} wagerProfile
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        featured: { featured: true },
        sortBy: { byMTP: 'ASC' },
        filterBy: { hasMTP: true, isOpen: true },
        wagerProfile: wagerProfile
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      // Add filter hasMTP and iOpen by default
      Object.assign(filterBy, { hasMTP: true, isOpen: true });

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the options');
      }

      var _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$filterBy = options.filterBy,
          filterBy = _options$filterBy === undefined ? {} : _options$filterBy;


      return {
        wagerProfile: wagerProfile,
        filterBy: FeaturedTracks.prepareFilters(filterBy)
      };
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('Featured Tracks not found');
      }
      return result;
    }
  }]);

  return FeaturedTracks;
}(_client.GraphQLSubscribeInterface);

exports.default = FeaturedTracks;

/***/ }),
/* 57 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _featuredTracks = __webpack_require__(56);

var _featuredTracks2 = _interopRequireDefault(_featuredTracks);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _featuredTracks2.default;

/***/ }),
/* 58 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getFullScheduleRaces(\n        $wagerProfile: String,\n        $sortBy: RaceListSort,\n        $filterBy: RaceListFilter,\n        $pagination: Pagination) {\n          races (sort: $sortBy, filter: $filterBy, profile: $wagerProfile, page: $pagination) {\n            number\n            distance\n            numRunners\n            postTime\n            mtp\n            isGreyhound\n            track {\n              code\n              name\n              featured\n              perfAbbr\n              location {\n                country\n              }\n            }\n            raceClass {\n              id\n              name\n            }\n            surface {\n              id\n              code\n              name\n            }\n            video {\n              onTvg\n              onTvg2\n              liveStreaming\n              hasReplay\n              streams\n              replays\n            }\n          }\n        }'], ['\n      query getFullScheduleRaces(\n        $wagerProfile: String,\n        $sortBy: RaceListSort,\n        $filterBy: RaceListFilter,\n        $pagination: Pagination) {\n          races (sort: $sortBy, filter: $filterBy, profile: $wagerProfile, page: $pagination) {\n            number\n            distance\n            numRunners\n            postTime\n            mtp\n            isGreyhound\n            track {\n              code\n              name\n              featured\n              perfAbbr\n              location {\n                country\n              }\n            }\n            raceClass {\n              id\n              name\n            }\n            surface {\n              id\n              code\n              name\n            }\n            video {\n              onTvg\n              onTvg2\n              liveStreaming\n              hasReplay\n              streams\n              replays\n            }\n          }\n        }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Full Schedule Races module
                                                                                                                                                           * @module FullScheduleRaces
                                                                                                                                                           */


var FullScheduleModel =
/**
 * FullScheduleModel
 * @param code
 * @param name
 * @param perf
 * @param country
 * @param number
 * @param postTime
 * @param mtp
 * @param runners
 * @param distance
 * @param raceClass
 * @param surfaceName
 * @param onTvg
 * @param liveStreaming
 * @param featured
 */
function FullScheduleModel(code, name, perf, country, number, postTime, mtp, runners, distance, raceClass, surfaceName, onTvg, onTvg2, liveStreaming, featured, isGreyhound) {
  _classCallCheck(this, FullScheduleModel);

  this.trackAbbr = code;
  this.trackName = name;
  this.perfAbbr = perf;
  this.country = country;
  this.raceNumber = number;
  this.postTime = postTime;
  this.MTP = mtp;
  this.runners = runners;
  this.distance = distance;
  this.raceClass = raceClass;
  this.surfaceName = surfaceName;
  this.onTvg = onTvg; // its on the video
  this.onTvg2 = onTvg2; // its on the video
  this.liveStreaming = liveStreaming; // its on the video
  this.featured = featured;
  this.raceId = code + '_' + number;
  this.id = code + '_' + perf + '_' + number;
  this.isGreyhound = isGreyhound;
};

var FullScheduleRaces = function (_GraphQLSubscribeInte) {
  _inherits(FullScheduleRaces, _GraphQLSubscribeInte);

  function FullScheduleRaces() {
    _classCallCheck(this, FullScheduleRaces);

    return _possibleConstructorReturn(this, (FullScheduleRaces.__proto__ || Object.getPrototypeOf(FullScheduleRaces)).apply(this, arguments));
  }

  _createClass(FullScheduleRaces, [{
    key: 'get',


    /**
     * Makes a single request to graph with the given query and options
     * @param options
     * @returns {Promise}
     */
    value: function get(options) {
      var _this2 = this;

      return Promise.resolve(options).then(FullScheduleRaces.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = FullScheduleRaces.buildQuery(_this2.options);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(FullScheduleRaces.verifyNotFoundResult).then(function (result) {
        return options.rawData ? result.data : FullScheduleRaces.buildRaces(result.data.races);
      });
    }

    /**
     * Starts a subscription running a given query on a poller
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {*}
     */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;

      try {
        this.options = FullScheduleRaces.verifyValidOptions(options);
        graphQuery = FullScheduleRaces.buildQuery(this.options);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(FullScheduleRaces.prototype.__proto__ || Object.getPrototypeOf(FullScheduleRaces.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(FullScheduleRaces.verifyNotFoundResult(results)).then(function (result) {
          return options.rawData ? result.data : FullScheduleRaces.buildRaces(result.data.races);
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(FullScheduleRaces.prototype.__proto__ || Object.getPrototypeOf(FullScheduleRaces.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     * Refetched the subscription with new options
     * @param options
     * @returns {*}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(FullScheduleRaces.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;

        return _get(FullScheduleRaces.prototype.__proto__ || Object.getPrototypeOf(FullScheduleRaces.prototype), 'refetch', _this4).call(_this4, _this4.options)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(FullScheduleRaces.verifyNotFoundResult).then(function (result) {
          return options.rawData ? result.data : FullScheduleRaces.buildRaces(result.data.races);
        });
      });
    }
  }], [{
    key: 'buildRaces',


    /**
     *  Builds array with FullScheduleModel from raceData
     * @param {Array} raceData
     * @returns {FullScheduleModel|Array}
     */
    value: function buildRaces(raceData) {
      return raceData.map(function (race) {
        return new FullScheduleModel(race.track.code, race.track.name, race.track.perfAbbr, race.track.location ? race.track.location.country : null, race.number, new Date(race.postTime), race.mtp, race.numRunners, race.distance, race.raceClass.name, race.surface.name, race.video ? race.video.onTvg : false, race.video ? race.video.onTvg2 : false, race.video ? race.video.liveStreaming : false, race.track.featured, race.isGreyhound);
      });
    }
  }, {
    key: 'buildQuery',
    value: function buildQuery(options) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      return {
        string: queryString,
        variables: this.buildOptions(options)
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      // Add filter hasMTP and iOpen by default
      Object.assign(filterBy, { hasMTP: true, isOpen: true });

      // Remove empty typeCode filter
      if (filterBy && filterBy.typeCode && filterBy.typeCode.length === 0) {
        delete filterBy.typeCode;
      }

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the options');
      }

      var _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$filterBy = options.filterBy,
          filterBy = _options$filterBy === undefined ? {} : _options$filterBy;


      return {
        wagerProfile: wagerProfile,
        filterBy: FullScheduleRaces.prepareFilters(filterBy)
      };
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('Featured Tracks not found');
      }
      return result;
    }

    /**
     * Builds an options object with defaults
     * @param obj
     * @returns {{wagerProfile: string, filterBy: {isOpen: boolean}, sortBy: {byPostTime: string}, pagination: *}}
     */

  }, {
    key: 'buildOptions',
    value: function buildOptions(obj) {
      var _obj$wagerProfile = obj.wagerProfile,
          wagerProfile = _obj$wagerProfile === undefined ? 'PORT-Generic' : _obj$wagerProfile,
          _obj$filterBy = obj.filterBy,
          filterBy = _obj$filterBy === undefined ? { isOpen: true } : _obj$filterBy,
          _obj$sortBy = obj.sortBy,
          sortBy = _obj$sortBy === undefined ? { byPostTime: 'ASC' } : _obj$sortBy,
          pagination = obj.pagination;


      return { wagerProfile: wagerProfile, filterBy: filterBy, sortBy: sortBy, pagination: pagination };
    }
  }]);

  return FullScheduleRaces;
}(_client.GraphQLSubscribeInterface);

exports.default = FullScheduleRaces;

/***/ }),
/* 59 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _fullScheduleRaces = __webpack_require__(58);

var _fullScheduleRaces2 = _interopRequireDefault(_fullScheduleRaces);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _fullScheduleRaces2.default;

/***/ }),
/* 60 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['query getFullScheduleTracks(\n    $wagerProfile: String,\n    $trackSortBy: TrackListSort,\n    $trackFilterBy: TrackListFilter,\n    $raceSortBy: RaceListSort,\n    $raceFilterBy: RaceListFilter\n    ){\n      tracks(\n      sort: $trackSortBy,\n      profile: $wagerProfile,\n      filter: $trackFilterBy,\n      ) {\n        code\n        name\n        perfAbbr\n        location {\n          country\n        }\n        races (\n          sort: $raceSortBy,\n          filter: $raceFilterBy\n        ) {\n          number\n          postTime\n          video {\n            onTvg\n            onTvg2\n            liveStreaming\n            hasReplay\n          }\n          status {\n            code\n          }\n        }\n      }\n    }'], ['query getFullScheduleTracks(\n    $wagerProfile: String,\n    $trackSortBy: TrackListSort,\n    $trackFilterBy: TrackListFilter,\n    $raceSortBy: RaceListSort,\n    $raceFilterBy: RaceListFilter\n    ){\n      tracks(\n      sort: $trackSortBy,\n      profile: $wagerProfile,\n      filter: $trackFilterBy,\n      ) {\n        code\n        name\n        perfAbbr\n        location {\n          country\n        }\n        races (\n          sort: $raceSortBy,\n          filter: $raceFilterBy\n        ) {\n          number\n          postTime\n          video {\n            onTvg\n            onTvg2\n            liveStreaming\n            hasReplay\n          }\n          status {\n            code\n          }\n        }\n      }\n    }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Full Schedule Tracks module
                                                                                                                                                           * @module FullScheduleTracks
                                                                                                                                                           */


var RaceModel =
/**
 *
 * @param {string} trackAbbr
 * @param {string} trackName
 * @param {int} raceNumber
 * @param {string} perfAbbr
 * @param {string} country
 * @param {int} postTime
 * @param {boolean} isFavorite
 */
function RaceModel(trackAbbr, trackName, raceNumber, perfAbbr, country, postTime) {
  _classCallCheck(this, RaceModel);

  this.trackAbbr = trackAbbr;
  this.trackName = trackName;
  this.raceNumber = raceNumber;
  this.postTime = new Date(postTime);
  this.perfAbbr = perfAbbr;
  this.country = country;
  this.raceId = trackAbbr + '_' + raceNumber;
  this.id = trackAbbr + '_' + perfAbbr + '_' + raceNumber;
};

var TrackModel =
/**
 *
 * @param {string} trackAbbr
 * @param {array} races
 */
function TrackModel(trackAbbr, trackName, liveStreaming, races) {
  _classCallCheck(this, TrackModel);

  this.trackAbbr = trackAbbr;
  this.trackName = trackName;
  this.liveStreaming = liveStreaming;
  this.races = races;
};

var FullScheduleTracks = function (_GraphQLSubscribeInte) {
  _inherits(FullScheduleTracks, _GraphQLSubscribeInte);

  function FullScheduleTracks() {
    _classCallCheck(this, FullScheduleTracks);

    return _possibleConstructorReturn(this, (FullScheduleTracks.__proto__ || Object.getPrototypeOf(FullScheduleTracks)).apply(this, arguments));
  }

  _createClass(FullScheduleTracks, [{
    key: 'get',


    /**
     * Gets query result from graphql
     * @param options
     * @returns {Promise.<T>}
     */
    value: function get(options) {
      var _this2 = this;

      return Promise.resolve(options).then(FullScheduleTracks.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = FullScheduleTracks.buildQuery(_this2.options.wagerProfile, _this2.options.trackFilterBy);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(FullScheduleTracks.verifyNotFoundResult).then(function (result) {
        return result.data.tracks;
      }).then(function (tracks) {
        return FullScheduleTracks.buildTracks(tracks);
      });
    }

    /**
     * Subscribes to graphql query
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {Object} Observable
     */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        this.options = FullScheduleTracks.verifyValidOptions(options);
        graphQuery = FullScheduleTracks.buildQuery(this.options.wagerProfile, this.options.trackFilterBy);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(FullScheduleTracks.prototype.__proto__ || Object.getPrototypeOf(FullScheduleTracks.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(FullScheduleTracks.verifyNotFoundResult(results)).then(function (result) {
          return result.data.tracks;
        }).then(FullScheduleTracks.buildTracks).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(FullScheduleTracks.prototype.__proto__ || Object.getPrototypeOf(FullScheduleTracks.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(FullScheduleTracks.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;

        return _get(FullScheduleTracks.prototype.__proto__ || Object.getPrototypeOf(FullScheduleTracks.prototype), 'refetch', _this4).call(_this4, _this4.options)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(FullScheduleTracks.verifyNotFoundResult).then(function (result) {
          return result.data.tracks;
        }).then(function (tracks) {
          return FullScheduleTracks.buildTracks(tracks);
        });
      });
    }
  }], [{
    key: 'buildTracks',


    /**
     *  Builds array with Track from graphql result
     * @param {Array} result
     * @returns {TrackModel|Array}
     */
    value: function buildTracks(tracks) {
      var trackList = [];
      var _iteratorNormalCompletion = true;
      var _didIteratorError = false;
      var _iteratorError = undefined;

      try {
        for (var _iterator = tracks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var track = _step.value;

          if (track.races && track.races.length > 0) {
            var racesArray = [];
            var liveStreaming = false;

            var _iteratorNormalCompletion2 = true;
            var _didIteratorError2 = false;
            var _iteratorError2 = undefined;

            try {
              for (var _iterator2 = track.races[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                var race = _step2.value;

                var raceModel = new RaceModel(track.code, track.name, race.number, track.perfAbbr, track.location ? track.location.country : null, race.postTime);
                racesArray.push(raceModel);
                if (race.video && race.video.liveStreaming) {
                  liveStreaming = true;
                }
              }
            } catch (err) {
              _didIteratorError2 = true;
              _iteratorError2 = err;
            } finally {
              try {
                if (!_iteratorNormalCompletion2 && _iterator2.return) {
                  _iterator2.return();
                }
              } finally {
                if (_didIteratorError2) {
                  throw _iteratorError2;
                }
              }
            }

            var trackModel = new TrackModel(track.code, track.name, liveStreaming, racesArray);
            trackList.push(trackModel);
          }
        }
      } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator.return) {
            _iterator.return();
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError;
          }
        }
      }

      return trackList;
    }

    /**
     * Builds graphql query
     * @param {string} wagerProfile
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile, trackFilterBy) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      // Remove empty typeCode filter
      if (trackFilterBy && trackFilterBy.code && trackFilterBy.code.length === 0) {
        delete trackFilterBy.code;
      }

      var queryVariables = {
        trackSortBy: { byName: 'ASC' },
        raceSortBy: { byMTP: 'ASC' },
        raceFilterBy: { hasMTP: true, isOpen: true },
        trackFilterBy: trackFilterBy,
        wagerProfile: wagerProfile
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      // Add filter hasMTP and iOpen by default
      Object.assign(filterBy, { hasMTP: true, isOpen: true });

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the options');
      }

      var _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$filterBy = options.filterBy,
          filterBy = _options$filterBy === undefined ? {} : _options$filterBy;


      return {
        wagerProfile: wagerProfile,
        filterBy: FullScheduleTracks.prepareFilters(filterBy)
      };
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('Featured Tracks not found');
      }
      return result;
    }
  }]);

  return FullScheduleTracks;
}(_client.GraphQLSubscribeInterface);

exports.default = FullScheduleTracks;

/***/ }),
/* 61 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _fullScheduleTracks = __webpack_require__(60);

var _fullScheduleTracks2 = _interopRequireDefault(_fullScheduleTracks);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _fullScheduleTracks2.default;

/***/ }),
/* 62 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _templateObject = _taggedTemplateLiteral(['\n      query getPastRunnersName(\n        $horseName: String!\n      ) {\n        pastRunnersName(runnerName: $horseName)\n      }\n    '], ['\n      query getPastRunnersName(\n        $horseName: String!\n      ) {\n        pastRunnersName(runnerName: $horseName)\n      }\n    ']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * HorseSearch module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module HorseSearch
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */

var HorseSearch = function (_GraphQLSubscribeInte) {
  _inherits(HorseSearch, _GraphQLSubscribeInte);

  function HorseSearch() {
    _classCallCheck(this, HorseSearch);

    return _possibleConstructorReturn(this, (HorseSearch.__proto__ || Object.getPrototypeOf(HorseSearch)).apply(this, arguments));
  }

  _createClass(HorseSearch, [{
    key: 'getHorsesByName',


    /**
     * Gets query result from graphql
     * @param {string} date
     * @returns {Promise.<T>}
     */
    value: function getHorsesByName(horseName) {
      var _this2 = this;

      var options = {
        horseName: horseName
      };

      return Promise.resolve(options).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = HorseSearch.buildQuery(_this2.options.horseName);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(function (result) {
        return result.data.pastRunnersName;
      });
    }
  }], [{
    key: 'buildQuery',

    /**
     * Builds graphql query
     * @param {string} date
     * @returns {}
     */
    value: function buildQuery(horseName) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        horseName: horseName
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }
  }]);

  return HorseSearch;
}(_client.GraphQLSubscribeInterface);

exports.default = HorseSearch;

/***/ }),
/* 63 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _horseSearch = __webpack_require__(62);

var _horseSearch2 = _interopRequireDefault(_horseSearch);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _horseSearch2.default;

/***/ }),
/* 64 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _leftBarTracks = __webpack_require__(65);

var _leftBarTracks2 = _interopRequireDefault(_leftBarTracks);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _leftBarTracks2.default;

/***/ }),
/* 65 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['query getLeftBarTracks(\n    $wagerProfile: String,\n    $sortBy: RaceListSort,\n    $filterFeatureBy: TrackListFilter,\n    $filterFavoriteBy: TrackListFilter,\n    $filterByNextOpenRaces: RaceListFilter,\n    $filterByOnTvg: RaceListFilter,\n    $filterByOnTvg2: RaceListFilter,\n    $filterBy: RaceListFilter,\n    $page: Pagination\n    $pageNext: Pagination\n    ){\n      featured:\n      tracks(\n      filter: $filterFeatureBy,\n      profile: $wagerProfile,\n      ) {\n        code\n        name\n        perfAbbr\n        featured\n        races (\n          sort: $sortBy,\n          filter: $filterBy\n        ) {\n          number\n          mtp\n          postTime\n          status {\n            code\n          }\n        }\n      }\n      favorites:\n      tracks(\n      filter: $filterFavoriteBy,\n      profile: $wagerProfile\n      ) {\n        code\n        name\n        perfAbbr\n        featured\n        races (\n          sort: $sortBy,\n          filter: $filterBy\n        ) {\n          number\n          mtp\n          postTime\n          status {\n            code\n          }\n        }\n      }\n      onTvg:\n      races (\n        sort: $sortBy\n        filter: $filterByOnTvg\n        page: $page\n        profile: $wagerProfile\n      ) {\n        track {\n          code\n          perfAbbr\n          name\n        }\n        number\n        mtp\n        postTime\n        status {\n          code\n        }\n        video{\n          onTvg\n          liveStreaming\n        }\n      }\n      onTvg2:\n      races (\n        sort: $sortBy\n        filter: $filterByOnTvg2\n        page: $page\n        profile: $wagerProfile\n      ) {\n        track {\n          code\n          perfAbbr\n          name\n        }\n        number\n        mtp\n        postTime\n        status {\n          code\n        }\n        video{\n          onTvg2\n          liveStreaming\n        }\n      }\n      nextRaces:\n      races (\n        sort: $sortBy\n        page: $pageNext\n        profile: $wagerProfile\n        filter: $filterByNextOpenRaces\n      ) {\n        track {\n          code\n          perfAbbr\n          name\n        }\n        number\n        mtp\n        postTime\n        status {\n          code\n        }\n        video{\n          liveStreaming\n        }\n      }\n    }'], ['query getLeftBarTracks(\n    $wagerProfile: String,\n    $sortBy: RaceListSort,\n    $filterFeatureBy: TrackListFilter,\n    $filterFavoriteBy: TrackListFilter,\n    $filterByNextOpenRaces: RaceListFilter,\n    $filterByOnTvg: RaceListFilter,\n    $filterByOnTvg2: RaceListFilter,\n    $filterBy: RaceListFilter,\n    $page: Pagination\n    $pageNext: Pagination\n    ){\n      featured:\n      tracks(\n      filter: $filterFeatureBy,\n      profile: $wagerProfile,\n      ) {\n        code\n        name\n        perfAbbr\n        featured\n        races (\n          sort: $sortBy,\n          filter: $filterBy\n        ) {\n          number\n          mtp\n          postTime\n          status {\n            code\n          }\n        }\n      }\n      favorites:\n      tracks(\n      filter: $filterFavoriteBy,\n      profile: $wagerProfile\n      ) {\n        code\n        name\n        perfAbbr\n        featured\n        races (\n          sort: $sortBy,\n          filter: $filterBy\n        ) {\n          number\n          mtp\n          postTime\n          status {\n            code\n          }\n        }\n      }\n      onTvg:\n      races (\n        sort: $sortBy\n        filter: $filterByOnTvg\n        page: $page\n        profile: $wagerProfile\n      ) {\n        track {\n          code\n          perfAbbr\n          name\n        }\n        number\n        mtp\n        postTime\n        status {\n          code\n        }\n        video{\n          onTvg\n          liveStreaming\n        }\n      }\n      onTvg2:\n      races (\n        sort: $sortBy\n        filter: $filterByOnTvg2\n        page: $page\n        profile: $wagerProfile\n      ) {\n        track {\n          code\n          perfAbbr\n          name\n        }\n        number\n        mtp\n        postTime\n        status {\n          code\n        }\n        video{\n          onTvg2\n          liveStreaming\n        }\n      }\n      nextRaces:\n      races (\n        sort: $sortBy\n        page: $pageNext\n        profile: $wagerProfile\n        filter: $filterByNextOpenRaces\n      ) {\n        track {\n          code\n          perfAbbr\n          name\n        }\n        number\n        mtp\n        postTime\n        status {\n          code\n        }\n        video{\n          liveStreaming\n        }\n      }\n    }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _utils = __webpack_require__(14);

var _utils2 = _interopRequireDefault(_utils);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Left Bar Tracks module
                                                                                                                                                           * @module LeftBarTracks
                                                                                                                                                           */


var LeftBarRace =
/**
 *
 * @param {string} trackName
 * @param {string} trackAbbr
 * @param {string} perfAbbr
 * @param {int} mtp
 * @param {int} raceNumber
 * @param {object} raceStatus
 * @param {object} mtpDisplay
 */
function LeftBarRace(trackName, trackAbbr, perfAbbr, mtp, raceNumber, raceStatus, mtpDisplay, postTime) {
  _classCallCheck(this, LeftBarRace);

  this.trackName = trackName;
  this.trackAbbr = trackAbbr;
  this.perfAbbr = perfAbbr;
  this.mtp = mtp;
  this.raceNumber = raceNumber;
  this.raceStatus = raceStatus;
  this.mtpDisplay = mtpDisplay;
  this.raceId = trackAbbr + '_' + raceNumber;
  this.postTime = postTime;
};

var LeftBarTrack =
/**
 *
 * @param {string} trackAbbr
 * @param {array} races
 */
function LeftBarTrack(trackAbbr, races) {
  _classCallCheck(this, LeftBarTrack);

  this.trackAbbr = trackAbbr;
  this.races = races;
};

var LeftBarTracks = function (_GraphQLSubscribeInte) {
  _inherits(LeftBarTracks, _GraphQLSubscribeInte);

  function LeftBarTracks() {
    _classCallCheck(this, LeftBarTracks);

    return _possibleConstructorReturn(this, (LeftBarTracks.__proto__ || Object.getPrototypeOf(LeftBarTracks)).apply(this, arguments));
  }

  _createClass(LeftBarTracks, [{
    key: 'get',


    /**
     * Gets query result from graphql
     * @param wagerProfile
     * @param filterFavoriteBy
     * @param pageNext
     * @returns {Promise.<TResult>|*}
     */
    value: function get(wagerProfile, filterFavoriteBy) {
      var _this2 = this;

      var pageNext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { current: 0, results: 3 };

      var options = {
        wagerProfile: wagerProfile,
        filterFavoriteBy: filterFavoriteBy,
        pageNext: pageNext
      };

      return Promise.resolve(options).then(LeftBarTracks.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = LeftBarTracks.buildQuery(_this2.options.wagerProfile, _this2.options.filterFavoriteBy, _this2.options.pageNext);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(LeftBarTracks.verifyNotFoundResult).then(LeftBarTracks.buildLeftBarTracks);
    }

    /**
     * Subscribes to graphql query
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {Object} Observable
     */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        this.options = LeftBarTracks.verifyValidOptions(options);
        graphQuery = LeftBarTracks.buildQuery(this.options.wagerProfile, this.options.filterFavoriteBy, this.options.pageNext);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(LeftBarTracks.prototype.__proto__ || Object.getPrototypeOf(LeftBarTracks.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(LeftBarTracks.verifyNotFoundResult(results)).then(LeftBarTracks.buildLeftBarTracks).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(LeftBarTracks.prototype.__proto__ || Object.getPrototypeOf(LeftBarTracks.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(LeftBarTracks.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        return _get(LeftBarTracks.prototype.__proto__ || Object.getPrototypeOf(LeftBarTracks.prototype), 'refetch', _this4).call(_this4, queryOptions)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(LeftBarTracks.verifyNotFoundResult).then(LeftBarTracks.buildLeftBarTracks);
      });
    }
  }], [{
    key: 'buildLeftBarTracks',


    /**
     *  Builds array with leftBarTracks from graphql result
     * @param {Array} result
     * @returns {FeaturedTrack|Array}
     */
    value: function buildLeftBarTracks(result) {
      var featureTracks = [];
      var favoriteTracks = [];
      var nextRaces = [];

      if (!result.data.favorites.length && !result.data.featured.length && !result.data.onTvg.length && !result.data.onTvg2.length) {
        return { message: 'NoResults' };
      }

      var newLeftBarRace = function newLeftBarRace(track, race) {
        return new LeftBarRace(track.name, track.code, track.perfAbbr, race.mtp, race.number, race.status, _utils2.default.mtpDisplay(race.postTime, race.mtp), race.postTime);
      };
      var parseTracks = function parseTracks(tracks) {
        var tracksArray = [];
        tracks.forEach(function (track) {
          if (track.races && track.races.length) {
            var racesArray = [];
            track.races.forEach(function (race) {
              racesArray.push(newLeftBarRace(track, race));
            });
            tracksArray.push(new LeftBarTrack(track.code, racesArray));
          }
        });

        return tracksArray;
      };

      var parseRaces = function parseRaces(races) {
        var racesArray = [];
        races.forEach(function (race) {
          racesArray.push(newLeftBarRace(race.track, race));
        });
        return racesArray;
      };

      featureTracks = parseTracks(result.data.featured);
      favoriteTracks = parseTracks(result.data.favorites);
      nextRaces = parseRaces(result.data.nextRaces);
      var onTvg = result.data.onTvg.length ? newLeftBarRace(result.data.onTvg[0].track, result.data.onTvg[0]) : null;
      var onTvg2 = result.data.onTvg2.length ? newLeftBarRace(result.data.onTvg2[0].track, result.data.onTvg2[0]) : null;

      return {
        nextRaces: nextRaces,
        featureTracks: featureTracks,
        favoriteTracks: favoriteTracks,
        onTvg: onTvg,
        onTvg2: onTvg2
      };
    }

    /**
     * Builds graphql query
     * @param {string} wagerProfile
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile) {
      var filterFavoriteBy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var pageNext = arguments[2];

      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        sortBy: { byMTP: 'ASC' },
        filterBy: { status: ['MO', 'O', 'SK', 'IC'] },
        filterByNextOpenRaces: { status: ['MO', 'O', 'IC'] },
        filterFeatureBy: { featured: true },
        pagingOnTvg: { current: 0, results: 1 },
        filterByOnTvg: { onTvg: true },
        filterByOnTvg2: { onTvg2: true },
        page: { current: 0, results: 1 },
        pageNext: pageNext,
        filterFavoriteBy: filterFavoriteBy,
        wagerProfile: wagerProfile
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     *
     * @param result
     * @returns {boolean}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data || !result.data.favorites && !result.data.featured && !result.data.onTvg && !result.data.onTvg2) {
        throw new Error('Races not found');
      }

      return result;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile and trackAbbr in the subscription options');
      }

      var _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$filterFavori = options.filterFavoriteBy,
          filterFavoriteBy = _options$filterFavori === undefined ? { code: [] } : _options$filterFavori,
          pageNext = options.pageNext;


      return {
        wagerProfile: wagerProfile,
        filterFavoriteBy: filterFavoriteBy,
        pageNext: pageNext
      };
    }
  }]);

  return LeftBarTracks;
}(_client.GraphQLSubscribeInterface);

exports.default = LeftBarTracks;

/***/ }),
/* 66 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _nextRaces = __webpack_require__(67);

var _nextRaces2 = _interopRequireDefault(_nextRaces);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _nextRaces2.default;

/***/ }),
/* 67 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n    query getNextRaces(\n      $wagerProfile: String,\n      $sortBy: RaceListSort,\n      $filterBy: RaceListFilter,\n      $page: Pagination\n      ) {\n      races (\n        sort: $sortBy,\n        filter: $filterBy,\n        profile: $wagerProfile,\n        page: $page\n        ) {\n        track {\n          code\n          name\n          perfAbbr\n          location {\n            country\n          }\n        }\n        postTime\n        isGreyhound\n        number\n        type {\n          id\n        },\n      }\n    }'], ['\n    query getNextRaces(\n      $wagerProfile: String,\n      $sortBy: RaceListSort,\n      $filterBy: RaceListFilter,\n      $page: Pagination\n      ) {\n      races (\n        sort: $sortBy,\n        filter: $filterBy,\n        profile: $wagerProfile,\n        page: $page\n        ) {\n        track {\n          code\n          name\n          perfAbbr\n          location {\n            country\n          }\n        }\n        postTime\n        isGreyhound\n        number\n        type {\n          id\n        },\n      }\n    }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Next Races module
                                                                                                                                                           * @module NextRaces
                                                                                                                                                           */


var RaceModel =
/**
 * Returns RaceModel object
 * @param {string} code
 * @param {string} name
 * @param {string} perf
 * @param {string} country
 * @param {int} number
 * @param {int} type
 * @param {bool} favorite
 * @param {Date} postTime
 */
function RaceModel(code, name, perf, country, number, type, favorite, postTime) {
  _classCallCheck(this, RaceModel);

  this.trackAbbr = code;
  this.trackName = name;
  this.perfAbbr = perf;
  this.country = country;
  this.raceNumber = number;
  this.raceTypeId = type;
  this.raceId = code + '_' + number;
  this.isFavorite = favorite;
  this.postTime = postTime;
};

var NextRaces = function (_GraphQLSubscribeInte) {
  _inherits(NextRaces, _GraphQLSubscribeInte);

  function NextRaces() {
    _classCallCheck(this, NextRaces);

    return _possibleConstructorReturn(this, (NextRaces.__proto__ || Object.getPrototypeOf(NextRaces)).apply(this, arguments));
  }

  _createClass(NextRaces, [{
    key: 'get',


    /**
    * Gets query result from graphql
    * @param {string} wagerProfile
    * @param {array} favorites
    * @returns {Promise.<T>}
    */
    value: function get(wagerProfile, favorites, filterBy, page) {
      var _this2 = this;

      var options = {
        wagerProfile: wagerProfile,
        filterBy: filterBy,
        page: page,
        favorites: favorites
      };

      return Promise.resolve(options).then(NextRaces.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = NextRaces.buildQuery(_this2.options.wagerProfile, _this2.options.filterBy, _this2.options.page);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(NextRaces.verifyNotFoundResult).then(function (result) {
        return result.data.races;
      }).then(function (races) {
        return NextRaces.buildRaces(races, _this2.options.favorites);
      });
    }

    /**
     * Subscribes to graphql query
     * @param {object} options {wagerProfile, filterBy}
     * @param {function} callback {success, fail}
     * @param {int} pollInterval (ms)
     * @param {boolean} forceFetch
     * @returns {object} Observable
       */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        this.options = NextRaces.verifyValidOptions(options);
        graphQuery = NextRaces.buildQuery(this.options.wagerProfile, this.options.filterBy, this.options.page);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(NextRaces.prototype.__proto__ || Object.getPrototypeOf(NextRaces.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(NextRaces.verifyNotFoundResult(results)).then(function (result) {
          return result.data.races;
        }, _this3.options.favorites).then(NextRaces.buildRaces).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(NextRaces.prototype.__proto__ || Object.getPrototypeOf(NextRaces.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        }
        callback.fail(error);
      });
    }

    /**
     * Refetches data from graqhpl
     * @param options {wagerProfile, filterBy}
     * @returns {Promise.<T>}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(NextRaces.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        var queryVariables = {
          filterBy: queryOptions.filterBy,
          wagerProfile: queryOptions.wagerProfile
        };

        return _get(NextRaces.prototype.__proto__ || Object.getPrototypeOf(NextRaces.prototype), 'refetch', _this4).call(_this4, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(NextRaces.verifyNotFoundResult).then(function (result) {
          return result.data.races;
        }).then(function (races) {
          return NextRaces.buildRaces(races, _this4.options.favorites);
        });
      });
    }
  }], [{
    key: 'buildRaces',


    /**
     *  Builds array with RaceModels from raceData
     * @param {Array} raceData
     * @returns {RaceModel|Array}
     */
    value: function buildRaces(raceData, favorites) {
      return raceData.map(function (race) {
        return new RaceModel(race.track.code, race.track.name, race.track.perfAbbr, race.track.location ? race.track.location.country : null, race.number, race.type.id, favorites ? favorites.indexOf(race.track.code) !== -1 : false, race.postTime);
      });
    }

    /**
     * Builds graphql query
     * @param {string} wagerProfile
     * @param {object} filterBy {typeCode[]}
     * @param {object} page {current, results}
     * @returns {{string: *, variables: {sortBy: {byMTP: string}, filterBy: {hasMTP: boolean, typeCode: string}, wagerProfile: {string}}}}
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile) {
      var filterBy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var page = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        sortBy: { byMTP: 'ASC' },
        filterBy: filterBy,
        wagerProfile: wagerProfile,
        page: page
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      // Add filter hasMTP and iOpen by default
      Object.assign(filterBy, { hasMTP: true, isOpen: true });

      // Remove empty typeCode filter
      if (filterBy.typeCode && filterBy.typeCode.length === 0) {
        delete filterBy.typeCode;
      }

      // Remove empty trackCode filter
      if (filterBy.trackCode && filterBy.trackCode.length === 0) {
        delete filterBy.trackCode;
      }

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile and trackAbbr in the subscription options');
      }

      var _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$filterBy = options.filterBy,
          filterBy = _options$filterBy === undefined ? {} : _options$filterBy,
          _options$page = options.page,
          page = _options$page === undefined ? { current: 0, results: 8 } : _options$page,
          _options$favorites = options.favorites,
          favorites = _options$favorites === undefined ? [] : _options$favorites;


      return {
        wagerProfile: wagerProfile,
        filterBy: NextRaces.prepareFilters(filterBy),
        page: page,
        favorites: favorites
      };
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('Races not found');
      }

      return result;
    }
  }]);

  return NextRaces;
}(_client.GraphQLSubscribeInterface);

exports.default = NextRaces;

/***/ }),
/* 68 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _pastRaces = __webpack_require__(69);

var _pastRaces2 = _interopRequireDefault(_pastRaces);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _pastRaces2.default;

/***/ }),
/* 69 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _templateObject = _taggedTemplateLiteral(['\n      fragment bettingInterestsFragment on PastRace {\n        bettingInterests {\n          biNumber\n          numberColor\n          saddleColor\n          favorite\n          runners {\n            horseName\n            runnerId\n            weight\n            med\n            trainer\n            age\n            dam\n            ownerName\n            sex\n            scratched\n            jockey\n            damSire\n            sire\n            date\n            dob\n          }\n          morningLineOdds {\n            numerator\n            denominator\n          }\n          currentOdds {\n            numerator\n            denominator\n          }\n        }\n      }\n    '], ['\n      fragment bettingInterestsFragment on PastRace {\n        bettingInterests {\n          biNumber\n          numberColor\n          saddleColor\n          favorite\n          runners {\n            horseName\n            runnerId\n            weight\n            med\n            trainer\n            age\n            dam\n            ownerName\n            sex\n            scratched\n            jockey\n            damSire\n            sire\n            date\n            dob\n          }\n          morningLineOdds {\n            numerator\n            denominator\n          }\n          currentOdds {\n            numerator\n            denominator\n          }\n        }\n      }\n    ']),
    _templateObject2 = _taggedTemplateLiteral(['\n      fragment resultsFragment on PastRace {\n        results {\n          runners {\n            biNumber\n            betAmount\n            runnerNumber\n            finishPosition\n            runnerName\n            winPayoff\n            placePayoff\n            showPayoff\n          }\n          payoffs {\n            wagerAmount\n            selections {\n              payoutAmount\n              selection\n            }\n            wagerType {\n              code\n              name\n            }\n          }\n        }\n      }\n    '], ['\n      fragment resultsFragment on PastRace {\n        results {\n          runners {\n            biNumber\n            betAmount\n            runnerNumber\n            finishPosition\n            runnerName\n            winPayoff\n            placePayoff\n            showPayoff\n          }\n          payoffs {\n            wagerAmount\n            selections {\n              payoutAmount\n              selection\n            }\n            wagerType {\n              code\n              name\n            }\n          }\n        }\n      }\n    ']),
    _templateObject3 = _taggedTemplateLiteral(['\n      fragment pastRacesFragment on PastRace {\n        number\n        description\n        purse\n        date\n        postTime\n        track {\n          code\n          name\n        }\n        surface {\n          code\n          name\n        }\n        distance {\n          value\n          code\n          name\n        }\n        isGreyhound\n        type {\n          id\n          code\n          name\n        }\n        raceClass {\n          code\n          name\n        }\n        video {\n          replayFileName\n        }\n      }\n    '], ['\n      fragment pastRacesFragment on PastRace {\n        number\n        description\n        purse\n        date\n        postTime\n        track {\n          code\n          name\n        }\n        surface {\n          code\n          name\n        }\n        distance {\n          value\n          code\n          name\n        }\n        isGreyhound\n        type {\n          id\n          code\n          name\n        }\n        raceClass {\n          code\n          name\n        }\n        video {\n          replayFileName\n        }\n      }\n    ']),
    _templateObject4 = _taggedTemplateLiteral(['\n      query getPastRaces(\n        $filterBy: PastRaceListFilter\n        $wagerProfile: String!\n        $byDate: Boolean!\n        $byDateTrack: Boolean!\n        $date: String\n        $trackCode: String\n        $byDateTrackNumber: Boolean!\n        $raceNumber: String\n        $byHorseName: Boolean!\n        $runnerName: String\n        $runnerDob: Int\n      ) {\n        pastRacesByDate: pastRaces(\n          filter: $filterBy\n          profile: $wagerProfile\n          date: $date\n          sort:{byPostTime: DESC}\n        ) @include(if: $byDate) {\n          ...pastRacesFragment\n        }\n        pastRacesByDateAndTrack: pastRaces(\n          filter: $filterBy\n          profile: $wagerProfile\n          date: $date\n          trackCode: $trackCode\n          sort:{byPostTime: DESC}\n        ) @include(if: $byDateTrack) {\n          ...pastRacesFragment\n        }\n        pastRaceByDateTrackAndNumber: pastRaces(\n          filter: $filterBy\n          profile: $wagerProfile\n          date: $date\n          trackCode: $trackCode\n          raceNumber: $raceNumber\n          sort:{byPostTime: DESC}\n        ) @include(if: $byDateTrackNumber) {\n          ...pastRacesFragment\n          ...bettingInterestsFragment\n          ...resultsFragment\n        }\n        pastRacesByHorseName: pastRaces(\n          filter: $filterBy\n          runnerName: $runnerName\n          profile: $wagerProfile\n          sort:{byPostTime: DESC}\n          runnerDob: $runnerDob\n        ) @include(if: $byHorseName) {\n          ...pastRacesFragment\n        }\n      }\n    '], ['\n      query getPastRaces(\n        $filterBy: PastRaceListFilter\n        $wagerProfile: String!\n        $byDate: Boolean!\n        $byDateTrack: Boolean!\n        $date: String\n        $trackCode: String\n        $byDateTrackNumber: Boolean!\n        $raceNumber: String\n        $byHorseName: Boolean!\n        $runnerName: String\n        $runnerDob: Int\n      ) {\n        pastRacesByDate: pastRaces(\n          filter: $filterBy\n          profile: $wagerProfile\n          date: $date\n          sort:{byPostTime: DESC}\n        ) @include(if: $byDate) {\n          ...pastRacesFragment\n        }\n        pastRacesByDateAndTrack: pastRaces(\n          filter: $filterBy\n          profile: $wagerProfile\n          date: $date\n          trackCode: $trackCode\n          sort:{byPostTime: DESC}\n        ) @include(if: $byDateTrack) {\n          ...pastRacesFragment\n        }\n        pastRaceByDateTrackAndNumber: pastRaces(\n          filter: $filterBy\n          profile: $wagerProfile\n          date: $date\n          trackCode: $trackCode\n          raceNumber: $raceNumber\n          sort:{byPostTime: DESC}\n        ) @include(if: $byDateTrackNumber) {\n          ...pastRacesFragment\n          ...bettingInterestsFragment\n          ...resultsFragment\n        }\n        pastRacesByHorseName: pastRaces(\n          filter: $filterBy\n          runnerName: $runnerName\n          profile: $wagerProfile\n          sort:{byPostTime: DESC}\n          runnerDob: $runnerDob\n        ) @include(if: $byHorseName) {\n          ...pastRacesFragment\n        }\n      }\n    ']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _moment = __webpack_require__(21);

var _moment2 = _interopRequireDefault(_moment);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * PastRaces module
                                                                                                                                                           * @module PastRace
                                                                                                                                                           */


var PastRacesModel =
/**
 * Returns PastRacesModel object
 */
function PastRacesModel(raceNumber, description, purse, date, postTime, trackCode, trackName, distanceValue, distanceCode, distanceName, surfaceCode, surfaceName, isGreyhound, typeId, typeCode, typeName, classCode, className, video, results, bettingInterests) {
  _classCallCheck(this, PastRacesModel);

  this.raceNumber = raceNumber;
  this.description = description;
  this.purse = purse;
  this.date = date;
  this.postTime = postTime;
  this.trackCode = trackCode;
  this.trackName = trackName;
  this.distanceValue = distanceValue;
  this.distanceCode = distanceCode;
  this.distanceName = distanceName;
  this.surfaceCode = surfaceCode;
  this.surfaceName = surfaceName;
  this.isGreyhound = isGreyhound;
  this.typeId = typeId;
  this.typeCode = typeCode;
  this.typeName = typeName;
  this.classCode = classCode;
  this.className = className;
  this.video = video;

  if (results) {
    this.results = results;
  }

  if (bettingInterests) {
    this.bettingInterests = bettingInterests;
  }
};

var PastRaces = function (_GraphQLSubscribeInte) {
  _inherits(PastRaces, _GraphQLSubscribeInte);

  function PastRaces() {
    _classCallCheck(this, PastRaces);

    return _possibleConstructorReturn(this, (PastRaces.__proto__ || Object.getPrototypeOf(PastRaces)).apply(this, arguments));
  }

  _createClass(PastRaces, [{
    key: 'getRacesByDate',


    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {string} date
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */
    value: function getRacesByDate(wagerProfile, date, filterBy) {
      var _this2 = this;

      var options = {
        wagerProfile: wagerProfile,
        date: date,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastRaces.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = PastRaces.buildQuery(_this2.options.wagerProfile, _this2.options.filterBy, _this2.options.date);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastRaces.verifyNotFoundResult).then(function (result) {
        return result.data.pastRacesByDate;
      }).then(function (pastRaces) {
        return PastRaces.buildPastRaces(pastRaces);
      });
    }

    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {string} date
     * @param {string} trackCode
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */

  }, {
    key: 'getRacesByDateAndTrack',
    value: function getRacesByDateAndTrack(wagerProfile, date, trackCode, filterBy) {
      var _this3 = this;

      var options = {
        wagerProfile: wagerProfile,
        date: date,
        trackCode: trackCode,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastRaces.verifyValidOptions).then(function (queryOptions) {
        _this3.options = queryOptions;
        var graphQuery = PastRaces.buildQuery(_this3.options.wagerProfile, _this3.options.filterBy, _this3.options.date, _this3.options.trackCode);

        return _this3.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastRaces.verifyNotFoundResult).then(function (result) {
        return result.data.pastRacesByDateAndTrack;
      }).then(function (pastRaces) {
        return PastRaces.buildPastRaces(pastRaces);
      });
    }

    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {string} date
     * @param {string} trackCode
     * @param {string} raceNumber
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */

  }, {
    key: 'getRacesByDateAndTrackAndRace',
    value: function getRacesByDateAndTrackAndRace(wagerProfile, date, trackCode, raceNumber, filterBy) {
      var _this4 = this;

      var options = {
        wagerProfile: wagerProfile,
        date: date,
        trackCode: trackCode,
        raceNumber: raceNumber,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastRaces.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        var graphQuery = PastRaces.buildQuery(_this4.options.wagerProfile, _this4.options.filterBy, _this4.options.date, _this4.options.trackCode, _this4.options.raceNumber);

        return _this4.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastRaces.verifyNotFoundResult).then(function (result) {
        return result.data.pastRaceByDateTrackAndNumber;
      }).then(function (pastRaces) {
        return PastRaces.buildPastRaces(pastRaces);
      });
    }

    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {string} runnerName
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */

  }, {
    key: 'getRacesByHorseName',
    value: function getRacesByHorseName(wagerProfile, runnerName, filterBy) {
      var _this5 = this;

      var runnerDob = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined;

      var options = {
        wagerProfile: wagerProfile,
        runnerName: runnerName,
        filterBy: filterBy,
        runnerDob: runnerDob
      };

      return Promise.resolve(options).then(PastRaces.verifyValidOptions).then(function (queryOptions) {
        _this5.options = queryOptions;
        var graphQuery = PastRaces.buildQuery(_this5.options.wagerProfile, _this5.options.filterBy, undefined, undefined, undefined, runnerName, runnerDob);

        return _this5.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastRaces.verifyNotFoundResult).then(function (result) {
        return result.data.pastRacesByHorseName;
      }).then(function (pastRaces) {
        return PastRaces.buildPastRaces(pastRaces);
      });
    }
  }], [{
    key: 'buildPastRaces',

    /**
     *  Builds array with PastRacesModel from pastRacesData
     * @param {Array} pastRacesData
     * @returns {PastRacesModel|Array}
     */
    value: function buildPastRaces(pastRacesData) {
      if (!pastRacesData) {
        return { error: 'Error on graph query' };
      }
      return pastRacesData.map(function (pastRace) {
        return new PastRacesModel(pastRace.number, pastRace.description, pastRace.purse, pastRace.date, pastRace.postTime, pastRace.track.code, pastRace.track.name, pastRace.distance.value, pastRace.distance.code, pastRace.distance.name, pastRace.surface.code, pastRace.surface.name, pastRace.isGreyhound, pastRace.type.id, pastRace.type.code, pastRace.type.name, pastRace.raceClass.code, pastRace.raceClass.name, pastRace.video, pastRace.results, pastRace.bettingInterests);
      });
    }

    /**
     * Builds graphql query
     * @param {string} date
     * @param {string} trackCode
     * @param {string} raceNumber
     * @param {string} runnerName
     * @param {int} runnerDob
     * @returns {}
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile) {
      var filterBy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var date = arguments[2];
      var trackCode = arguments[3];
      var raceNumber = arguments[4];
      var runnerName = arguments[5];
      var runnerDob = arguments[6];

      var bettingInterestsQuery = (0, _graphqlTag2.default)(_templateObject);

      var resultsQuery = (0, _graphqlTag2.default)(_templateObject2);

      var pastRacesQuery = (0, _graphqlTag2.default)(_templateObject3);

      var queryString = (0, _graphqlTag2.default)(_templateObject4);

      var queryVariables = {
        wagerProfile: wagerProfile,
        filterBy: filterBy,
        byDate: !!date && !trackCode && !raceNumber,
        byDateTrack: !!date && !!trackCode && !raceNumber,
        date: date,
        trackCode: trackCode,
        byDateTrackNumber: !!date && !!trackCode && !!raceNumber,
        raceNumber: raceNumber,
        byHorseName: !!runnerName,
        runnerName: runnerName,
        runnerDob: runnerDob
      };

      return {
        string: queryString,
        variables: queryVariables,
        fragments: [bettingInterestsQuery, resultsQuery, pastRacesQuery]
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      if (!filterBy || filterBy.isGreyhound === undefined) {
        return {};
      }

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      var opt = options;

      if (!opt || !opt.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the subscription options');
      }

      // In case the date is not valid redefine to today.
      if (typeof opt.date !== 'undefined' && isNaN(Date.parse(opt.date))) {
        opt.date = (0, _moment2.default)().format('YYYY-MM-DD');
      }

      // Remove empty trackCode prop
      if (!opt.trackCode || opt.trackCode.length === 0) {
        delete opt.trackCode;
      }

      // Remove empty raceNumber prop
      if (!opt.raceNumber || opt.raceNumber.length === 0) {
        delete opt.raceNumber;
      }

      // Remove empty runnerName prop
      if (!opt.runnerName || opt.runnerName.length === 0) {
        delete opt.runnerName;
      }

      // Remove empty runnerDob prop
      if (!opt.runnerDob || opt.runnerDob.length === 0) {
        delete opt.runnerDob;
      }

      opt.filterBy = PastRaces.prepareFilters(opt.filterBy);

      return opt;
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('PastRaces not found');
      }

      return result;
    }
  }]);

  return PastRaces;
}(_client.GraphQLSubscribeInterface);

exports.default = PastRaces;

/***/ }),
/* 70 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _pastTracks = __webpack_require__(71);

var _pastTracks2 = _interopRequireDefault(_pastTracks);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _pastTracks2.default;

/***/ }),
/* 71 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _templateObject = _taggedTemplateLiteral(['\n      fragment trackDatesFragment on PastTrack {\n        dates\n      }\n    '], ['\n      fragment trackDatesFragment on PastTrack {\n        dates\n      }\n    ']),
    _templateObject2 = _taggedTemplateLiteral(['\n      fragment pastTracksFragment on PastTrack {\n        code\n        name\n        location {\n          city\n          state\n          country\n        }\n        imageName\n        imageLink\n      }\n    '], ['\n      fragment pastTracksFragment on PastTrack {\n        code\n        name\n        location {\n          city\n          state\n          country\n        }\n        imageName\n        imageLink\n      }\n    ']),
    _templateObject3 = _taggedTemplateLiteral(['\n      query getPastTracks(\n        $wagerProfile: String!\n        $filterBy: PastTrackListFilter\n        $allTracks: Boolean!\n        $date: String\n        $byDate: Boolean!\n        $trackCode: String\n        $byCode: Boolean!,\n        $withDates: Boolean!\n      ) {\n        allPastTracks: pastTracks(profile: $wagerProfile, filter: $filterBy)\n          @include(if: $allTracks) {\n          ...pastTracksFragment\n        }\n        pastTracksByDate: pastTracks(\n          profile: $wagerProfile\n          filter: $filterBy\n          date: $date\n        ) @include(if: $byDate) {\n          ...pastTracksFragment\n        }\n        pastTrackByTrackCode: pastTracks(\n          profile: $wagerProfile\n          filter: $filterBy\n          trackCode: $trackCode\n        )  {\n          ...pastTracksFragment @include(if: $byCode)\n          ...trackDatesFragment @include(if: $withDates)\n        }\n      }\n    '], ['\n      query getPastTracks(\n        $wagerProfile: String!\n        $filterBy: PastTrackListFilter\n        $allTracks: Boolean!\n        $date: String\n        $byDate: Boolean!\n        $trackCode: String\n        $byCode: Boolean!,\n        $withDates: Boolean!\n      ) {\n        allPastTracks: pastTracks(profile: $wagerProfile, filter: $filterBy)\n          @include(if: $allTracks) {\n          ...pastTracksFragment\n        }\n        pastTracksByDate: pastTracks(\n          profile: $wagerProfile\n          filter: $filterBy\n          date: $date\n        ) @include(if: $byDate) {\n          ...pastTracksFragment\n        }\n        pastTrackByTrackCode: pastTracks(\n          profile: $wagerProfile\n          filter: $filterBy\n          trackCode: $trackCode\n        )  {\n          ...pastTracksFragment @include(if: $byCode)\n          ...trackDatesFragment @include(if: $withDates)\n        }\n      }\n    ']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _moment = __webpack_require__(21);

var _moment2 = _interopRequireDefault(_moment);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * PastTracks module
                                                                                                                                                           * @module PastTrack
                                                                                                                                                           */


var PastTracksModel =
/**
 * Returns PastTracksModel object
 * @param {string} code
 * @param {string} name
 * @param {Array<String>} dates
 * @param {country: string, loction: string, state: string}
 * @param {string} imageLink
 * @param {string} imageName
 */
function PastTracksModel(code, name, dates, location, imageLink, imageName) {
  _classCallCheck(this, PastTracksModel);

  this.code = code;
  this.name = name;
  this.location = location;
  this.imageLink = imageLink;
  this.imageName = imageName;

  if (dates) {
    this.dates = dates;
  }
};

var PastTracks = function (_GraphQLSubscribeInte) {
  _inherits(PastTracks, _GraphQLSubscribeInte);

  function PastTracks() {
    _classCallCheck(this, PastTracks);

    return _possibleConstructorReturn(this, (PastTracks.__proto__ || Object.getPrototypeOf(PastTracks)).apply(this, arguments));
  }

  _createClass(PastTracks, [{
    key: 'getTracksByDate',


    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {string} date
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */
    value: function getTracksByDate(wagerProfile, date, filterBy) {
      var _this2 = this;

      var options = {
        wagerProfile: wagerProfile,
        date: date,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastTracks.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = PastTracks.buildQuery({
          wagerProfile: _this2.options.wagerProfile,
          filterBy: _this2.options.filterBy,
          date: _this2.options.date,
          byDate: true
        });

        return _this2.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastTracks.verifyNotFoundResult).then(function (result) {
        return result.data.pastTracksByDate;
      }).then(function (pastTracks) {
        return PastTracks.buildPastTracks(pastTracks);
      });
    }

    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {string} trackCode
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */

  }, {
    key: 'getTrackDatesByTrackCode',
    value: function getTrackDatesByTrackCode(wagerProfile, trackCode, filterBy) {
      var _this3 = this;

      var options = {
        wagerProfile: wagerProfile,
        trackCode: trackCode,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastTracks.verifyValidOptions).then(function (queryOptions) {
        _this3.options = queryOptions;
        var graphQuery = PastTracks.buildQuery({
          wagerProfile: _this3.options.wagerProfile,
          filterBy: _this3.options.filterBy,
          trackCode: _this3.options.trackCode,
          byCode: true,
          withDates: true
        });

        return _this3.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastTracks.verifyNotFoundResult).then(function (result) {
        return result.data.pastTrackByTrackCode;
      }).then(function (pastTracks) {
        return PastTracks.buildPastTracks(pastTracks);
      });
    }

    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {string} trackCode
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */

  }, {
    key: 'getTrackByTrackCode',
    value: function getTrackByTrackCode(wagerProfile, trackCode, filterBy) {
      var _this4 = this;

      var options = {
        wagerProfile: wagerProfile,
        trackCode: trackCode,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastTracks.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        var graphQuery = PastTracks.buildQuery({
          wagerProfile: _this4.options.wagerProfile,
          filterBy: _this4.options.filterBy,
          trackCode: _this4.options.trackCode,
          byCode: true,
          withDates: false
        });

        return _this4.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastTracks.verifyNotFoundResult).then(function (result) {
        return result.data.pastTrackByTrackCode;
      }).then(function (pastTracks) {
        return PastTracks.buildPastTracks(pastTracks);
      });
    }

    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {object} filterBy
     * @returns {Promise.<T>}
     */

  }, {
    key: 'getAllTracks',
    value: function getAllTracks(wagerProfile, filterBy) {
      var _this5 = this;

      var options = {
        wagerProfile: wagerProfile,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastTracks.verifyValidOptions).then(function (queryOptions) {
        _this5.options = queryOptions;
        var graphQuery = PastTracks.buildQuery({
          wagerProfile: _this5.options.wagerProfile,
          filterBy: _this5.options.filterBy,
          allTracks: true
        });

        return _this5.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastTracks.verifyNotFoundResult).then(function (result) {
        return result.data.allPastTracks;
      }).then(function (pastTracks) {
        return PastTracks.buildPastTracks(pastTracks);
      });
    }

    /**
     * Gets query result from graphql
     * @param wagerProfile
     * @param date
     * @param filterBy
     * @returns {Promise<{allPastTracks: (PastTracksModel|Array), pastTracksByDate: (PastTracksModel|Array)} | never>}
     */

  }, {
    key: 'getAllTracksAndTodays',
    value: function getAllTracksAndTodays(wagerProfile, date, filterBy) {
      var _this6 = this;

      var options = {
        wagerProfile: wagerProfile,
        date: date,
        filterBy: filterBy
      };

      return Promise.resolve(options).then(PastTracks.verifyValidOptions).then(function (queryOptions) {
        _this6.options = queryOptions;
        var graphQuery = PastTracks.buildQuery({
          wagerProfile: _this6.options.wagerProfile,
          filterBy: _this6.options.filterBy,
          allTracks: true,
          byDate: true,
          date: _this6.options.date
        });

        return _this6.graphql.query(graphQuery.string, graphQuery.variables, false, graphQuery.fragments);
      }).then(PastTracks.verifyNotFoundResult).then(function (result) {
        return result.data;
      }).then(function (data) {
        return {
          allPastTracks: PastTracks.buildPastTracks(data.allPastTracks),
          pastTracksByDate: PastTracks.buildPastTracks(data.pastTracksByDate)
        };
      });
    }
  }], [{
    key: 'buildPastTracks',

    /**
     *  Builds array with PastTracksModel from pastTracksData
     * @param {Array} pastTracksData
     * @returns {PastTracksModel|Array}
     */
    value: function buildPastTracks(pastTracksData) {
      return pastTracksData.map(function (pastTrack) {
        return new PastTracksModel(pastTrack.code, pastTrack.name, pastTrack.dates, pastTrack.location, pastTrack.imageLink, pastTrack.imageName);
      });
    }

    /**
     * Builds the query
     * @param queryVariables
     * @returns {{string: *, variables: *, fragments: *[]}}
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery() {
      var queryVariables = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

      var defaultVariables = {
        wagerProfile: 'PORT-Generic',
        filterBy: {},
        allTracks: false,
        byDate: false,
        byCode: false,
        date: '',
        trackCode: '',
        withDates: true
      };

      var variables = Object.assign({}, defaultVariables, queryVariables);

      var trackDatesQuery = (0, _graphqlTag2.default)(_templateObject);

      var pastTracksQuery = (0, _graphqlTag2.default)(_templateObject2);

      var queryString = (0, _graphqlTag2.default)(_templateObject3);

      return {
        string: queryString,
        variables: variables,
        fragments: [trackDatesQuery, pastTracksQuery]
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      if (!filterBy || filterBy.isGreyhound === undefined) {
        return {};
      }

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      var opt = options;

      if (!opt || !opt.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the subscription options');
      }

      // In case the date is not valid redefine to today.
      if (typeof opt.date !== 'undefined' && isNaN(Date.parse(opt.date))) {
        opt.date = (0, _moment2.default)().format('YYYY-MM-DD');
      }

      // remove prop if this is empty or has no value.
      if (!opt.trackCode) {
        delete opt.trackCode;
      }

      opt.filterBy = PastTracks.prepareFilters(opt.filterBy);

      return opt;
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('PastTracks not found');
      }

      return result;
    }
  }]);

  return PastTracks;
}(_client.GraphQLSubscribeInterface);

exports.default = PastTracks;

/***/ }),
/* 72 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _raceBettingInterests = __webpack_require__(73);

var _raceBettingInterests2 = _interopRequireDefault(_raceBettingInterests);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _raceBettingInterests2.default;

/***/ }),
/* 73 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      fragment wagerTypesFragment on Race {\n        wagerTypes {\n          maxWagerAmount\n          minWagerAmount\n          wagerAmounts\n          hasPool\n          poolAmount\n          columnCount\n          legCount\n          minBIsPerLeg\n          maxBIsPerLeg\n          columnType\n          isBox\n          poolsPerBI\n          isKey\n          positionCount\n          isWheel\n          type {\n            id\n            code\n            name\n          }\n        }\n      }'], ['\n      fragment wagerTypesFragment on Race {\n        wagerTypes {\n          maxWagerAmount\n          minWagerAmount\n          wagerAmounts\n          hasPool\n          poolAmount\n          columnCount\n          legCount\n          minBIsPerLeg\n          maxBIsPerLeg\n          columnType\n          isBox\n          poolsPerBI\n          isKey\n          positionCount\n          isWheel\n          type {\n            id\n            code\n            name\n          }\n        }\n      }']),
    _templateObject2 = _taggedTemplateLiteral(['\n      fragment runnersFragment on BettingInterest {\n        runners {\n          horseName\n          runnerId\n          scratched\n          jockey\n        }\n      }'], ['\n      fragment runnersFragment on BettingInterest {\n        runners {\n          horseName\n          runnerId\n          scratched\n          jockey\n        }\n      }']),
    _templateObject3 = _taggedTemplateLiteral(['\n      fragment oddsFragment on BettingInterest {\n        morningLineOdds {\n          numerator\n          denominator\n        }\n        currentOdds {\n          numerator\n          denominator\n        }\n      }'], ['\n      fragment oddsFragment on BettingInterest {\n        morningLineOdds {\n          numerator\n          denominator\n        }\n        currentOdds {\n          numerator\n          denominator\n        }\n      }']),
    _templateObject4 = _taggedTemplateLiteral(['\n      query getRaceBettingInterests(\n        $trackAbbr: String,\n        $raceNumber: String,\n        $wagerProfile: String,\n        $withRunners: Boolean!,\n        $withWagerTypes: Boolean!,\n        $withOdds: Boolean!) {\n          race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n            type {\n              id\n            }\n            ...wagerTypesFragment @include(if: $withWagerTypes)\n            bettingInterests {\n              biNumber\n              numberColor\n              favorite\n              saddleColor\n              ...runnersFragment @include(if: $withRunners)\n              ...oddsFragment @include(if: $withOdds)\n            }\n          }\n        }'], ['\n      query getRaceBettingInterests(\n        $trackAbbr: String,\n        $raceNumber: String,\n        $wagerProfile: String,\n        $withRunners: Boolean!,\n        $withWagerTypes: Boolean!,\n        $withOdds: Boolean!) {\n          race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n            type {\n              id\n            }\n            ...wagerTypesFragment @include(if: $withWagerTypes)\n            bettingInterests {\n              biNumber\n              numberColor\n              favorite\n              saddleColor\n              ...runnersFragment @include(if: $withRunners)\n              ...oddsFragment @include(if: $withOdds)\n            }\n          }\n        }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race Betting Interests Module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Queries the GraphQL to return the betting interests for a particular race
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceBettingInterests
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var RaceBettingInterests = function (_GraphQLSubscribeInte) {
  _inherits(RaceBettingInterests, _GraphQLSubscribeInte);

  function RaceBettingInterests() {
    _classCallCheck(this, RaceBettingInterests);

    return _possibleConstructorReturn(this, (RaceBettingInterests.__proto__ || Object.getPrototypeOf(RaceBettingInterests)).apply(this, arguments));
  }

  _createClass(RaceBettingInterests, [{
    key: 'subscribe',


    /**
     * Polls the graph api to the given query.
     * @param options
     * @param callback
     * @param pollInterval - in milliseconds
     * @param forceFetch
     */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

      var graphQuery = void 0;
      try {
        RaceBettingInterests.verifyValidOptions(options);
        graphQuery = RaceBettingInterests.buildQuery(options);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RaceBettingInterests.prototype.__proto__ || Object.getPrototypeOf(RaceBettingInterests.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch, graphQuery.fragments)(function (results) {
        return Promise.resolve(RaceBettingInterests.verifyNotFoundResult(results)).then(function (result) {
          return result.data;
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RaceBettingInterests.prototype.__proto__ || Object.getPrototypeOf(RaceBettingInterests.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     * Updates the already made subscription with new query variables
     * @param options
     * @returns {Promise}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RaceBettingInterests.verifyValidOptions).then(function () {
        return _get(RaceBettingInterests.prototype.__proto__ || Object.getPrototypeOf(RaceBettingInterests.prototype), 'refetch', _this3).call(_this3, options)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RaceBettingInterests.verifyNotFoundResult).then(function (result) {
          return result.data;
        });
      });
    }

    /**
     * Makes the query, one time, and returns the response
     * @param options
     * @returns {Promise}
     */

  }, {
    key: 'get',
    value: function get(options) {
      var _this4 = this;

      return Promise.resolve(options).then(RaceBettingInterests.verifyValidOptions).then(function () {
        var graphQuery = RaceBettingInterests.buildQuery(options);

        return _this4.graphql.query(graphQuery.string, graphQuery.variables, options.forceFetch, graphQuery.fragments);
      }).then(RaceBettingInterests.verifyNotFoundResult).then(function (result) {
        return result.data;
      });
    }
  }], [{
    key: 'buildQuery',

    /**
     * Builds the query according to the given options
     * @param options
     * @returns {{string: String, variables: Object}}
     */
    value: function buildQuery(options) {
      var wagerTypesQuery = (0, _graphqlTag2.default)(_templateObject);

      var runnersQuery = (0, _graphqlTag2.default)(_templateObject2);

      var oddsQuery = (0, _graphqlTag2.default)(_templateObject3);

      var queryString = (0, _graphqlTag2.default)(_templateObject4);

      var trackAbbr = options.trackAbbr,
          raceNumber = options.raceNumber,
          wagerProfile = options.wagerProfile,
          _options$withOdds = options.withOdds,
          withOdds = _options$withOdds === undefined ? true : _options$withOdds,
          _options$withWagerTyp = options.withWagerTypes,
          withWagerTypes = _options$withWagerTyp === undefined ? true : _options$withWagerTyp,
          _options$withRunners = options.withRunners,
          withRunners = _options$withRunners === undefined ? true : _options$withRunners;


      return {
        string: queryString,
        variables: {
          trackAbbr: trackAbbr,
          raceNumber: raceNumber,
          wagerProfile: wagerProfile,
          withOdds: withOdds,
          withWagerTypes: withWagerTypes,
          withRunners: withRunners
        },
        fragments: [wagerTypesQuery, oddsQuery, runnersQuery]
      };
    }

    /**
     * Takes the result and verifies if there is any error.
     * @param result
     * @returns {boolean}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (result.errors || !result.data || !result.data.race) {
        throw new Error('Race not found');
      }
      return result;
    }

    /**
     * Verifies if the client has the necessary options to perform the query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.trackAbbr || !options.raceNumber || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile, a trackAbbr and a raceNumber in the options');
      }
    }
  }]);

  return RaceBettingInterests;
}(_client.GraphQLSubscribeInterface);

exports.default = RaceBettingInterests;

/***/ }),
/* 74 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _raceEntities = __webpack_require__(75);

var _raceEntities2 = _interopRequireDefault(_raceEntities);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _raceEntities2.default;

/***/ }),
/* 75 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _templateObject = _taggedTemplateLiteral(['\n      fragment searchByHorse on RaceEntities {\n        runners {\n          name\n          dob\n          entityRunnerId\n        }\n      }'], ['\n      fragment searchByHorse on RaceEntities {\n        runners {\n          name\n          dob\n          entityRunnerId\n        }\n      }']),
    _templateObject2 = _taggedTemplateLiteral(['\n      fragment searchByJockey on RaceEntities {\n        jockeys {\n          name\n          dob\n          entityRunnerId\n        }\n      }'], ['\n      fragment searchByJockey on RaceEntities {\n        jockeys {\n          name\n          dob\n          entityRunnerId\n        }\n      }']),
    _templateObject3 = _taggedTemplateLiteral(['\n      fragment searchByTrainer on RaceEntities {\n        trainers {\n          name\n          dob\n          entityRunnerId\n        }\n      }'], ['\n      fragment searchByTrainer on RaceEntities {\n        trainers {\n          name\n          dob\n          entityRunnerId\n        }\n      }']),
    _templateObject4 = _taggedTemplateLiteral(['\n      fragment searchByOwner on RaceEntities {\n        owners {\n          name\n          dob\n          entityRunnerId\n        }\n      }'], ['\n      fragment searchByOwner on RaceEntities {\n        owners {\n          name\n          dob\n          entityRunnerId\n        }\n      }']),
    _templateObject5 = _taggedTemplateLiteral(['\n      query getRaceEntities(\n      $searchText: String!,\n      $horse: Boolean!,\n      $jockey: Boolean!,\n      $trainer: Boolean!,\n      $owner: Boolean!\n      ) {\n        raceEntities(searchText: $searchText) {\n          ...searchByHorse @include(if: $horse)\n          ...searchByJockey @include(if: $jockey)\n          ...searchByTrainer @include(if: $trainer)\n          ...searchByOwner @include(if: $owner)\n        }\n      }'], ['\n      query getRaceEntities(\n      $searchText: String!,\n      $horse: Boolean!,\n      $jockey: Boolean!,\n      $trainer: Boolean!,\n      $owner: Boolean!\n      ) {\n        raceEntities(searchText: $searchText) {\n          ...searchByHorse @include(if: $horse)\n          ...searchByJockey @include(if: $jockey)\n          ...searchByTrainer @include(if: $trainer)\n          ...searchByOwner @include(if: $owner)\n        }\n      }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race Results module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceProgram
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var RaceEntities = function (_GraphQLSubscribeInte) {
  _inherits(RaceEntities, _GraphQLSubscribeInte);

  function RaceEntities() {
    _classCallCheck(this, RaceEntities);

    return _possibleConstructorReturn(this, (RaceEntities.__proto__ || Object.getPrototypeOf(RaceEntities)).apply(this, arguments));
  }

  _createClass(RaceEntities, [{
    key: 'get',


    /**
     * One time get method for the query using the given options
     * @param options
     * @returns {Promise}
     */
    value: function get(options) {
      var _this2 = this;

      return Promise.resolve(options).then(RaceEntities.verifyValidOptions).then(function (params) {
        var graphQuery = RaceEntities.buildQuery(params.searchString, params);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables, true, graphQuery.fragments);
      }).then(RaceEntities.verifyNotFoundResult).then(function (result) {
        return result.data.raceEntities;
      });
    }
  }], [{
    key: 'buildQuery',


    /**
     *
     * @param searchText
     * @returns {raceEntities: {$raceEntitie: [{name: string, dob: number}]}}
     */

    value: function buildQuery(searchText, queryOptions) {
      var getHorses = (0, _graphqlTag2.default)(_templateObject);

      var getJockeys = (0, _graphqlTag2.default)(_templateObject2);

      var getTrainers = (0, _graphqlTag2.default)(_templateObject3);

      var getOwners = (0, _graphqlTag2.default)(_templateObject4);

      // linting must be disabled due to template string not identifying a variable used in a fragment
      /* eslint-disable graphql/template-strings */
      var queryString = (0, _graphqlTag2.default)(_templateObject5);
      /* eslint-enable graphql/template-strings */

      var _queryOptions$horse = queryOptions.horse,
          horse = _queryOptions$horse === undefined ? false : _queryOptions$horse,
          _queryOptions$jockey = queryOptions.jockey,
          jockey = _queryOptions$jockey === undefined ? false : _queryOptions$jockey,
          _queryOptions$trainer = queryOptions.trainer,
          trainer = _queryOptions$trainer === undefined ? false : _queryOptions$trainer,
          _queryOptions$owner = queryOptions.owner,
          owner = _queryOptions$owner === undefined ? false : _queryOptions$owner;


      var queryVariables = {
        searchText: searchText,
        horse: horse,
        jockey: jockey,
        trainer: trainer,
        owner: owner
      };

      var queryFragments = [getHorses, getJockeys, getTrainers, getOwners];

      return {
        string: queryString,
        variables: queryVariables,
        fragments: queryFragments
      };
    }

    /**
     *
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.searchString) {
        throw new Error('You must specify a search parameter');
      }
      return options;
    }

    /**
     * Verifies if the result we got is invalid
     * @param result
     * @returns {Promise<*>}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (result.errors) {
        return Promise.reject('With Errors');
      }

      if (!result.data || !result.data.raceEntities) {
        return Promise.reject('No results');
      }

      return Promise.resolve(result);
    }
  }]);

  return RaceEntities;
}(_client.GraphQLSubscribeInterface);

exports.default = RaceEntities;

/***/ }),
/* 76 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _raceListInfo = __webpack_require__(77);

var _raceListInfo2 = _interopRequireDefault(_raceListInfo);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _raceListInfo2.default;

/***/ }),
/* 77 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race List Info Module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Queries the GraphQL to return info for a set of races
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceList
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */

var RaceListInfo = function (_GraphQLSubscribeInte) {
  _inherits(RaceListInfo, _GraphQLSubscribeInte);

  function RaceListInfo() {
    _classCallCheck(this, RaceListInfo);

    return _possibleConstructorReturn(this, (RaceListInfo.__proto__ || Object.getPrototypeOf(RaceListInfo)).apply(this, arguments));
  }

  _createClass(RaceListInfo, [{
    key: 'subscribe',


    /**
     * Polls the graph api to the given query.
     * @param options
     * @param callback
     * @param pollInterval - in milliseconds
     * @param forceFetch
     */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

      var graphQuery = void 0;

      try {
        this.options = RaceListInfo.verifyValidOptions(options);
        graphQuery = RaceListInfo.buildQuery(options);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RaceListInfo.prototype.__proto__ || Object.getPrototypeOf(RaceListInfo.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(RaceListInfo.verifyNotFoundResult(results)).then(function (result) {
          return result.data;
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RaceListInfo.prototype.__proto__ || Object.getPrototypeOf(RaceListInfo.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     * Updates the already made subscription with new query variables.
     *
     * @param options
     * @returns {Promise}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RaceListInfo.verifyValidOptions).then(function () {
        _this3.options = options;
        return _get(RaceListInfo.prototype.__proto__ || Object.getPrototypeOf(RaceListInfo.prototype), 'refetch', _this3).call(_this3, options)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RaceListInfo.verifyNotFoundResult).then(function (result) {
          return result.data;
        });
      });
    }

    /**
     * Makes the query, one time, and returns the response
     * @param options
     * @returns {Promise}
     */

  }, {
    key: 'get',
    value: function get(options) {
      var _this4 = this;

      return Promise.resolve(options).then(RaceListInfo.verifyValidOptions).then(function () {
        _this4.options = options;
        var graphQuery = RaceListInfo.buildQuery(options);

        return _this4.graphql.query(graphQuery.string, graphQuery.variables, options.forceFetch);
      }).then(RaceListInfo.verifyNotFoundResult).then(function (result) {
        return result.data;
      });
    }
  }], [{
    key: 'buildQuery',

    /**
     * Builds the query according to the given options
     * @param options
     * @returns {{string: String, variables: Object}}
     */
    value: function buildQuery(options) {
      // Build Race Query Array
      var allRaces = [];
      if (options.races) {
        allRaces = options.races.map(function (option, index) {
          return 'O' + index + ': race(\n        profile: $wagerProfile,\n        date: "' + option.date + '",\n        track: "' + option.track + '",\n        number: "' + option.number + '"){\n          ...raceInfo\n        }';
        });
      }

      // Add Next Race Query
      allRaces.push('nextRace: races (\n        profile: $wagerProfile,\n        sort: $sortBy,\n        filter: $filterBy\n        page: $page)\n        {\n        track {\n          code\n          perfAbbr\n          name\n        }\n        number\n      }');

      var query = '\n    query getRaceListInfo(\n    $wagerProfile: String,\n    $sortBy: RaceListSort,\n    $filterBy: RaceListFilter,\n    $page: Pagination){' + allRaces + '}\n\n    ' + (allRaces.length > 1 ? 'fragment raceInfo on Race {\n      number\n      trackCode\n      mtp\n      postTime\n      track {\n        name\n        perfAbbr\n        code\n        name\n      }\n      status {\n        code\n      }\n      results {\n        runners {\n          biNumber\n          finishPosition\n        }\n      }\n    }' : '') + '\n    ';

      var queryString = (0, _graphqlTag2.default)([query]);

      var filterBy = this.prepareFilters(options.filterBy || {});

      return {
        string: queryString,
        variables: {
          wagerProfile: options.wagerProfile,
          sortBy: {
            byMTP: 'ASC'
          },
          page: {
            current: 0,
            results: 1
          },
          filterBy: filterBy
        }
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      // Add filter hasMTP and iOpen by default
      Object.assign(filterBy, { isOpen: true });

      return filterBy;
    }

    /**
     * Takes the result and verifies if there is any error.
     * @param result
     * @returns {boolean}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (result.errors || !result.data) {
        throw new Error('Error getting RaceListInfo');
      }
      return result;
    }

    /**
     * Verifies if the client has the necessary options to perform the query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the options');
      }
      if (options.races) {
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;

        try {
          for (var _iterator = options.races[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
            var option = _step.value;

            if (!option.date || !option.track || !option.number) {
              throw new Error('You must specify a date, a track and the number in each option.races');
            }
          }
        } catch (err) {
          _didIteratorError = true;
          _iteratorError = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion && _iterator.return) {
              _iterator.return();
            }
          } finally {
            if (_didIteratorError) {
              throw _iteratorError;
            }
          }
        }
      }
    }
  }]);

  return RaceListInfo;
}(_client.GraphQLSubscribeInterface);

exports.default = RaceListInfo;

/***/ }),
/* 78 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _raceProgram = __webpack_require__(79);

var _raceProgram2 = _interopRequireDefault(_raceProgram);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _raceProgram2.default;

/***/ }),
/* 79 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      fragment poolsFragment on Race {\n        racePools {\n          wagerType {\n            name\n            id\n          }\n          amount\n        }\n      }\n    '], ['\n      fragment poolsFragment on Race {\n        racePools {\n          wagerType {\n            name\n            id\n          }\n          amount\n        }\n      }\n    ']),
    _templateObject2 = _taggedTemplateLiteral(['\n      fragment racesFragment on Track {\n        races(\n          filter: { isGreyhound: $isGreyhound }\n          sort: { byPostTime: ASC }\n        ) {\n          number\n          bettingInterests {\n            biNumber\n            saddleColor\n            favorite\n            numberColor\n            currentOdds {\n              numerator\n              denominator\n            }\n            morningLineOdds {\n              numerator\n              denominator\n            }\n            runners {\n              horseName\n              jockey\n              runnerId\n              scratched\n              dob\n            }\n          }\n        }\n      }\n    '], ['\n      fragment racesFragment on Track {\n        races(\n          filter: { isGreyhound: $isGreyhound }\n          sort: { byPostTime: ASC }\n        ) {\n          number\n          bettingInterests {\n            biNumber\n            saddleColor\n            favorite\n            numberColor\n            currentOdds {\n              numerator\n              denominator\n            }\n            morningLineOdds {\n              numerator\n              denominator\n            }\n            runners {\n              horseName\n              jockey\n              runnerId\n              scratched\n              dob\n            }\n          }\n        }\n      }\n    ']),
    _templateObject3 = _taggedTemplateLiteral(['\n      fragment resultsFragment on Race {\n        results {\n          payoffs {\n            selections {\n              payoutAmount\n              selection\n            }\n            wagerAmount\n            wagerType {\n              id\n              name\n            }\n          }\n          runners {\n            betAmount\n            runnerNumber\n            biNumber\n            finishPosition\n            placePayoff\n            runnerName\n            showPayoff\n            winPayoff\n          }\n        }\n      }\n    '], ['\n      fragment resultsFragment on Race {\n        results {\n          payoffs {\n            selections {\n              payoutAmount\n              selection\n            }\n            wagerAmount\n            wagerType {\n              id\n              name\n            }\n          }\n          runners {\n            betAmount\n            runnerNumber\n            biNumber\n            finishPosition\n            placePayoff\n            runnerName\n            showPayoff\n            winPayoff\n          }\n        }\n      }\n    ']),
    _templateObject4 = _taggedTemplateLiteral(['\n      fragment handicappingFragment on Runner {\n        horseName\n        jockey\n        trainer\n        ownerName\n        weight\n        med\n        ownerName\n        sire\n        damSire\n        dam\n        age\n        sex\n        handicapping {\n          speedAndClass {\n            avgClassRating\n            highSpeed\n            avgSpeed\n            lastClassRating\n            avgDistance\n          }\n          averagePace {\n            finish\n            numRaces\n            middle\n            early\n          }\n          jockeyTrainer {\n            places\n            jockeyName\n            trainerName\n            shows\n            wins\n            starts\n          }\n          snapshot {\n            powerRating\n            daysOff\n            horseWins\n            horseStarts\n          }\n          freePick {\n            number\n            info\n          }\n        }\n      }\n    '], ['\n      fragment handicappingFragment on Runner {\n        horseName\n        jockey\n        trainer\n        ownerName\n        weight\n        med\n        ownerName\n        sire\n        damSire\n        dam\n        age\n        sex\n        handicapping {\n          speedAndClass {\n            avgClassRating\n            highSpeed\n            avgSpeed\n            lastClassRating\n            avgDistance\n          }\n          averagePace {\n            finish\n            numRaces\n            middle\n            early\n          }\n          jockeyTrainer {\n            places\n            jockeyName\n            trainerName\n            shows\n            wins\n            starts\n          }\n          snapshot {\n            powerRating\n            daysOff\n            horseWins\n            horseStarts\n          }\n          freePick {\n            number\n            info\n          }\n        }\n      }\n    ']),
    _templateObject5 = _taggedTemplateLiteral(['\n      fragment bettingInterestsFragment on Race {\n        bettingInterests {\n          biNumber\n          saddleColor\n          numberColor\n          ...biPoolsFragment @include(if: $withBiPools)\n          currentOdds {\n            numerator\n            denominator\n          }\n          favorite\n          morningLineOdds {\n            numerator\n            denominator\n          }\n          runners {\n            runnerId\n            scratched\n            dob\n            ...handicappingFragment @include(if: $withHandicapping)\n          }\n        }\n      }\n    '], ['\n      fragment bettingInterestsFragment on Race {\n        bettingInterests {\n          biNumber\n          saddleColor\n          numberColor\n          ...biPoolsFragment @include(if: $withBiPools)\n          currentOdds {\n            numerator\n            denominator\n          }\n          favorite\n          morningLineOdds {\n            numerator\n            denominator\n          }\n          runners {\n            runnerId\n            scratched\n            dob\n            ...handicappingFragment @include(if: $withHandicapping)\n          }\n        }\n      }\n    ']),
    _templateObject6 = _taggedTemplateLiteral(['\n      fragment biPoolsFragment on BettingInterest {\n        biPools {\n          poolRunnersData {\n            amount\n          }\n          wagerType {\n            id\n          }\n        }\n      }\n    '], ['\n      fragment biPoolsFragment on BettingInterest {\n        biPools {\n          poolRunnersData {\n            amount\n          }\n          wagerType {\n            id\n          }\n        }\n      }\n    ']),
    _templateObject7 = _taggedTemplateLiteral(['\n      fragment probablesFragment on Race {\n        probables {\n          betCombos {\n            runner1\n            runner2\n            payout\n          }\n          minWagerAmount\n          wagerType {\n            id\n            name\n          }\n        }\n      }\n    '], ['\n      fragment probablesFragment on Race {\n        probables {\n          betCombos {\n            runner1\n            runner2\n            payout\n          }\n          minWagerAmount\n          wagerType {\n            id\n            name\n          }\n        }\n      }\n    ']),
    _templateObject8 = _taggedTemplateLiteral(['\n      fragment lateChangesFragment on Race {\n        lateChanges {\n          raceChanges {\n            description\n            date\n            newValue\n            oldValue\n          }\n          horseChanges {\n            horseName\n            runnerId\n            changes {\n              description\n              date\n              newValue\n              oldValue\n            }\n          }\n        }\n      }\n    '], ['\n      fragment lateChangesFragment on Race {\n        lateChanges {\n          raceChanges {\n            description\n            date\n            newValue\n            oldValue\n          }\n          horseChanges {\n            horseName\n            runnerId\n            changes {\n              description\n              date\n              newValue\n              oldValue\n            }\n          }\n        }\n      }\n    ']),
    _templateObject9 = _taggedTemplateLiteral(['\n      fragment wagerTypesFragment on Race {\n        wagerTypes {\n          maxWagerAmount\n          minWagerAmount\n          wagerAmounts\n          hasPool\n          poolAmount\n          columnCount\n          legCount\n          minBIsPerLeg\n          maxBIsPerLeg\n          columnType\n          isBox\n          poolsPerBI\n          isKey\n          positionCount\n          isWheel\n          type {\n            id\n            code\n            name\n          }\n        }\n      }\n    '], ['\n      fragment wagerTypesFragment on Race {\n        wagerTypes {\n          maxWagerAmount\n          minWagerAmount\n          wagerAmounts\n          hasPool\n          poolAmount\n          columnCount\n          legCount\n          minBIsPerLeg\n          maxBIsPerLeg\n          columnType\n          isBox\n          poolsPerBI\n          isKey\n          positionCount\n          isWheel\n          type {\n            id\n            code\n            name\n          }\n        }\n      }\n    ']),
    _templateObject10 = _taggedTemplateLiteral(['\n      fragment detailsFragment on Race {\n        description\n        distance\n        purse\n        numRunners\n        surface {\n          id\n          name\n          defaultCondition\n        }\n        type {\n          id\n          code\n          name\n        }\n        claimingPrice\n        raceClass {\n          id\n          name\n        }\n        video {\n          liveStreaming\n          onTvg\n          onTvg2\n          hasReplay\n          replays\n          streams\n          replayFileName\n          isStreamHighDefinition\n          flashAvailable\n          mobileAvailable\n        }\n      }\n    '], ['\n      fragment detailsFragment on Race {\n        description\n        distance\n        purse\n        numRunners\n        surface {\n          id\n          name\n          defaultCondition\n        }\n        type {\n          id\n          code\n          name\n        }\n        claimingPrice\n        raceClass {\n          id\n          name\n        }\n        video {\n          liveStreaming\n          onTvg\n          onTvg2\n          hasReplay\n          replays\n          streams\n          replayFileName\n          isStreamHighDefinition\n          flashAvailable\n          mobileAvailable\n        }\n      }\n    ']),
    _templateObject11 = _taggedTemplateLiteral(['\n      fragment willPaysFragment on Race {\n        willPays {\n          wagerAmount\n          payOffType\n          type {\n            id\n            code\n            name\n          }\n          legResults {\n            legNumber\n            winningBi\n          }\n          payouts {\n            bettingInterestNumber\n            payoutAmount\n          }\n        }\n      }\n    '], ['\n      fragment willPaysFragment on Race {\n        willPays {\n          wagerAmount\n          payOffType\n          type {\n            id\n            code\n            name\n          }\n          legResults {\n            legNumber\n            winningBi\n          }\n          payouts {\n            bettingInterestNumber\n            payoutAmount\n          }\n        }\n      }\n    ']),
    _templateObject12 = _taggedTemplateLiteral(['\n      query getRaceProgram(\n        $trackAbbr: String\n        $raceNumber: String\n        $wagerProfile: String\n        $withRaces: Boolean!\n        $withResults: Boolean!\n        $withBettingInterests: Boolean!\n        $withLateChanges: Boolean!\n        $withProbables: Boolean!\n        $withPools: Boolean!\n        $withWagerTypes: Boolean!\n        $withHandicapping: Boolean!\n        $withDetails: Boolean!\n        $withWillPays: Boolean!\n        $withBiPools: Boolean!\n        $isGreyhound: Boolean!\n        $product: String\n        $brand: String\n      ) {\n        race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n          number\n          mtp\n          tvgRaceId\n          postTime\n          status {\n            code\n          }\n          promos(product: $product, brand: $brand) {\n            rootParentPromoID\n            isAboveTheLine\n            promoPath\n            isPromoTagShown\n          }\n          isGreyhound\n          ...detailsFragment @include(if: $withDetails)\n          track {\n            name\n            code\n            perfAbbr\n            featured\n            trackDataSource\n            location {\n              country\n            }\n            ...racesFragment @include(if: $withRaces)\n          }\n          ...poolsFragment @include(if: $withPools)\n          ...probablesFragment @include(if: $withProbables)\n          ...bettingInterestsFragment @include(if: $withBettingInterests)\n          ...lateChangesFragment @include(if: $withLateChanges)\n          ...resultsFragment @include(if: $withResults)\n          ...wagerTypesFragment @include(if: $withWagerTypes)\n          ...willPaysFragment @include(if: $withWillPays)\n        }\n      }\n    '], ['\n      query getRaceProgram(\n        $trackAbbr: String\n        $raceNumber: String\n        $wagerProfile: String\n        $withRaces: Boolean!\n        $withResults: Boolean!\n        $withBettingInterests: Boolean!\n        $withLateChanges: Boolean!\n        $withProbables: Boolean!\n        $withPools: Boolean!\n        $withWagerTypes: Boolean!\n        $withHandicapping: Boolean!\n        $withDetails: Boolean!\n        $withWillPays: Boolean!\n        $withBiPools: Boolean!\n        $isGreyhound: Boolean!\n        $product: String\n        $brand: String\n      ) {\n        race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n          number\n          mtp\n          tvgRaceId\n          postTime\n          status {\n            code\n          }\n          promos(product: $product, brand: $brand) {\n            rootParentPromoID\n            isAboveTheLine\n            promoPath\n            isPromoTagShown\n          }\n          isGreyhound\n          ...detailsFragment @include(if: $withDetails)\n          track {\n            name\n            code\n            perfAbbr\n            featured\n            trackDataSource\n            location {\n              country\n            }\n            ...racesFragment @include(if: $withRaces)\n          }\n          ...poolsFragment @include(if: $withPools)\n          ...probablesFragment @include(if: $withProbables)\n          ...bettingInterestsFragment @include(if: $withBettingInterests)\n          ...lateChangesFragment @include(if: $withLateChanges)\n          ...resultsFragment @include(if: $withResults)\n          ...wagerTypesFragment @include(if: $withWagerTypes)\n          ...willPaysFragment @include(if: $withWillPays)\n        }\n      }\n    ']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race Program Volatile Module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * This module is responsible for querying the GraphQL server for the volatile data displayed in a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * program page (odds, scratches, probables, pools and results
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceProgram
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var RaceProgram = function (_GraphQLSubscribeInte) {
  _inherits(RaceProgram, _GraphQLSubscribeInte);

  function RaceProgram() {
    _classCallCheck(this, RaceProgram);

    return _possibleConstructorReturn(this, (RaceProgram.__proto__ || Object.getPrototypeOf(RaceProgram)).apply(this, arguments));
  }

  _createClass(RaceProgram, [{
    key: 'subscribe',


    /**
     * Subscribes to the query with the given options and poll interval,
     * calling the callbacks every pollInterval milliseconds
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {*}
     */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        this.options = RaceProgram.verifyValidOptions(options);
        graphQuery = RaceProgram.buildQuery(this.options.trackAbbr, this.options.raceNumber, this.options.wagerProfile, this.options.queryOptions);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RaceProgram.prototype.__proto__ || Object.getPrototypeOf(RaceProgram.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch, graphQuery.fragments)(function (results) {
        return Promise.resolve(RaceProgram.verifyNotFoundResult(results)).then(function (result) {
          return result.data;
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RaceProgram.prototype.__proto__ || Object.getPrototypeOf(RaceProgram.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     * Refresh the subscription with new options
     * @param options
     * @returns {*}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RaceProgram.verifyValidOptions).then(function (queryOptions) {
        return _get(RaceProgram.prototype.__proto__ || Object.getPrototypeOf(RaceProgram.prototype), 'refetch', _this3).call(_this3, queryOptions)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RaceProgram.verifyNotFoundResult).then(function (result) {
          return result.data;
        });
      });
    }

    /**
     * One time get method for the query using the given options
     * @param options
     * @returns {Promise}
     */

  }, {
    key: 'get',
    value: function get(options) {
      var _this4 = this;

      return Promise.resolve(options).then(RaceProgram.verifyValidOptions).then(function (params) {
        var graphQuery = RaceProgram.buildQuery(params.trackAbbr, params.raceNumber, params.wagerProfile, params.queryOptions);

        return _this4.graphql.query(graphQuery.string, graphQuery.variables, params.forceFetch, graphQuery.fragments);
      }).then(RaceProgram.verifyNotFoundResult).then(function (result) {
        return result.data;
      });
    }
  }], [{
    key: 'buildQuery',

    /**
     * Builds the query and query options to be used in the subscribe / refetch / get methods
     * @param trackAbbr
     * @param raceNumber
     * @param wagerProfile
     * @param queryOptions
     * @returns {{string: *, variables: {trackAbbr: *, raceNumber: *, filterByTrack: {trackCode: *, isOpen: boolean}}}}
     */
    value: function buildQuery(trackAbbr, raceNumber, wagerProfile, queryOptions) {
      var racePoolsQuery = (0, _graphqlTag2.default)(_templateObject);

      var racesQuery = (0, _graphqlTag2.default)(_templateObject2);

      var resultsQuery = (0, _graphqlTag2.default)(_templateObject3);

      var handicappingQuery = (0, _graphqlTag2.default)(_templateObject4);

      var bettingInterestsQuery = (0, _graphqlTag2.default)(_templateObject5);

      var biPoolsQuery = (0, _graphqlTag2.default)(_templateObject6);

      var probablesQuery = (0, _graphqlTag2.default)(_templateObject7);

      var lateChangesQuery = (0, _graphqlTag2.default)(_templateObject8);

      var wagerTypesQuery = (0, _graphqlTag2.default)(_templateObject9);

      var detailsQuery = (0, _graphqlTag2.default)(_templateObject10);

      var willPaysQuery = (0, _graphqlTag2.default)(_templateObject11);

      // linting must be disabled due to template string not identifying a variable used in a fragment
      /* eslint-disable graphql/template-strings */
      var queryString = (0, _graphqlTag2.default)(_templateObject12);
      /* eslint-enable graphql/template-strings */

      var _queryOptions$withDet = queryOptions.withDetails,
          withDetails = _queryOptions$withDet === undefined ? false : _queryOptions$withDet,
          _queryOptions$withRac = queryOptions.withRaces,
          withRaces = _queryOptions$withRac === undefined ? false : _queryOptions$withRac,
          _queryOptions$withRes = queryOptions.withResults,
          withResults = _queryOptions$withRes === undefined ? false : _queryOptions$withRes,
          _queryOptions$withPoo = queryOptions.withPools,
          withPools = _queryOptions$withPoo === undefined ? false : _queryOptions$withPoo,
          _queryOptions$withPro = queryOptions.withProbables,
          withProbables = _queryOptions$withPro === undefined ? false : _queryOptions$withPro,
          _queryOptions$withBet = queryOptions.withBettingInterests,
          withBettingInterests = _queryOptions$withBet === undefined ? false : _queryOptions$withBet,
          _queryOptions$withLat = queryOptions.withLateChanges,
          withLateChanges = _queryOptions$withLat === undefined ? false : _queryOptions$withLat,
          _queryOptions$withHan = queryOptions.withHandicapping,
          withHandicapping = _queryOptions$withHan === undefined ? false : _queryOptions$withHan,
          _queryOptions$withWag = queryOptions.withWagerTypes,
          withWagerTypes = _queryOptions$withWag === undefined ? false : _queryOptions$withWag,
          _queryOptions$withWil = queryOptions.withWillPays,
          withWillPays = _queryOptions$withWil === undefined ? false : _queryOptions$withWil,
          _queryOptions$withBiP = queryOptions.withBiPools,
          withBiPools = _queryOptions$withBiP === undefined ? false : _queryOptions$withBiP,
          _queryOptions$isGreyh = queryOptions.isGreyhound,
          isGreyhound = _queryOptions$isGreyh === undefined ? false : _queryOptions$isGreyh,
          _queryOptions$product = queryOptions.product,
          product = _queryOptions$product === undefined ? null : _queryOptions$product,
          _queryOptions$brand = queryOptions.brand,
          brand = _queryOptions$brand === undefined ? null : _queryOptions$brand;


      var queryVariables = {
        trackAbbr: trackAbbr,
        raceNumber: raceNumber,
        wagerProfile: wagerProfile,
        withDetails: withDetails,
        withRaces: withRaces,
        withResults: withResults,
        withBettingInterests: withBettingInterests,
        withLateChanges: withLateChanges,
        withProbables: withProbables,
        withPools: withPools,
        withHandicapping: withHandicapping,
        withWagerTypes: withWagerTypes,
        withWillPays: withWillPays,
        withBiPools: withBiPools,
        isGreyhound: isGreyhound,
        product: product,
        brand: brand
      };

      if (product) {
        queryVariables.product = product;
      }

      if (brand) {
        queryVariables.brand = brand;
      }

      var queryFragments = [detailsQuery, racesQuery, handicappingQuery, bettingInterestsQuery, racePoolsQuery, probablesQuery, lateChangesQuery, resultsQuery, wagerTypesQuery, willPaysQuery, biPoolsQuery];

      return {
        string: queryString,
        variables: queryVariables,
        fragments: queryFragments
      };
    }

    /**
     * Verifies if the options passed to the query are valid
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.trackAbbr || !options.raceNumber || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile, a trackAbbr and a raceNumber in the options');
      }

      var _options$trackAbbr = options.trackAbbr,
          trackAbbr = _options$trackAbbr === undefined ? '' : _options$trackAbbr,
          _options$raceNumber = options.raceNumber,
          raceNumber = _options$raceNumber === undefined ? '' : _options$raceNumber,
          _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$queryOptions = options.queryOptions,
          queryOptions = _options$queryOptions === undefined ? {} : _options$queryOptions,
          _options$forceFetch = options.forceFetch,
          forceFetch = _options$forceFetch === undefined ? true : _options$forceFetch;


      return {
        trackAbbr: trackAbbr,
        raceNumber: raceNumber,
        wagerProfile: wagerProfile,
        queryOptions: queryOptions,
        forceFetch: forceFetch
      };
    }

    /**
     * Verifies if the result we got is invalid
     * @param result
     * @returns {boolean}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data || !result.data.race || result.errors) {
        throw new Error('Error getting race');
      }

      return result;
    }
  }]);

  return RaceProgram;
}(_client.GraphQLSubscribeInterface);

exports.default = RaceProgram;

/***/ }),
/* 80 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _raceResults = __webpack_require__(81);

var _raceResults2 = _interopRequireDefault(_raceResults);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _raceResults2.default;

/***/ }),
/* 81 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getRaceResults($trackAbbr: String, $raceNumber: String, $wagerProfile: String) {\n        race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n          number\n          track {\n            code\n            perfAbbr\n            name\n          }\n          type {\n            id\n          }\n          bettingInterests {\n            biNumber\n            saddleColor\n            numberColor\n            runners {\n              runnerId\n              horseName\n            }\n          }\n          results {\n            runners {\n              biNumber\n              runnerNumber\n              betAmount\n              finishPosition\n              placePayoff\n              runnerName\n              showPayoff\n              winPayoff\n            }\n            payoffs {\n              selections {\n                payoutAmount\n                selection\n              }\n              wagerAmount\n              wagerType {\n                name\n                id\n                code\n              }\n            }\n          }\n          wagerTypes {\n            type {\n              name\n              id\n              code\n            }\n          }\n          video {\n            liveStreaming\n            hasReplay\n            onTvg\n          }\n        }\n      }'], ['\n      query getRaceResults($trackAbbr: String, $raceNumber: String, $wagerProfile: String) {\n        race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n          number\n          track {\n            code\n            perfAbbr\n            name\n          }\n          type {\n            id\n          }\n          bettingInterests {\n            biNumber\n            saddleColor\n            numberColor\n            runners {\n              runnerId\n              horseName\n            }\n          }\n          results {\n            runners {\n              biNumber\n              runnerNumber\n              betAmount\n              finishPosition\n              placePayoff\n              runnerName\n              showPayoff\n              winPayoff\n            }\n            payoffs {\n              selections {\n                payoutAmount\n                selection\n              }\n              wagerAmount\n              wagerType {\n                name\n                id\n                code\n              }\n            }\n          }\n          wagerTypes {\n            type {\n              name\n              id\n              code\n            }\n          }\n          video {\n            liveStreaming\n            hasReplay\n            onTvg\n          }\n        }\n      }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race Results module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceProgram
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var RaceResults = function (_GraphQLSubscribeInte) {
  _inherits(RaceResults, _GraphQLSubscribeInte);

  function RaceResults() {
    _classCallCheck(this, RaceResults);

    return _possibleConstructorReturn(this, (RaceResults.__proto__ || Object.getPrototypeOf(RaceResults)).apply(this, arguments));
  }

  _createClass(RaceResults, [{
    key: 'subscribe',


    /**
     * Subscribes to the query with the given options and poll interval,
     * calling the callbacks every pollInterval milliseconds
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {*}
     */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        RaceResults.verifyValidOptions(options);
        graphQuery = RaceResults.buildQuery(options.trackAbbr, options.raceNumber, options.wagerProfile);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RaceResults.prototype.__proto__ || Object.getPrototypeOf(RaceResults.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return RaceResults.verifyNotFoundResult(results).then(function (result) {
          return result.data.race;
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RaceResults.prototype.__proto__ || Object.getPrototypeOf(RaceResults.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        }
        callback.fail(error);
      });
    }
  }, {
    key: 'refetch',
    value: function refetch(options) {
      try {
        RaceResults.verifyValidOptions(options);
      } catch (error) {
        return Promise.reject({ error: 'Wrong Parameters' });
      }
      return _get(RaceResults.prototype.__proto__ || Object.getPrototypeOf(RaceResults.prototype), 'refetch', this).call(this, options)(function (result) {
        return result;
      }, function (error) {
        return Promise.reject({ error: error });
      }).then(RaceResults.verifyNotFoundResult).then(function (result) {
        return result.data.race;
      });
    }

    /**
     *
     * @param options
     * @returns {*|Promise.<T>}
     */

  }, {
    key: 'get',
    value: function get(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RaceResults.verifyValidOptions).then(function () {
        var graphQuery = RaceResults.buildQuery(options.trackAbbr, options.raceNumber, options.wagerProfile);

        return _this3.graphql.query(graphQuery.string, graphQuery.variables, options.forceFetch);
      }).then(RaceResults.verifyNotFoundResult).then(function (result) {
        return result.data.race;
      });
    }
  }], [{
    key: 'buildQuery',


    /**
     *
     * @param trackAbbr
     * @param raceNumber
     * @param wagerProfile
     * @returns {{string: *, variables: {trackAbbr: *, raceNumber: *, wagerProfile: *}}}
     */
    value: function buildQuery(trackAbbr, raceNumber, wagerProfile) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = { trackAbbr: trackAbbr, raceNumber: raceNumber, wagerProfile: wagerProfile };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     *
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.trackAbbr || !options.raceNumber || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile, a trackAbbr and a raceNumber in the options');
      }
    }

    /**
     * Verifies if the result we got is invalid
     * @param result
     * @returns {boolean}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (result.errors) {
        return Promise.reject('With Errors');
      }

      if (!result.data || !result.data.race) {
        return Promise.reject('No results');
      }

      return Promise.resolve(result);
    }
  }]);

  return RaceResults;
}(_client.GraphQLSubscribeInterface);

exports.default = RaceResults;

/***/ }),
/* 82 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _raceRunners = __webpack_require__(83);

var _raceRunners2 = _interopRequireDefault(_raceRunners);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _raceRunners2.default;

/***/ }),
/* 83 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getRaceRunners(\n        $filterByTrack: String,\n        $wagerProfile: String,\n        $sortBy: RaceListSort,\n        $allRaceClasses: RaceListFilter\n        ) {\n        track(profile: $wagerProfile, code: $filterByTrack) {\n          races(sort: $sortBy, filter: $allRaceClasses) {\n            raceNumber:number\n            trackAbbr:trackCode\n            track {\n              name\n              perfAbbr\n            }\n            mtp\n            postTime\n            status {\n              code\n            }\n            type {\n              id\n            }\n            wagerTypes {\n              type {\n                id\n                name\n                code\n              }\n              maxWagerAmount\n              minWagerAmount\n              wagerAmounts\n              hasPool\n              poolAmount\n              isBox\n              isKey\n              isWheel\n              legCount\n              maxBIsPerLeg\n              minBIsPerLeg\n              poolsPerBI\n              positionCount\n              columnCount\n              columnType\n            }\n            bettingInterests {\n              biNumber\n              numberColor\n              saddleColor\n              favorite\n              currentOdds {\n                numerator\n                denominator\n              }\n              runners {\n                runnerId\n                horseName\n                scratched\n              }\n            }\n          }\n        }\n      }'], ['\n      query getRaceRunners(\n        $filterByTrack: String,\n        $wagerProfile: String,\n        $sortBy: RaceListSort,\n        $allRaceClasses: RaceListFilter\n        ) {\n        track(profile: $wagerProfile, code: $filterByTrack) {\n          races(sort: $sortBy, filter: $allRaceClasses) {\n            raceNumber:number\n            trackAbbr:trackCode\n            track {\n              name\n              perfAbbr\n            }\n            mtp\n            postTime\n            status {\n              code\n            }\n            type {\n              id\n            }\n            wagerTypes {\n              type {\n                id\n                name\n                code\n              }\n              maxWagerAmount\n              minWagerAmount\n              wagerAmounts\n              hasPool\n              poolAmount\n              isBox\n              isKey\n              isWheel\n              legCount\n              maxBIsPerLeg\n              minBIsPerLeg\n              poolsPerBI\n              positionCount\n              columnCount\n              columnType\n            }\n            bettingInterests {\n              biNumber\n              numberColor\n              saddleColor\n              favorite\n              currentOdds {\n                numerator\n                denominator\n              }\n              runners {\n                runnerId\n                horseName\n                scratched\n              }\n            }\n          }\n        }\n      }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race Program module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceProgram
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var RaceRunners = function (_GraphQLSubscribeInte) {
  _inherits(RaceRunners, _GraphQLSubscribeInte);

  function RaceRunners() {
    _classCallCheck(this, RaceRunners);

    return _possibleConstructorReturn(this, (RaceRunners.__proto__ || Object.getPrototypeOf(RaceRunners)).apply(this, arguments));
  }

  _createClass(RaceRunners, [{
    key: 'subscribe',


    /**
     *
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
       * @returns {*}
       */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

      var graphQuery = void 0;
      try {
        RaceRunners.verifyValidOptions(options);
        graphQuery = RaceRunners.buildQuery(options.trackAbbr, options.wagerProfile);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RaceRunners.prototype.__proto__ || Object.getPrototypeOf(RaceRunners.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(RaceRunners.verifyNotFoundResult(results)).then(function (result) {
          return result.data.track;
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RaceRunners.prototype.__proto__ || Object.getPrototypeOf(RaceRunners.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
       */

  }, {
    key: 'get',
    value: function get(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RaceRunners.verifyValidOptions).then(function () {
        var graphQuery = RaceRunners.buildQuery(options.trackAbbr, options.wagerProfile);

        return _this3.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(RaceRunners.verifyNotFoundResult).then(function (result) {
        return result.data.track;
      });
    }

    /**
     *
     * @param options
     * @returns {*}
       */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(RaceRunners.verifyValidOptions).then(function () {
        var queryVariables = {
          filterByTrack: { trackCode: options.trackAbbr },
          wagerProfile: options.wagerProfile
        };

        return _get(RaceRunners.prototype.__proto__ || Object.getPrototypeOf(RaceRunners.prototype), 'refetch', _this4).call(_this4, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RaceRunners.verifyNotFoundResult).then(function (result) {
          return result.data.track;
        });
      });
    }
  }], [{
    key: 'buildQuery',


    /**
     *
     * @param trackCode
     * @param wagerProfile
     * @returns {{string: *, variables: {filterByTrack: *, wagerProfile: *}}}
       */
    value: function buildQuery(trackCode, wagerProfile) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        filterByTrack: trackCode,
        allRaceClasses: { allRaceClasses: true },
        wagerProfile: wagerProfile,
        sortBy: { byRaceNumber: 'ASC' }
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     *
     * @param options
       */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.trackAbbr || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile and trackAbbr in the subscription options');
      }
    }

    /**
     *
     * @param result
     * @returns {boolean}
       */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data || !result.data.track || !result.data.track.races) {
        throw new Error('Races not found');
      }

      return result;
    }
  }]);

  return RaceRunners;
}(_client.GraphQLSubscribeInterface);

exports.default = RaceRunners;

/***/ }),
/* 84 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _raceWillpays = __webpack_require__(85);

var _raceWillpays2 = _interopRequireDefault(_raceWillpays);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _raceWillpays2.default;

/***/ }),
/* 85 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getRaceWillPays(\n        $trackAbbr: String,\n        $raceNumber: String,\n        $wagerProfile: String\n        ) {\n        race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n          number\n          willPays {\n            wagerAmount\n            payOffType\n            type {\n              id\n              code\n              name\n            }\n            legResults{\n              legNumber\n              winningBi\n            }\n            payouts {\n              bettingInterestNumber\n              payoutAmount\n            }\n          }\n        }\n      }'], ['\n      query getRaceWillPays(\n        $trackAbbr: String,\n        $raceNumber: String,\n        $wagerProfile: String\n        ) {\n        race(track: $trackAbbr, number: $raceNumber, profile: $wagerProfile) {\n          number\n          willPays {\n            wagerAmount\n            payOffType\n            type {\n              id\n              code\n              name\n            }\n            legResults{\n              legNumber\n              winningBi\n            }\n            payouts {\n              bettingInterestNumber\n              payoutAmount\n            }\n          }\n        }\n      }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * Race Results module
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                * @module RaceProgram
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                */


var RaceWillPays = function (_GraphQLSubscribeInte) {
  _inherits(RaceWillPays, _GraphQLSubscribeInte);

  function RaceWillPays() {
    _classCallCheck(this, RaceWillPays);

    return _possibleConstructorReturn(this, (RaceWillPays.__proto__ || Object.getPrototypeOf(RaceWillPays)).apply(this, arguments));
  }

  _createClass(RaceWillPays, [{
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

      var graphQuery = void 0;
      try {
        RaceWillPays.verifyValidOptions(options);
        graphQuery = RaceWillPays.buildQuery(options.trackAbbr, options.raceNumber, options.wagerProfile);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RaceWillPays.prototype.__proto__ || Object.getPrototypeOf(RaceWillPays.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(RaceWillPays.verifyNotFoundResult(results)).then(function (result) {
          return result.data.race;
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RaceWillPays.prototype.__proto__ || Object.getPrototypeOf(RaceWillPays.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }
  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RaceWillPays.verifyValidOptions).then(function (queryOptions) {
        return _get(RaceWillPays.prototype.__proto__ || Object.getPrototypeOf(RaceWillPays.prototype), 'refetch', _this3).call(_this3, queryOptions)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RaceWillPays.verifyNotFoundResult).then(function (result) {
          return result.data.race;
        });
      });
    }
  }], [{
    key: 'buildQuery',
    value: function buildQuery(trackAbbr, raceNumber, wagerProfile) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = { trackAbbr: trackAbbr, raceNumber: raceNumber, wagerProfile: wagerProfile };

      return {
        string: queryString,
        variables: queryVariables
      };
    }
  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.trackAbbr || !options.raceNumber || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile, a trackAbbr and a raceNumber in the options');
      }

      var _options$trackAbbr = options.trackAbbr,
          trackAbbr = _options$trackAbbr === undefined ? '' : _options$trackAbbr,
          _options$raceNumber = options.raceNumber,
          raceNumber = _options$raceNumber === undefined ? '' : _options$raceNumber,
          _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile;


      return {
        trackAbbr: trackAbbr,
        raceNumber: raceNumber,
        wagerProfile: wagerProfile
      };
    }
  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data || !result.data.race || result.errors) {
        throw new Error('Error getting race');
      }

      return result;
    }
  }]);

  return RaceWillPays;
}(_client.GraphQLSubscribeInterface);

exports.default = RaceWillPays;

/***/ }),
/* 86 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _racesMtpStatus = __webpack_require__(87);

var _racesMtpStatus2 = _interopRequireDefault(_racesMtpStatus);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _racesMtpStatus2.default;

/***/ }),
/* 87 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['query getRacesMtpStatus(\n      $wagerProfile: String,\n      $sortBy: RaceListSort,\n      $filterBy: RaceListFilter\n      $page: Pagination){\n        raceDate\n        mtpRaces: races( filter: $filterBy, profile: $wagerProfile, sort: $sortBy) {\n          number\n          mtp\n          trackCode\n          trackName\n          postTime\n          track {\n            perfAbbr\n          }\n          status {\n            code\n          }\n        }\n        nextRace: races(page: $page, profile: $wagerProfile, sort: $sortBy) {\n          number\n          mtp\n          trackCode\n          trackName\n          postTime\n          track {\n            perfAbbr\n          }\n          status {\n            code\n          }\n        }\n      }'], ['query getRacesMtpStatus(\n      $wagerProfile: String,\n      $sortBy: RaceListSort,\n      $filterBy: RaceListFilter\n      $page: Pagination){\n        raceDate\n        mtpRaces: races( filter: $filterBy, profile: $wagerProfile, sort: $sortBy) {\n          number\n          mtp\n          trackCode\n          trackName\n          postTime\n          track {\n            perfAbbr\n          }\n          status {\n            code\n          }\n        }\n        nextRace: races(page: $page, profile: $wagerProfile, sort: $sortBy) {\n          number\n          mtp\n          trackCode\n          trackName\n          postTime\n          track {\n            perfAbbr\n          }\n          status {\n            code\n          }\n        }\n      }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _isUndefined = __webpack_require__(118);

var _isUndefined2 = _interopRequireDefault(_isUndefined);

var _utils = __webpack_require__(14);

var _utils2 = _interopRequireDefault(_utils);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Race Mtp Status module
                                                                                                                                                           * @module RacesMtpStatus
                                                                                                                                                           */


var MtpStatusModel =

/**
 *
 * @param trackAbbr
 * @param perfAbbr
 * @param trackName
 * @param mtp
 * @param raceNumber
 * @param raceStatus
 * @param postTime
 */
function MtpStatusModel(raceNumber, trackAbbr, perfAbbr, trackName, mtp, raceStatus, postTime) {
  _classCallCheck(this, MtpStatusModel);

  this.raceNumber = raceNumber;
  this.trackAbbr = trackAbbr;
  this.perfAbbr = perfAbbr;
  this.trackName = trackName;
  this.mtp = mtp;
  this.raceStatus = raceStatus;
  this.mtpDisplay = _utils2.default.mtpDisplay(postTime, mtp);
  this.raceId = trackAbbr + '_' + raceNumber;
};

var RacesMtpStatus = function (_GraphQLSubscribeInte) {
  _inherits(RacesMtpStatus, _GraphQLSubscribeInte);

  function RacesMtpStatus() {
    _classCallCheck(this, RacesMtpStatus);

    return _possibleConstructorReturn(this, (RacesMtpStatus.__proto__ || Object.getPrototypeOf(RacesMtpStatus)).apply(this, arguments));
  }

  _createClass(RacesMtpStatus, [{
    key: 'subscribe',


    /**
     * Subscribes to graphql query
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {Object} Observable
     */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        graphQuery = RacesMtpStatus.buildQuery(options);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RacesMtpStatus.prototype.__proto__ || Object.getPrototypeOf(RacesMtpStatus.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(RacesMtpStatus.verifyNotFoundResult(results)).then(function (result) {
          return options.rawData ? result : {
            races: RacesMtpStatus.buildRacesMtpStatus(result),
            raceDate: result.data.raceDate
          };
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RacesMtpStatus.prototype.__proto__ || Object.getPrototypeOf(RacesMtpStatus.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RacesMtpStatus.buildOptions).then(function (queryOptions) {
        return _get(RacesMtpStatus.prototype.__proto__ || Object.getPrototypeOf(RacesMtpStatus.prototype), 'refetch', _this3).call(_this3, queryOptions)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RacesMtpStatus.verifyNotFoundResult).then(function (result) {
          return {
            races: RacesMtpStatus.buildRacesMtpStatus(result),
            raceDate: result.data.raceDate
          };
        });
      });
    }
  }], [{
    key: 'buildRacesMtpStatus',


    /**
     *  Builds array with RacesMtpStatus from graphql result
     * @param {Array} result
     * @returns {FeaturedTrack|Array}
     */
    value: function buildRacesMtpStatus(result) {
      var racesMtpStatus = {};

      var parseRaces = function parseRaces(races) {
        races.forEach(function (race) {
          if (race) {
            var tempRace = new MtpStatusModel(race.number, race.trackCode, race.track.perfAbbr, race.trackName, race.mtp, race.status, race.postTime);

            racesMtpStatus[tempRace.raceId] = tempRace;
          }
        });

        return racesMtpStatus;
      };

      var racesToParse = result.data.mtpRaces || [];

      if (!racesToParse.length && result.data.nextRace.length) {
        racesToParse.push(result.data.nextRace[0]);
      }

      return parseRaces(racesToParse);
    }

    /**
     * Builds graphql query
     * @param {object} options
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(options) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      return {
        string: queryString,
        variables: RacesMtpStatus.buildOptions(options)
      };
    }

    /**
     *
     * @param obj
     * @returns {{wagerProfile: *, sortBy: *, filterBy: *}}
     */

  }, {
    key: 'buildOptions',
    value: function buildOptions() {
      var obj = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var _obj$wagerProfile = obj.wagerProfile,
          wagerProfile = _obj$wagerProfile === undefined ? 'PORT-Generic' : _obj$wagerProfile,
          _obj$sortBy = obj.sortBy,
          sortBy = _obj$sortBy === undefined ? { byPostTime: 'ASC' } : _obj$sortBy,
          _obj$filterBy = obj.filterBy,
          filterBy = _obj$filterBy === undefined ? { startIn: 60, status: ['MO', 'O', 'SK', 'IC'] } : _obj$filterBy,
          _obj$page = obj.page,
          page = _obj$page === undefined ? { current: 0, results: 1 } : _obj$page;


      return { wagerProfile: wagerProfile, sortBy: sortBy, filterBy: filterBy, page: page };
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data || (0, _isUndefined2.default)(result.data.mtpRaces) || (0, _isUndefined2.default)(result.data.nextRace)) {
        throw new Error('Races MTP not found');
      }
      return result;
    }
  }]);

  return RacesMtpStatus;
}(_client.GraphQLSubscribeInterface);

exports.default = RacesMtpStatus;

/***/ }),
/* 88 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _racesNavigation = __webpack_require__(89);

var _racesNavigation2 = _interopRequireDefault(_racesNavigation);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _racesNavigation2.default;

/***/ }),
/* 89 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getRacesNavigation(\n        $filterByTrack: RaceListFilter,\n        $sortByRaceNumber: RaceListSort,\n        $wagerProfile: String\n        ) {\n        races(filter: $filterByTrack, sort: $sortByRaceNumber, profile: $wagerProfile) {\n          number\n          trackCode\n          postTime\n          status {\n            code\n          }\n        }\n      }'], ['\n      query getRacesNavigation(\n        $filterByTrack: RaceListFilter,\n        $sortByRaceNumber: RaceListSort,\n        $wagerProfile: String\n        ) {\n        races(filter: $filterByTrack, sort: $sortByRaceNumber, profile: $wagerProfile) {\n          number\n          trackCode\n          postTime\n          status {\n            code\n          }\n        }\n      }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Race Navigation module
                                                                                                                                                           * @module RacesNavigation
                                                                                                                                                           */


var RaceModel =
/**
 * Returns RaceModel object
 * @param {int} number
 * @param {string} code
 * @param {string} status
 * @param {string} postTime
 */
function RaceModel(number, code, status, postTime) {
  _classCallCheck(this, RaceModel);

  this.raceNumber = number;
  this.status = status;
  this.trackAbbr = code;
  this.postTime = new Date(postTime);
  this.id = code + '_' + number;
};

var RacesNavigation = function (_GraphQLSubscribeInte) {
  _inherits(RacesNavigation, _GraphQLSubscribeInte);

  function RacesNavigation() {
    _classCallCheck(this, RacesNavigation);

    return _possibleConstructorReturn(this, (RacesNavigation.__proto__ || Object.getPrototypeOf(RacesNavigation)).apply(this, arguments));
  }

  _createClass(RacesNavigation, [{
    key: 'subscribe',


    /**
     *
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
       * @returns {*}
       */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

      var graphQuery = void 0;
      try {
        RacesNavigation.verifyValidOptions(options);
        graphQuery = RacesNavigation.buildQuery(options.trackAbbr, options.wagerProfile);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RacesNavigation.prototype.__proto__ || Object.getPrototypeOf(RacesNavigation.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(RacesNavigation.verifyNotFoundResult(results)).then(function (result) {
          return result.data.races;
        }).then(RacesNavigation.buildRaces).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RacesNavigation.prototype.__proto__ || Object.getPrototypeOf(RacesNavigation.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
       */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RacesNavigation.verifyValidOptions).then(function () {
        var queryVariables = {
          filterByTrack: { trackCode: options.trackAbbr },
          wagerProfile: options.wagerProfile
        };

        return _get(RacesNavigation.prototype.__proto__ || Object.getPrototypeOf(RacesNavigation.prototype), 'refetch', _this3).call(_this3, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RacesNavigation.verifyNotFoundResult).then(function (result) {
          return result.data.races;
        }).then(RacesNavigation.buildRaces);
      });
    }

    /**
     *
     * @param options
     * @returns {*|Promise.<T>}
       */

  }, {
    key: 'get',
    value: function get(options) {
      var _this4 = this;

      return Promise.resolve(options).then(RacesNavigation.verifyValidOptions).then(function () {
        var graphQuery = RacesNavigation.buildQuery(options.trackAbbr, options.wagerProfile);

        return _this4.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(RacesNavigation.verifyNotFoundResult).then(function (result) {
        return result.data.races;
      }).then(RacesNavigation.buildRaces);
    }
  }], [{
    key: 'buildRaces',


    /**
     *  Builds array with RaceModels from raceData
     * @param {Array} raceData
     * @returns {RaceModel|Array}
     */
    value: function buildRaces(raceData) {
      return raceData.map(function (race) {
        return new RaceModel(race.number, race.trackCode, race.status.code, race.postTime);
      });
    }

    /**
     *
     * @param trackCode
     * @param wagerProfile
     * @returns {{string: *, variables: {filterByTrack: {trackCode: *}, sortByRaceNumber: {byPostTime: string}, wagerProfile: *}}}
       */

  }, {
    key: 'buildQuery',
    value: function buildQuery(trackCode, wagerProfile) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var filterByTrack = { trackCode: trackCode };
      var queryVariables = {
        filterByTrack: filterByTrack,
        sortByRaceNumber: { byRaceNumber: 'ASC' },
        wagerProfile: wagerProfile
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.trackAbbr || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile and trackAbbr in the subscription options');
      }
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data || !result.data.races) {
        throw new Error('Races not found');
      }

      return result;
    }
  }]);

  return RacesNavigation;
}(_client.GraphQLSubscribeInterface);

exports.default = RacesNavigation;

/***/ }),
/* 90 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _racesRssFeed = __webpack_require__(91);

var _racesRssFeed2 = _interopRequireDefault(_racesRssFeed);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _racesRssFeed2.default;

/***/ }),
/* 91 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getRacesRssFeed(\n        $filterByTrack: String,\n        $sortByRaceNumber: RaceListSort,\n        $allRaceClasses: RaceListFilter,\n        $wagerProfile: String\n        ) {\n          track(code: $filterByTrack, profile: $wagerProfile) {\n            races(sort: $sortByRaceNumber, filter: $allRaceClasses) {\n              mtp\n              number\n              postTime\n              video {\n                liveStreaming\n                onTvg\n                onTvg2\n              }\n              distance\n              type {\n                name\n              }\n              claimingPrice\n              class {\n                name\n              }\n              surface {\n                name\n                defaultCondition\n              }\n              purse\n              isGreyhound\n              status {\n                code\n              }\n            }\n          }\n        }'], ['\n      query getRacesRssFeed(\n        $filterByTrack: String,\n        $sortByRaceNumber: RaceListSort,\n        $allRaceClasses: RaceListFilter,\n        $wagerProfile: String\n        ) {\n          track(code: $filterByTrack, profile: $wagerProfile) {\n            races(sort: $sortByRaceNumber, filter: $allRaceClasses) {\n              mtp\n              number\n              postTime\n              video {\n                liveStreaming\n                onTvg\n                onTvg2\n              }\n              distance\n              type {\n                name\n              }\n              claimingPrice\n              class {\n                name\n              }\n              surface {\n                name\n                defaultCondition\n              }\n              purse\n              isGreyhound\n              status {\n                code\n              }\n            }\n          }\n        }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Race Navigation module
                                                                                                                                                           * @module RacesRssFeed
                                                                                                                                                           */


var RaceRssFeedModal =
/**
 * Returns RaceModel object
 * @param {int} mtp
 * @param {int} number
 * @param {string} postTime
 * @param liveStreaming
 * @param onTvg
 * @param onTvg2
 * @param {int} distance
 * @param {string} type
 * @param claimingPrice
 * @param {string} raceClass
 * @param {string} surface
 * @param {string} defaultCondition
 * @param {string} purse
 * @param isGreyhound
 * @param {string} status
 */

function RaceRssFeedModal(mtp, number, postTime, liveStreaming, onTvg, onTvg2, distance, type, claimingPrice, raceClass, surface, defaultCondition, purse, isGreyhound, status) {
  _classCallCheck(this, RaceRssFeedModal);

  this.mtp = mtp;
  this.raceNumber = number;
  this.postTime = postTime;
  this.liveStreaming = liveStreaming;
  this.onTvg = onTvg;
  this.onTvg2 = onTvg2;
  this.distance = distance;
  this.breed = type;
  this.claimingPrice = claimingPrice;
  this.raceClass = raceClass;
  this.surface = surface;
  this.defaultCondition = defaultCondition;
  this.purse = purse;
  this.isGreyhound = isGreyhound;
  this.status = status;
};

var RacesRssFeed = function (_GraphQLSubscribeInte) {
  _inherits(RacesRssFeed, _GraphQLSubscribeInte);

  function RacesRssFeed() {
    _classCallCheck(this, RacesRssFeed);

    return _possibleConstructorReturn(this, (RacesRssFeed.__proto__ || Object.getPrototypeOf(RacesRssFeed)).apply(this, arguments));
  }

  _createClass(RacesRssFeed, [{
    key: 'subscribe',


    /**
     *
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
       * @returns {*}
       */
    value: function subscribe(options, callback) {
      var _this2 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

      var graphQuery = void 0;
      try {
        RacesRssFeed.verifyValidOptions(options);
        graphQuery = RacesRssFeed.buildQuery(options);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RacesRssFeed.prototype.__proto__ || Object.getPrototypeOf(RacesRssFeed.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(RacesRssFeed.verifyNotFoundResult(results)).then(function (result) {
          return result.data.track.races;
        }).then(RacesRssFeed.buildRaces).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RacesRssFeed.prototype.__proto__ || Object.getPrototypeOf(RacesRssFeed.prototype), 'fetchRetry', _this2).call(_this2, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
       */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this3 = this;

      return Promise.resolve(options).then(RacesRssFeed.verifyValidOptions).then(function () {
        var queryVariables = {
          filterByTrack: options.trackAbbr,
          allRaceClasses: { allRaceClasses: true },
          sortByRaceNumber: { byRaceNumber: 'ASC' },
          wagerProfile: options.wagerProfile || 'PORT-Generic'
        };

        return _get(RacesRssFeed.prototype.__proto__ || Object.getPrototypeOf(RacesRssFeed.prototype), 'refetch', _this3).call(_this3, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RacesRssFeed.verifyNotFoundResult).then(function (result) {
          return result.data.track.races;
        }).then(RacesRssFeed.buildRaces);
      });
    }

    /**
     *
     * @param options
     * @returns {*|Promise.<T>}
       */

  }, {
    key: 'get',
    value: function get(options) {
      var _this4 = this;

      return Promise.resolve(options).then(RacesRssFeed.verifyValidOptions).then(function () {
        var graphQuery = RacesRssFeed.buildQuery(options);

        return _this4.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(RacesRssFeed.verifyNotFoundResult).then(function (result) {
        return result.data.track.races;
      }).then(RacesRssFeed.buildRaces);
    }
  }], [{
    key: 'buildRaces',


    /**
     *  Builds array with RaceModels from raceData
     * @param {Array} raceData
     * @returns {RaceModel|Array}
     */

    value: function buildRaces(raceData) {
      return raceData.map(function (race) {
        return new RaceRssFeedModal(race.mtp, race.number, race.postTime, race.video.liveStreaming, race.video.onTvg, race.video.onTvg2, race.distance, race.type.name, race.claimingPrice, race.class.name, race.surface.name, race.defaultCondition, race.purse, race.isGreyhound, race.status.code);
      });
    }

    /**
     *
     * @param options
     * @returns {{string: *, variables: {filterByTrack: {trackCode: *}, sortByRaceNumber: {byPostTime: string}}}}
       */

  }, {
    key: 'buildQuery',
    value: function buildQuery(options) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        filterByTrack: options.trackAbbr,
        allRaceClasses: { allRaceClasses: true },
        sortByRaceNumber: { byRaceNumber: 'ASC' },
        wagerProfile: options.wagerProfile || 'PORT-Generic'
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.trackAbbr) {
        throw new Error('You must specify a trackAbbr in the subscription options');
      }
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data || !result.data.track || !result.data.track.races) {
        throw new Error('Races not found');
      }

      return result;
    }
  }]);

  return RacesRssFeed;
}(_client.GraphQLSubscribeInterface);

exports.default = RacesRssFeed;

/***/ }),
/* 92 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _talentPicks = __webpack_require__(93);

var _talentPicks2 = _interopRequireDefault(_talentPicks);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _talentPicks2.default;

/***/ }),
/* 93 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getTalentPicks(\n        $wagerProfile: String\n        $filterBy: TalentPicksFilterType\n        $trackCode: String\n        $raceNumber: String\n      ) {\n        talentPicks(\n          filter: $filterBy\n          profile: $wagerProfile\n          trackCode: $trackCode\n          raceNumber: $raceNumber\n        ) {\n          id\n          talent {\n            name\n            talentId\n            pictureUrl\n            popularity\n            active\n            phrases\n          }\n          amount\n          price\n          betCount\n          wagerType {\n            columnCount\n            legCount\n            minBIsPerLeg\n            maxBIsPerLeg\n            columnType\n            isBox\n            poolsPerBI\n            isKey\n            positionCount\n            type {\n              id\n              name\n              code\n            }\n          }\n          selections {\n            order\n          }\n          favorites {\n            order\n          }\n          race {\n            id\n            trackCode\n            number\n            postTime\n            mtp  \n            status {\n              id\n              code\n            }\n            type {\n              id\n              code\n            }\n          }\n        }\n      }\n    '], ['\n      query getTalentPicks(\n        $wagerProfile: String\n        $filterBy: TalentPicksFilterType\n        $trackCode: String\n        $raceNumber: String\n      ) {\n        talentPicks(\n          filter: $filterBy\n          profile: $wagerProfile\n          trackCode: $trackCode\n          raceNumber: $raceNumber\n        ) {\n          id\n          talent {\n            name\n            talentId\n            pictureUrl\n            popularity\n            active\n            phrases\n          }\n          amount\n          price\n          betCount\n          wagerType {\n            columnCount\n            legCount\n            minBIsPerLeg\n            maxBIsPerLeg\n            columnType\n            isBox\n            poolsPerBI\n            isKey\n            positionCount\n            type {\n              id\n              name\n              code\n            }\n          }\n          selections {\n            order\n          }\n          favorites {\n            order\n          }\n          race {\n            id\n            trackCode\n            number\n            postTime\n            mtp  \n            status {\n              id\n              code\n            }\n            type {\n              id\n              code\n            }\n          }\n        }\n      }\n    ']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * TalentPick module
                                                                                                                                                           * @module TalentPick
                                                                                                                                                           */


var TalentPickModel =
/**
 * Returns TalentPickModel object
 * @param {string} id
 * @param {object} talent
 * @param {string} amount
 * @param {string} price
 * @param {int} betCount
 * @param {object} wagerType
 * @param {array} selections
 * @param {array} favorites
 * @param {object} race
 */
function TalentPickModel(id, talent, amount, price, betCount, wagerType, selections, favorites, race) {
  _classCallCheck(this, TalentPickModel);

  this.id = id;
  this.talent = talent;
  this.amount = amount;
  this.price = price;
  this.betCount = betCount;
  this.wagerType = wagerType;
  this.selections = selections;
  this.favorites = favorites;
  this.race = race;
};

var TalentPicks = function (_GraphQLSubscribeInte) {
  _inherits(TalentPicks, _GraphQLSubscribeInte);

  function TalentPicks() {
    _classCallCheck(this, TalentPicks);

    return _possibleConstructorReturn(this, (TalentPicks.__proto__ || Object.getPrototypeOf(TalentPicks)).apply(this, arguments));
  }

  _createClass(TalentPicks, [{
    key: 'get',


    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {array} favorites
     * @returns {Promise.<T>}
     */
    value: function get(wagerProfile, filterBy, trackCode, raceNumber) {
      var _this2 = this;

      var options = {
        wagerProfile: wagerProfile,
        filterBy: filterBy,
        trackCode: trackCode,
        raceNumber: raceNumber
      };

      return Promise.resolve(options).then(TalentPicks.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = TalentPicks.buildQuery(_this2.options.wagerProfile, _this2.options.filterBy, _this2.options.trackCode, _this2.options.raceNumber);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(TalentPicks.verifyNotFoundResult).then(function (result) {
        return result.data.talentPicks;
      }).then(function (talentPicks) {
        return TalentPicks.buildTalents(talentPicks);
      });
    }

    /**
     * Subscribes to graphql query
     * @param {object} options {wagerProfile, filterBy}
     * @param {function} callback {success, fail}
     * @param {int} pollInterval (ms)
     * @param {boolean} forceFetch
     * @returns {object} Observable
     */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        this.options = TalentPicks.verifyValidOptions(options);
        graphQuery = TalentPicks.buildQuery(this.options.wagerProfile, this.options.filterBy, this.options.trackCode, this.options.raceNumber);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(TalentPicks.prototype.__proto__ || Object.getPrototypeOf(TalentPicks.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(TalentPicks.verifyNotFoundResult(results)).then(function (result) {
          return result.data.talentPicks;
        }).then(TalentPicks.buildTalents).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(TalentPicks.prototype.__proto__ || Object.getPrototypeOf(TalentPicks.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        }
        callback.fail(error);
      });
    }

    /**
     * Refetches data from graqhpl
     * @param options {wagerProfile, filterBy}
     * @returns {Promise.<T>}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(TalentPicks.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        var queryVariables = {
          filterBy: queryOptions.filterBy,
          wagerProfile: queryOptions.wagerProfile,
          trackCode: queryOptions.trackCode,
          raceNumber: queryOptions.raceNumber
        };

        return _get(TalentPicks.prototype.__proto__ || Object.getPrototypeOf(TalentPicks.prototype), 'refetch', _this4).call(_this4, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(TalentPicks.verifyNotFoundResult).then(function (result) {
          return result.data.talentPicks;
        }).then(function (talentPicks) {
          return TalentPicks.buildTalents(talentPicks);
        });
      });
    }
  }], [{
    key: 'buildTalents',

    /**
     *  Builds array with TalentPickModel from talentData
     * @param {Array} talentData
     * @returns {TalentPickModel|Array}
     */
    value: function buildTalents(talentData) {
      return talentData.map(function (talentPick) {
        return new TalentPickModel(talentPick.id, talentPick.talent, talentPick.amount, talentPick.price, talentPick.betCount, talentPick.wagerType, talentPick.selections, talentPick.favorites, talentPick.race);
      });
    }

    /**
     * Builds graphql query
     * @param {string} wagerProfile
     * @param {object} filterBy {typeCode[]}
     * @param {string} trackCode
     * @param {string} raceNumber
     * @returns {}
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile) {
      var filterBy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var trackCode = arguments[2];
      var raceNumber = arguments[3];

      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        filterBy: filterBy,
        wagerProfile: wagerProfile,
        trackCode: trackCode,
        raceNumber: raceNumber
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      if (!filterBy || filterBy.isOpen === undefined) {
        return {};
      }

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      var opt = options;

      if (!opt || !opt.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the subscription options');
      }

      // Remove empty trackCode prop
      if (!opt.trackCode || opt.trackCode.length === 0) {
        delete opt.trackCode;
      }

      // Remove empty raceNumber prop
      if (!opt.raceNumber || opt.raceNumber.length === 0) {
        delete opt.raceNumber;
      }

      opt.filterBy = TalentPicks.prepareFilters(opt.filterBy);

      return opt;
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('TalentPicks not found');
      }

      return result;
    }
  }]);

  return TalentPicks;
}(_client.GraphQLSubscribeInterface);

exports.default = TalentPicks;

/***/ }),
/* 94 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _trackList = __webpack_require__(95);

var _trackList2 = _interopRequireDefault(_trackList);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _trackList2.default;

/***/ }),
/* 95 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['query getTrackList(\n    $wagerProfile: String,\n    $sortBy: TrackListSort,\n    $filterBy: TrackListFilter\n    ){\n      tracks(\n      profile: $wagerProfile,\n      sort: $sortBy\n      filter: $filterBy\n      ) {\n        currentRace {\n          number\n          postTime\n          video {\n            liveStreaming\n            streams\n          }\n        }\n        featured\n        name\n        perfAbbr\n        code\n        numberOfRaces\n      }\n    }'], ['query getTrackList(\n    $wagerProfile: String,\n    $sortBy: TrackListSort,\n    $filterBy: TrackListFilter\n    ){\n      tracks(\n      profile: $wagerProfile,\n      sort: $sortBy\n      filter: $filterBy\n      ) {\n        currentRace {\n          number\n          postTime\n          video {\n            liveStreaming\n            streams\n          }\n        }\n        featured\n        name\n        perfAbbr\n        code\n        numberOfRaces\n      }\n    }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Track list module
                                                                                                                                                           * @module trackList
                                                                                                                                                           */


var Track =
/**
 * @param {Track} track
 * @param {array} races
 */
function Track(track) {
  _classCallCheck(this, Track);

  var currentRace = track.currentRace || {};
  var video = currentRace.video || {};
  var streamCodes = video.streams || []; // must always be an array -> ["tvg_mrb"]
  var replayCodes = video.replays || []; // must always be an array -> ["saracing_mrb"]

  this.currentRace = track.currentRace ? track.currentRace.number : track.numberOfRaces;
  this.currentWagerableRace = currentRace.number || 0;
  this.currentWagerableRacePostTime = currentRace.postTime ? new Date(track.currentRace.postTime) : null;

  this.featured = track.featured;
  this.name = track.name;
  this.perfAbbr = track.perfAbbr;
  this.trackAbbr = track.code;

  this.liveStreaming = !!video.liveStreaming;
  this.streamCode = streamCodes[0] || false;
  this.replayCode = replayCodes[0] || false;
};

var TrackList = function (_GraphQLSubscribeInte) {
  _inherits(TrackList, _GraphQLSubscribeInte);

  function TrackList() {
    _classCallCheck(this, TrackList);

    return _possibleConstructorReturn(this, (TrackList.__proto__ || Object.getPrototypeOf(TrackList)).apply(this, arguments));
  }

  _createClass(TrackList, [{
    key: 'get',


    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @returns {Promise.<T>}
     */
    value: function get(wagerProfile) {
      var _this2 = this;

      var filter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

      var options = {
        wagerProfile: wagerProfile,
        filter: filter
      };

      return Promise.resolve(options).then(TrackList.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = TrackList.buildQuery(_this2.options.wagerProfile, _this2.options.filter);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(TrackList.verifyNotFoundResult).then(function (result) {
        return result.data.tracks;
      }).then(function (tracks) {
        return TrackList.buildTracks(tracks);
      });
    }

    /**
     * Subscribes to graphql query
     * @param options
     * @param callback
     * @param pollInterval
     * @param forceFetch
     * @returns {Object} Observable
     */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;
      try {
        this.options = TrackList.verifyValidOptions(options);
        graphQuery = TrackList.buildQuery(this.options.wagerProfile, this.options.filter);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(TrackList.prototype.__proto__ || Object.getPrototypeOf(TrackList.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(TrackList.verifyNotFoundResult(results)).then(function (result) {
          return result.data.tracks;
        }).then(TrackList.buildTracks).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(TrackList.prototype.__proto__ || Object.getPrototypeOf(TrackList.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     *
     * @param options
     * @returns {*}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(TrackList.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        var queryVariables = {
          wagerProfile: queryOptions.wagerProfile,
          filter: queryOptions.filter
        };

        return _get(TrackList.prototype.__proto__ || Object.getPrototypeOf(TrackList.prototype), 'refetch', _this4).call(_this4, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(TrackList.verifyNotFoundResult).then(function (result) {
          return result.data.tracks;
        }).then(TrackList.buildTracks);
      });
    }
  }], [{
    key: 'buildTracks',


    /**
     *  Builds array with leftBarTracks from graphql result
     * @param {Array} result
     * @returns {FeaturedTrack|Array}
     */
    value: function buildTracks(result) {
      var tracksArray = [];
      result.forEach(function (track) {
        tracksArray.push(new Track(track));
      });

      return tracksArray;
    }

    /**
     * Builds graphql query
     * @param {string} wagerProfile
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile, filter) {
      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        sortBy: { byName: 'ASC' },
        filterBy: filter,
        wagerProfile: wagerProfile
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the options');
      }

      var _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$filter = options.filter,
          filter = _options$filter === undefined ? {} : _options$filter;


      return {
        wagerProfile: wagerProfile,
        filter: filter
      };
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('Tracks not found');
      }

      return result;
    }
  }]);

  return TrackList;
}(_client.GraphQLSubscribeInterface);

exports.default = TrackList;

/***/ }),
/* 96 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _moment = __webpack_require__(21);

var _moment2 = _interopRequireDefault(_moment);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var TimeUtil = function () {
  function TimeUtil() {
    _classCallCheck(this, TimeUtil);
  }

  _createClass(TimeUtil, null, [{
    key: 'mtpDisplay',
    value: function mtpDisplay(postTime, raceMtp) {
      var mtp = raceMtp;

      function timeText() {
        if (mtp <= 60) {
          return mtp + ' MTP';
        }
        return (0, _moment2.default)(postTime).format('hh:mm A');
      }

      function getMtpStatus() {
        var mtpStatusValues = ['near', 'med', 'far', 'time-format'];
        if (mtp <= 5) {
          return mtpStatusValues[0];
        } else if (mtp <= 15) {
          return mtpStatusValues[1];
        } else if (mtp <= 60) {
          return mtpStatusValues[2];
        }

        return mtpStatusValues[3];
      }

      return {
        time: {
          racePostTime: postTime
        },
        mtpStatus: getMtpStatus(),
        timeText: timeText()
      };
    }
  }]);

  return TimeUtil;
}();

exports.default = TimeUtil;

/***/ }),
/* 97 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

function shouldInclude(selection, variables) {
    if (!variables) {
        variables = {};
    }
    if (!selection.directives) {
        return true;
    }
    var res = true;
    selection.directives.forEach(function (directive) {
        if (directive.name.value !== 'skip' && directive.name.value !== 'include') {
            return;
        }
        var directiveArguments = directive.arguments;
        var directiveName = directive.name.value;
        if (directiveArguments.length !== 1) {
            throw new Error("Incorrect number of arguments for the @" + directiveName + " directive.");
        }
        var ifArgument = directive.arguments[0];
        if (!ifArgument.name || ifArgument.name.value !== 'if') {
            throw new Error("Invalid argument for the @" + directiveName + " directive.");
        }
        var ifValue = directive.arguments[0].value;
        var evaledValue = false;
        if (!ifValue || ifValue.kind !== 'BooleanValue') {
            if (ifValue.kind !== 'Variable') {
                throw new Error("Argument for the @" + directiveName + " directive must be a variable or a bool ean value.");
            }
            else {
                evaledValue = variables[ifValue.name.value];
                if (evaledValue === undefined) {
                    throw new Error("Invalid variable referenced in @" + directiveName + " directive.");
                }
            }
        }
        else {
            evaledValue = ifValue.value;
        }
        if (directiveName === 'skip') {
            evaledValue = !evaledValue;
        }
        if (!evaledValue) {
            res = false;
        }
    });
    return res;
}
exports.shouldInclude = shouldInclude;
//# sourceMappingURL=directives.js.map

/***/ }),
/* 98 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
function getMutationDefinition(doc) {
    checkDocument(doc);
    var mutationDef = null;
    doc.definitions.forEach(function (definition) {
        if (definition.kind === 'OperationDefinition'
            && definition.operation === 'mutation') {
            mutationDef = definition;
        }
    });
    if (!mutationDef) {
        throw new Error('Must contain a mutation definition.');
    }
    return mutationDef;
}
exports.getMutationDefinition = getMutationDefinition;
function checkDocument(doc) {
    if (doc.kind !== 'Document') {
        throw new Error("Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a \"gql\" tag? http://docs.apollostack.com/apollo-client/core.html#gql");
    }
    var numOpDefinitions = doc.definitions.filter(function (definition) {
        return definition.kind === 'OperationDefinition';
    }).length;
    if (numOpDefinitions > 1) {
        throw new Error('Queries must have exactly one operation definition.');
    }
}
exports.checkDocument = checkDocument;
function getOperationName(doc) {
    var res = '';
    doc.definitions.forEach(function (definition) {
        if (definition.kind === 'OperationDefinition'
            && definition.name) {
            res = definition.name.value;
        }
    });
    return res;
}
exports.getOperationName = getOperationName;
function getFragmentDefinitions(doc) {
    var fragmentDefinitions = doc.definitions.filter(function (definition) {
        if (definition.kind === 'FragmentDefinition') {
            return true;
        }
        else {
            return false;
        }
    });
    return fragmentDefinitions;
}
exports.getFragmentDefinitions = getFragmentDefinitions;
function getQueryDefinition(doc) {
    checkDocument(doc);
    var queryDef = null;
    doc.definitions.map(function (definition) {
        if (definition.kind === 'OperationDefinition'
            && definition.operation === 'query') {
            queryDef = definition;
        }
    });
    if (!queryDef) {
        throw new Error('Must contain a query definition.');
    }
    return queryDef;
}
exports.getQueryDefinition = getQueryDefinition;
function getFragmentDefinition(doc) {
    if (doc.kind !== 'Document') {
        throw new Error("Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a \"gql\" tag? http://docs.apollostack.com/apollo-client/core.html#gql");
    }
    if (doc.definitions.length > 1) {
        throw new Error('Fragment must have exactly one definition.');
    }
    var fragmentDef = doc.definitions[0];
    if (fragmentDef.kind !== 'FragmentDefinition') {
        throw new Error('Must be a fragment definition.');
    }
    return fragmentDef;
}
exports.getFragmentDefinition = getFragmentDefinition;
function createFragmentMap(fragments) {
    if (fragments === void 0) { fragments = []; }
    var symTable = {};
    fragments.forEach(function (fragment) {
        symTable[fragment.name.value] = fragment;
    });
    return symTable;
}
exports.createFragmentMap = createFragmentMap;
function addFragmentsToDocument(queryDoc, fragments) {
    checkDocument(queryDoc);
    return __assign({}, queryDoc, { definitions: queryDoc.definitions.concat(fragments) });
}
exports.addFragmentsToDocument = addFragmentsToDocument;
function getMainDefinition(queryDoc) {
    checkDocument(queryDoc);
    try {
        return getQueryDefinition(queryDoc);
    }
    catch (e) {
        try {
            var fragments = getFragmentDefinitions(queryDoc);
            return fragments[0];
        }
        catch (e) {
            throw new Error("Expected a parsed GraphQL query with a query or a fragment.");
        }
    }
}
exports.getMainDefinition = getMainDefinition;
//# sourceMappingURL=getFromAST.js.map

/***/ }),
/* 99 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

function isScalarValue(value) {
    var SCALAR_TYPES = {
        StringValue: 1,
        BooleanValue: 1,
        EnumValue: 1,
    };
    return !!SCALAR_TYPES[value.kind];
}
function isNumberValue(value) {
    var NUMBER_TYPES = {
        IntValue: 1,
        FloatValue: 1,
    };
    return NUMBER_TYPES[value.kind];
}
function isVariable(value) {
    return value.kind === 'Variable';
}
function isObject(value) {
    return value.kind === 'ObjectValue';
}
function isList(value) {
    return value.kind === 'ListValue';
}
function valueToObjectRepresentation(argObj, name, value, variables) {
    if (isNumberValue(value)) {
        argObj[name.value] = Number(value.value);
    }
    else if (isScalarValue(value)) {
        argObj[name.value] = value.value;
    }
    else if (isObject(value)) {
        var nestedArgObj_1 = {};
        value.fields.map(function (obj) { return valueToObjectRepresentation(nestedArgObj_1, obj.name, obj.value, variables); });
        argObj[name.value] = nestedArgObj_1;
    }
    else if (isVariable(value)) {
        if (!variables || !(value.name.value in variables)) {
            throw new Error("The inline argument \"" + value.name.value + "\" is expected as a variable but was not provided.");
        }
        var variableValue = variables[value.name.value];
        argObj[name.value] = variableValue;
    }
    else if (isList(value)) {
        argObj[name.value] = value.values.map(function (listValue) {
            var nestedArgArrayObj = {};
            valueToObjectRepresentation(nestedArgArrayObj, name, listValue, variables);
            return nestedArgArrayObj[name.value];
        });
    }
    else {
        throw new Error("The inline argument \"" + name.value + "\" of kind \"" + value.kind + "\" is not supported. Use variables instead of inline arguments to overcome this limitation.");
    }
}
function argumentsObjectFromField(field, variables) {
    if (field.arguments && field.arguments.length) {
        var argObj_1 = {};
        field.arguments.forEach(function (_a) {
            var name = _a.name, value = _a.value;
            return valueToObjectRepresentation(argObj_1, name, value, variables);
        });
        return argObj_1;
    }
    return null;
}
exports.argumentsObjectFromField = argumentsObjectFromField;
function resultKeyNameFromField(field) {
    return field.alias ?
        field.alias.value :
        field.name.value;
}
exports.resultKeyNameFromField = resultKeyNameFromField;
function isField(selection) {
    return selection.kind === 'Field';
}
exports.isField = isField;
function isInlineFragment(selection) {
    return selection.kind === 'InlineFragment';
}
exports.isInlineFragment = isInlineFragment;
function graphQLResultHasError(result) {
    return result.errors && result.errors.length;
}
exports.graphQLResultHasError = graphQLResultHasError;
//# sourceMappingURL=storeUtils.js.map

/***/ }),
/* 100 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";

var index_1 = __webpack_require__(27);
function filter(doc, data) {
    var resolver = function (fieldName, root, args, context, info) {
        return root[info.resultKey];
    };
    return index_1.default(resolver, doc, data);
}
exports.filter = filter;
function check(doc, data) {
    var resolver = function (fieldName, root, args, context, info) {
        if (!{}.hasOwnProperty.call(root, info.resultKey)) {
            throw new Error(info.resultKey + " missing on " + root);
        }
        return root[info.resultKey];
    };
    index_1.default(resolver, doc, data, {}, {}, {
        fragmentMatcher: function () { return false; },
    });
}
exports.check = check;
var ANONYMOUS = '<<anonymous>>';
function PropTypeError(message) {
    this.message = message;
    this.stack = '';
}
PropTypeError.prototype = Error.prototype;
var reactPropTypeLocationNames = {
    prop: 'prop',
    context: 'context',
    childContext: 'child context',
};
function createChainableTypeChecker(validate) {
    function checkType(isRequired, props, propName, componentName, location, propFullName) {
        componentName = componentName || ANONYMOUS;
        propFullName = propFullName || propName;
        if (props[propName] == null) {
            var locationName = reactPropTypeLocationNames[location];
            if (isRequired) {
                if (props[propName] === null) {
                    return new PropTypeError("The " + locationName + " `" + propFullName + "` is marked as required " +
                        ("in `" + componentName + "`, but its value is `null`."));
                }
                return new PropTypeError("The " + locationName + " `" + propFullName + "` is marked as required in " +
                    ("`" + componentName + "`, but its value is `undefined`."));
            }
            return null;
        }
        else {
            return validate(props, propName, componentName, location, propFullName);
        }
    }
    var chainedCheckType = checkType.bind(null, false);
    chainedCheckType.isRequired = checkType.bind(null, true);
    return chainedCheckType;
}
function propType(doc) {
    return createChainableTypeChecker(function (props, propName) {
        var prop = props[propName];
        try {
            check(doc, prop);
            return null;
        }
        catch (e) {
            return e;
        }
    });
}
exports.propType = propType;
//# sourceMappingURL=utilities.js.map

/***/ }),
/* 101 */
/***/ (function(module, exports) {

module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	module.exports = __webpack_require__(1);


/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.parse = parse;
	exports.parseValue = parseValue;
	exports.parseType = parseType;
	exports.parseConstValue = parseConstValue;
	exports.parseTypeReference = parseTypeReference;
	exports.parseNamedType = parseNamedType;

	var _source = __webpack_require__(2);

	var _error = __webpack_require__(3);

	var _lexer = __webpack_require__(10);

	var _kinds = __webpack_require__(11);

	/**
	 * Given a GraphQL source, parses it into a Document.
	 * Throws GraphQLError if a syntax error is encountered.
	 */


	/**
	 * Configuration options to control parser behavior
	 */

	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	function parse(source, options) {
	  var sourceObj = typeof source === 'string' ? new _source.Source(source) : source;
	  var lexer = (0, _lexer.createLexer)(sourceObj, options || {});
	  return parseDocument(lexer);
	}

	/**
	 * Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
	 * that value.
	 * Throws GraphQLError if a syntax error is encountered.
	 *
	 * This is useful within tools that operate upon GraphQL Values directly and
	 * in isolation of complete GraphQL documents.
	 *
	 * Consider providing the results to the utility function: valueFromAST().
	 */
	function parseValue(source, options) {
	  var sourceObj = typeof source === 'string' ? new _source.Source(source) : source;
	  var lexer = (0, _lexer.createLexer)(sourceObj, options || {});
	  expect(lexer, _lexer.TokenKind.SOF);
	  var value = parseValueLiteral(lexer, false);
	  expect(lexer, _lexer.TokenKind.EOF);
	  return value;
	}

	/**
	 * Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for
	 * that type.
	 * Throws GraphQLError if a syntax error is encountered.
	 *
	 * This is useful within tools that operate upon GraphQL Types directly and
	 * in isolation of complete GraphQL documents.
	 *
	 * Consider providing the results to the utility function: typeFromAST().
	 */
	function parseType(source, options) {
	  var sourceObj = typeof source === 'string' ? new _source.Source(source) : source;
	  var lexer = (0, _lexer.createLexer)(sourceObj, options || {});
	  expect(lexer, _lexer.TokenKind.SOF);
	  var type = parseTypeReference(lexer);
	  expect(lexer, _lexer.TokenKind.EOF);
	  return type;
	}

	/**
	 * Converts a name lex token into a name parse node.
	 */
	function parseName(lexer) {
	  var token = expect(lexer, _lexer.TokenKind.NAME);
	  return {
	    kind: _kinds.NAME,
	    value: token.value,
	    loc: loc(lexer, token)
	  };
	}

	// Implements the parsing rules in the Document section.

	/**
	 * Document : Definition+
	 */
	function parseDocument(lexer) {
	  var start = lexer.token;
	  expect(lexer, _lexer.TokenKind.SOF);
	  var definitions = [];
	  do {
	    definitions.push(parseDefinition(lexer));
	  } while (!skip(lexer, _lexer.TokenKind.EOF));

	  return {
	    kind: _kinds.DOCUMENT,
	    definitions: definitions,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * Definition :
	 *   - OperationDefinition
	 *   - FragmentDefinition
	 *   - TypeSystemDefinition
	 */
	function parseDefinition(lexer) {
	  if (peek(lexer, _lexer.TokenKind.BRACE_L)) {
	    return parseOperationDefinition(lexer);
	  }

	  if (peek(lexer, _lexer.TokenKind.NAME)) {
	    switch (lexer.token.value) {
	      // Note: subscription is an experimental non-spec addition.
	      case 'query':
	      case 'mutation':
	      case 'subscription':
	        return parseOperationDefinition(lexer);

	      case 'fragment':
	        return parseFragmentDefinition(lexer);

	      // Note: the Type System IDL is an experimental non-spec addition.
	      case 'schema':
	      case 'scalar':
	      case 'type':
	      case 'interface':
	      case 'union':
	      case 'enum':
	      case 'input':
	      case 'extend':
	      case 'directive':
	        return parseTypeSystemDefinition(lexer);
	    }
	  }

	  throw unexpected(lexer);
	}

	// Implements the parsing rules in the Operations section.

	/**
	 * OperationDefinition :
	 *  - SelectionSet
	 *  - OperationType Name? VariableDefinitions? Directives? SelectionSet
	 */
	function parseOperationDefinition(lexer) {
	  var start = lexer.token;
	  if (peek(lexer, _lexer.TokenKind.BRACE_L)) {
	    return {
	      kind: _kinds.OPERATION_DEFINITION,
	      operation: 'query',
	      name: null,
	      variableDefinitions: null,
	      directives: [],
	      selectionSet: parseSelectionSet(lexer),
	      loc: loc(lexer, start)
	    };
	  }
	  var operation = parseOperationType(lexer);
	  var name = void 0;
	  if (peek(lexer, _lexer.TokenKind.NAME)) {
	    name = parseName(lexer);
	  }
	  return {
	    kind: _kinds.OPERATION_DEFINITION,
	    operation: operation,
	    name: name,
	    variableDefinitions: parseVariableDefinitions(lexer),
	    directives: parseDirectives(lexer),
	    selectionSet: parseSelectionSet(lexer),
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * OperationType : one of query mutation subscription
	 */
	function parseOperationType(lexer) {
	  var operationToken = expect(lexer, _lexer.TokenKind.NAME);
	  switch (operationToken.value) {
	    case 'query':
	      return 'query';
	    case 'mutation':
	      return 'mutation';
	    // Note: subscription is an experimental non-spec addition.
	    case 'subscription':
	      return 'subscription';
	  }

	  throw unexpected(lexer, operationToken);
	}

	/**
	 * VariableDefinitions : ( VariableDefinition+ )
	 */
	function parseVariableDefinitions(lexer) {
	  return peek(lexer, _lexer.TokenKind.PAREN_L) ? many(lexer, _lexer.TokenKind.PAREN_L, parseVariableDefinition, _lexer.TokenKind.PAREN_R) : [];
	}

	/**
	 * VariableDefinition : Variable : Type DefaultValue?
	 */
	function parseVariableDefinition(lexer) {
	  var start = lexer.token;
	  return {
	    kind: _kinds.VARIABLE_DEFINITION,
	    variable: parseVariable(lexer),
	    type: (expect(lexer, _lexer.TokenKind.COLON), parseTypeReference(lexer)),
	    defaultValue: skip(lexer, _lexer.TokenKind.EQUALS) ? parseValueLiteral(lexer, true) : null,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * Variable : $ Name
	 */
	function parseVariable(lexer) {
	  var start = lexer.token;
	  expect(lexer, _lexer.TokenKind.DOLLAR);
	  return {
	    kind: _kinds.VARIABLE,
	    name: parseName(lexer),
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * SelectionSet : { Selection+ }
	 */
	function parseSelectionSet(lexer) {
	  var start = lexer.token;
	  return {
	    kind: _kinds.SELECTION_SET,
	    selections: many(lexer, _lexer.TokenKind.BRACE_L, parseSelection, _lexer.TokenKind.BRACE_R),
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * Selection :
	 *   - Field
	 *   - FragmentSpread
	 *   - InlineFragment
	 */
	function parseSelection(lexer) {
	  return peek(lexer, _lexer.TokenKind.SPREAD) ? parseFragment(lexer) : parseField(lexer);
	}

	/**
	 * Field : Alias? Name Arguments? Directives? SelectionSet?
	 *
	 * Alias : Name :
	 */
	function parseField(lexer) {
	  var start = lexer.token;

	  var nameOrAlias = parseName(lexer);
	  var alias = void 0;
	  var name = void 0;
	  if (skip(lexer, _lexer.TokenKind.COLON)) {
	    alias = nameOrAlias;
	    name = parseName(lexer);
	  } else {
	    alias = null;
	    name = nameOrAlias;
	  }

	  return {
	    kind: _kinds.FIELD,
	    alias: alias,
	    name: name,
	    arguments: parseArguments(lexer),
	    directives: parseDirectives(lexer),
	    selectionSet: peek(lexer, _lexer.TokenKind.BRACE_L) ? parseSelectionSet(lexer) : null,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * Arguments : ( Argument+ )
	 */
	function parseArguments(lexer) {
	  return peek(lexer, _lexer.TokenKind.PAREN_L) ? many(lexer, _lexer.TokenKind.PAREN_L, parseArgument, _lexer.TokenKind.PAREN_R) : [];
	}

	/**
	 * Argument : Name : Value
	 */
	function parseArgument(lexer) {
	  var start = lexer.token;
	  return {
	    kind: _kinds.ARGUMENT,
	    name: parseName(lexer),
	    value: (expect(lexer, _lexer.TokenKind.COLON), parseValueLiteral(lexer, false)),
	    loc: loc(lexer, start)
	  };
	}

	// Implements the parsing rules in the Fragments section.

	/**
	 * Corresponds to both FragmentSpread and InlineFragment in the spec.
	 *
	 * FragmentSpread : ... FragmentName Directives?
	 *
	 * InlineFragment : ... TypeCondition? Directives? SelectionSet
	 */
	function parseFragment(lexer) {
	  var start = lexer.token;
	  expect(lexer, _lexer.TokenKind.SPREAD);
	  if (peek(lexer, _lexer.TokenKind.NAME) && lexer.token.value !== 'on') {
	    return {
	      kind: _kinds.FRAGMENT_SPREAD,
	      name: parseFragmentName(lexer),
	      directives: parseDirectives(lexer),
	      loc: loc(lexer, start)
	    };
	  }
	  var typeCondition = null;
	  if (lexer.token.value === 'on') {
	    lexer.advance();
	    typeCondition = parseNamedType(lexer);
	  }
	  return {
	    kind: _kinds.INLINE_FRAGMENT,
	    typeCondition: typeCondition,
	    directives: parseDirectives(lexer),
	    selectionSet: parseSelectionSet(lexer),
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * FragmentDefinition :
	 *   - fragment FragmentName on TypeCondition Directives? SelectionSet
	 *
	 * TypeCondition : NamedType
	 */
	function parseFragmentDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'fragment');
	  return {
	    kind: _kinds.FRAGMENT_DEFINITION,
	    name: parseFragmentName(lexer),
	    typeCondition: (expectKeyword(lexer, 'on'), parseNamedType(lexer)),
	    directives: parseDirectives(lexer),
	    selectionSet: parseSelectionSet(lexer),
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * FragmentName : Name but not `on`
	 */
	function parseFragmentName(lexer) {
	  if (lexer.token.value === 'on') {
	    throw unexpected(lexer);
	  }
	  return parseName(lexer);
	}

	// Implements the parsing rules in the Values section.

	/**
	 * Value[Const] :
	 *   - [~Const] Variable
	 *   - IntValue
	 *   - FloatValue
	 *   - StringValue
	 *   - BooleanValue
	 *   - NullValue
	 *   - EnumValue
	 *   - ListValue[?Const]
	 *   - ObjectValue[?Const]
	 *
	 * BooleanValue : one of `true` `false`
	 *
	 * NullValue : `null`
	 *
	 * EnumValue : Name but not `true`, `false` or `null`
	 */
	function parseValueLiteral(lexer, isConst) {
	  var token = lexer.token;
	  switch (token.kind) {
	    case _lexer.TokenKind.BRACKET_L:
	      return parseList(lexer, isConst);
	    case _lexer.TokenKind.BRACE_L:
	      return parseObject(lexer, isConst);
	    case _lexer.TokenKind.INT:
	      lexer.advance();
	      return {
	        kind: _kinds.INT,
	        value: token.value,
	        loc: loc(lexer, token)
	      };
	    case _lexer.TokenKind.FLOAT:
	      lexer.advance();
	      return {
	        kind: _kinds.FLOAT,
	        value: token.value,
	        loc: loc(lexer, token)
	      };
	    case _lexer.TokenKind.STRING:
	      lexer.advance();
	      return {
	        kind: _kinds.STRING,
	        value: token.value,
	        loc: loc(lexer, token)
	      };
	    case _lexer.TokenKind.NAME:
	      if (token.value === 'true' || token.value === 'false') {
	        lexer.advance();
	        return {
	          kind: _kinds.BOOLEAN,
	          value: token.value === 'true',
	          loc: loc(lexer, token)
	        };
	      } else if (token.value === 'null') {
	        lexer.advance();
	        return {
	          kind: _kinds.NULL,
	          loc: loc(lexer, token)
	        };
	      }
	      lexer.advance();
	      return {
	        kind: _kinds.ENUM,
	        value: token.value,
	        loc: loc(lexer, token)
	      };
	    case _lexer.TokenKind.DOLLAR:
	      if (!isConst) {
	        return parseVariable(lexer);
	      }
	      break;
	  }
	  throw unexpected(lexer);
	}

	function parseConstValue(lexer) {
	  return parseValueLiteral(lexer, true);
	}

	function parseValueValue(lexer) {
	  return parseValueLiteral(lexer, false);
	}

	/**
	 * ListValue[Const] :
	 *   - [ ]
	 *   - [ Value[?Const]+ ]
	 */
	function parseList(lexer, isConst) {
	  var start = lexer.token;
	  var item = isConst ? parseConstValue : parseValueValue;
	  return {
	    kind: _kinds.LIST,
	    values: any(lexer, _lexer.TokenKind.BRACKET_L, item, _lexer.TokenKind.BRACKET_R),
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * ObjectValue[Const] :
	 *   - { }
	 *   - { ObjectField[?Const]+ }
	 */
	function parseObject(lexer, isConst) {
	  var start = lexer.token;
	  expect(lexer, _lexer.TokenKind.BRACE_L);
	  var fields = [];
	  while (!skip(lexer, _lexer.TokenKind.BRACE_R)) {
	    fields.push(parseObjectField(lexer, isConst));
	  }
	  return {
	    kind: _kinds.OBJECT,
	    fields: fields,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * ObjectField[Const] : Name : Value[?Const]
	 */
	function parseObjectField(lexer, isConst) {
	  var start = lexer.token;
	  return {
	    kind: _kinds.OBJECT_FIELD,
	    name: parseName(lexer),
	    value: (expect(lexer, _lexer.TokenKind.COLON), parseValueLiteral(lexer, isConst)),
	    loc: loc(lexer, start)
	  };
	}

	// Implements the parsing rules in the Directives section.

	/**
	 * Directives : Directive+
	 */
	function parseDirectives(lexer) {
	  var directives = [];
	  while (peek(lexer, _lexer.TokenKind.AT)) {
	    directives.push(parseDirective(lexer));
	  }
	  return directives;
	}

	/**
	 * Directive : @ Name Arguments?
	 */
	function parseDirective(lexer) {
	  var start = lexer.token;
	  expect(lexer, _lexer.TokenKind.AT);
	  return {
	    kind: _kinds.DIRECTIVE,
	    name: parseName(lexer),
	    arguments: parseArguments(lexer),
	    loc: loc(lexer, start)
	  };
	}

	// Implements the parsing rules in the Types section.

	/**
	 * Type :
	 *   - NamedType
	 *   - ListType
	 *   - NonNullType
	 */
	function parseTypeReference(lexer) {
	  var start = lexer.token;
	  var type = void 0;
	  if (skip(lexer, _lexer.TokenKind.BRACKET_L)) {
	    type = parseTypeReference(lexer);
	    expect(lexer, _lexer.TokenKind.BRACKET_R);
	    type = {
	      kind: _kinds.LIST_TYPE,
	      type: type,
	      loc: loc(lexer, start)
	    };
	  } else {
	    type = parseNamedType(lexer);
	  }
	  if (skip(lexer, _lexer.TokenKind.BANG)) {
	    return {
	      kind: _kinds.NON_NULL_TYPE,
	      type: type,
	      loc: loc(lexer, start)
	    };
	  }
	  return type;
	}

	/**
	 * NamedType : Name
	 */
	function parseNamedType(lexer) {
	  var start = lexer.token;
	  return {
	    kind: _kinds.NAMED_TYPE,
	    name: parseName(lexer),
	    loc: loc(lexer, start)
	  };
	}

	// Implements the parsing rules in the Type Definition section.

	/**
	 * TypeSystemDefinition :
	 *   - SchemaDefinition
	 *   - TypeDefinition
	 *   - TypeExtensionDefinition
	 *   - DirectiveDefinition
	 *
	 * TypeDefinition :
	 *   - ScalarTypeDefinition
	 *   - ObjectTypeDefinition
	 *   - InterfaceTypeDefinition
	 *   - UnionTypeDefinition
	 *   - EnumTypeDefinition
	 *   - InputObjectTypeDefinition
	 */
	function parseTypeSystemDefinition(lexer) {
	  if (peek(lexer, _lexer.TokenKind.NAME)) {
	    switch (lexer.token.value) {
	      case 'schema':
	        return parseSchemaDefinition(lexer);
	      case 'scalar':
	        return parseScalarTypeDefinition(lexer);
	      case 'type':
	        return parseObjectTypeDefinition(lexer);
	      case 'interface':
	        return parseInterfaceTypeDefinition(lexer);
	      case 'union':
	        return parseUnionTypeDefinition(lexer);
	      case 'enum':
	        return parseEnumTypeDefinition(lexer);
	      case 'input':
	        return parseInputObjectTypeDefinition(lexer);
	      case 'extend':
	        return parseTypeExtensionDefinition(lexer);
	      case 'directive':
	        return parseDirectiveDefinition(lexer);
	    }
	  }

	  throw unexpected(lexer);
	}

	/**
	 * SchemaDefinition : schema Directives? { OperationTypeDefinition+ }
	 *
	 * OperationTypeDefinition : OperationType : NamedType
	 */
	function parseSchemaDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'schema');
	  var directives = parseDirectives(lexer);
	  var operationTypes = many(lexer, _lexer.TokenKind.BRACE_L, parseOperationTypeDefinition, _lexer.TokenKind.BRACE_R);
	  return {
	    kind: _kinds.SCHEMA_DEFINITION,
	    directives: directives,
	    operationTypes: operationTypes,
	    loc: loc(lexer, start)
	  };
	}

	function parseOperationTypeDefinition(lexer) {
	  var start = lexer.token;
	  var operation = parseOperationType(lexer);
	  expect(lexer, _lexer.TokenKind.COLON);
	  var type = parseNamedType(lexer);
	  return {
	    kind: _kinds.OPERATION_TYPE_DEFINITION,
	    operation: operation,
	    type: type,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * ScalarTypeDefinition : scalar Name Directives?
	 */
	function parseScalarTypeDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'scalar');
	  var name = parseName(lexer);
	  var directives = parseDirectives(lexer);
	  return {
	    kind: _kinds.SCALAR_TYPE_DEFINITION,
	    name: name,
	    directives: directives,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * ObjectTypeDefinition :
	 *   - type Name ImplementsInterfaces? Directives? { FieldDefinition+ }
	 */
	function parseObjectTypeDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'type');
	  var name = parseName(lexer);
	  var interfaces = parseImplementsInterfaces(lexer);
	  var directives = parseDirectives(lexer);
	  var fields = any(lexer, _lexer.TokenKind.BRACE_L, parseFieldDefinition, _lexer.TokenKind.BRACE_R);
	  return {
	    kind: _kinds.OBJECT_TYPE_DEFINITION,
	    name: name,
	    interfaces: interfaces,
	    directives: directives,
	    fields: fields,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * ImplementsInterfaces : implements NamedType+
	 */
	function parseImplementsInterfaces(lexer) {
	  var types = [];
	  if (lexer.token.value === 'implements') {
	    lexer.advance();
	    do {
	      types.push(parseNamedType(lexer));
	    } while (peek(lexer, _lexer.TokenKind.NAME));
	  }
	  return types;
	}

	/**
	 * FieldDefinition : Name ArgumentsDefinition? : Type Directives?
	 */
	function parseFieldDefinition(lexer) {
	  var start = lexer.token;
	  var name = parseName(lexer);
	  var args = parseArgumentDefs(lexer);
	  expect(lexer, _lexer.TokenKind.COLON);
	  var type = parseTypeReference(lexer);
	  var directives = parseDirectives(lexer);
	  return {
	    kind: _kinds.FIELD_DEFINITION,
	    name: name,
	    arguments: args,
	    type: type,
	    directives: directives,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * ArgumentsDefinition : ( InputValueDefinition+ )
	 */
	function parseArgumentDefs(lexer) {
	  if (!peek(lexer, _lexer.TokenKind.PAREN_L)) {
	    return [];
	  }
	  return many(lexer, _lexer.TokenKind.PAREN_L, parseInputValueDef, _lexer.TokenKind.PAREN_R);
	}

	/**
	 * InputValueDefinition : Name : Type DefaultValue? Directives?
	 */
	function parseInputValueDef(lexer) {
	  var start = lexer.token;
	  var name = parseName(lexer);
	  expect(lexer, _lexer.TokenKind.COLON);
	  var type = parseTypeReference(lexer);
	  var defaultValue = null;
	  if (skip(lexer, _lexer.TokenKind.EQUALS)) {
	    defaultValue = parseConstValue(lexer);
	  }
	  var directives = parseDirectives(lexer);
	  return {
	    kind: _kinds.INPUT_VALUE_DEFINITION,
	    name: name,
	    type: type,
	    defaultValue: defaultValue,
	    directives: directives,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * InterfaceTypeDefinition : interface Name Directives? { FieldDefinition+ }
	 */
	function parseInterfaceTypeDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'interface');
	  var name = parseName(lexer);
	  var directives = parseDirectives(lexer);
	  var fields = any(lexer, _lexer.TokenKind.BRACE_L, parseFieldDefinition, _lexer.TokenKind.BRACE_R);
	  return {
	    kind: _kinds.INTERFACE_TYPE_DEFINITION,
	    name: name,
	    directives: directives,
	    fields: fields,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * UnionTypeDefinition : union Name Directives? = UnionMembers
	 */
	function parseUnionTypeDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'union');
	  var name = parseName(lexer);
	  var directives = parseDirectives(lexer);
	  expect(lexer, _lexer.TokenKind.EQUALS);
	  var types = parseUnionMembers(lexer);
	  return {
	    kind: _kinds.UNION_TYPE_DEFINITION,
	    name: name,
	    directives: directives,
	    types: types,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * UnionMembers :
	 *   - NamedType
	 *   - UnionMembers | NamedType
	 */
	function parseUnionMembers(lexer) {
	  var members = [];
	  do {
	    members.push(parseNamedType(lexer));
	  } while (skip(lexer, _lexer.TokenKind.PIPE));
	  return members;
	}

	/**
	 * EnumTypeDefinition : enum Name Directives? { EnumValueDefinition+ }
	 */
	function parseEnumTypeDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'enum');
	  var name = parseName(lexer);
	  var directives = parseDirectives(lexer);
	  var values = many(lexer, _lexer.TokenKind.BRACE_L, parseEnumValueDefinition, _lexer.TokenKind.BRACE_R);
	  return {
	    kind: _kinds.ENUM_TYPE_DEFINITION,
	    name: name,
	    directives: directives,
	    values: values,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * EnumValueDefinition : EnumValue Directives?
	 *
	 * EnumValue : Name
	 */
	function parseEnumValueDefinition(lexer) {
	  var start = lexer.token;
	  var name = parseName(lexer);
	  var directives = parseDirectives(lexer);
	  return {
	    kind: _kinds.ENUM_VALUE_DEFINITION,
	    name: name,
	    directives: directives,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * InputObjectTypeDefinition : input Name Directives? { InputValueDefinition+ }
	 */
	function parseInputObjectTypeDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'input');
	  var name = parseName(lexer);
	  var directives = parseDirectives(lexer);
	  var fields = any(lexer, _lexer.TokenKind.BRACE_L, parseInputValueDef, _lexer.TokenKind.BRACE_R);
	  return {
	    kind: _kinds.INPUT_OBJECT_TYPE_DEFINITION,
	    name: name,
	    directives: directives,
	    fields: fields,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * TypeExtensionDefinition : extend ObjectTypeDefinition
	 */
	function parseTypeExtensionDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'extend');
	  var definition = parseObjectTypeDefinition(lexer);
	  return {
	    kind: _kinds.TYPE_EXTENSION_DEFINITION,
	    definition: definition,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * DirectiveDefinition :
	 *   - directive @ Name ArgumentsDefinition? on DirectiveLocations
	 */
	function parseDirectiveDefinition(lexer) {
	  var start = lexer.token;
	  expectKeyword(lexer, 'directive');
	  expect(lexer, _lexer.TokenKind.AT);
	  var name = parseName(lexer);
	  var args = parseArgumentDefs(lexer);
	  expectKeyword(lexer, 'on');
	  var locations = parseDirectiveLocations(lexer);
	  return {
	    kind: _kinds.DIRECTIVE_DEFINITION,
	    name: name,
	    arguments: args,
	    locations: locations,
	    loc: loc(lexer, start)
	  };
	}

	/**
	 * DirectiveLocations :
	 *   - Name
	 *   - DirectiveLocations | Name
	 */
	function parseDirectiveLocations(lexer) {
	  var locations = [];
	  do {
	    locations.push(parseName(lexer));
	  } while (skip(lexer, _lexer.TokenKind.PIPE));
	  return locations;
	}

	// Core parsing utility functions

	/**
	 * Returns a location object, used to identify the place in
	 * the source that created a given parsed object.
	 */
	function loc(lexer, startToken) {
	  if (!lexer.options.noLocation) {
	    return new Loc(startToken, lexer.lastToken, lexer.source);
	  }
	}

	function Loc(startToken, endToken, source) {
	  this.start = startToken.start;
	  this.end = endToken.end;
	  this.startToken = startToken;
	  this.endToken = endToken;
	  this.source = source;
	}

	// Print a simplified form when appearing in JSON/util.inspect.
	Loc.prototype.toJSON = Loc.prototype.inspect = function toJSON() {
	  return { start: this.start, end: this.end };
	};

	/**
	 * Determines if the next token is of a given kind
	 */
	function peek(lexer, kind) {
	  return lexer.token.kind === kind;
	}

	/**
	 * If the next token is of the given kind, return true after advancing
	 * the lexer. Otherwise, do not change the parser state and return false.
	 */
	function skip(lexer, kind) {
	  var match = lexer.token.kind === kind;
	  if (match) {
	    lexer.advance();
	  }
	  return match;
	}

	/**
	 * If the next token is of the given kind, return that token after advancing
	 * the lexer. Otherwise, do not change the parser state and throw an error.
	 */
	function expect(lexer, kind) {
	  var token = lexer.token;
	  if (token.kind === kind) {
	    lexer.advance();
	    return token;
	  }
	  throw (0, _error.syntaxError)(lexer.source, token.start, 'Expected ' + kind + ', found ' + (0, _lexer.getTokenDesc)(token));
	}

	/**
	 * If the next token is a keyword with the given value, return that token after
	 * advancing the lexer. Otherwise, do not change the parser state and return
	 * false.
	 */
	function expectKeyword(lexer, value) {
	  var token = lexer.token;
	  if (token.kind === _lexer.TokenKind.NAME && token.value === value) {
	    lexer.advance();
	    return token;
	  }
	  throw (0, _error.syntaxError)(lexer.source, token.start, 'Expected "' + value + '", found ' + (0, _lexer.getTokenDesc)(token));
	}

	/**
	 * Helper function for creating an error when an unexpected lexed token
	 * is encountered.
	 */
	function unexpected(lexer, atToken) {
	  var token = atToken || lexer.token;
	  return (0, _error.syntaxError)(lexer.source, token.start, 'Unexpected ' + (0, _lexer.getTokenDesc)(token));
	}

	/**
	 * Returns a possibly empty list of parse nodes, determined by
	 * the parseFn. This list begins with a lex token of openKind
	 * and ends with a lex token of closeKind. Advances the parser
	 * to the next lex token after the closing token.
	 */
	function any(lexer, openKind, parseFn, closeKind) {
	  expect(lexer, openKind);
	  var nodes = [];
	  while (!skip(lexer, closeKind)) {
	    nodes.push(parseFn(lexer));
	  }
	  return nodes;
	}

	/**
	 * Returns a non-empty list of parse nodes, determined by
	 * the parseFn. This list begins with a lex token of openKind
	 * and ends with a lex token of closeKind. Advances the parser
	 * to the next lex token after the closing token.
	 */
	function many(lexer, openKind, parseFn, closeKind) {
	  expect(lexer, openKind);
	  var nodes = [parseFn(lexer)];
	  while (!skip(lexer, closeKind)) {
	    nodes.push(parseFn(lexer));
	  }
	  return nodes;
	}

/***/ },
/* 2 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	/**
	 * A representation of source input to GraphQL. The name is optional,
	 * but is mostly useful for clients who store GraphQL documents in
	 * source files; for example, if the GraphQL input is in a file Foo.graphql,
	 * it might be useful for name to be "Foo.graphql".
	 */
	var Source = exports.Source = function Source(body, name) {
	  _classCallCheck(this, Source);

	  this.body = body;
	  this.name = name || 'GraphQL';
	};

/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _GraphQLError = __webpack_require__(4);

	Object.defineProperty(exports, 'GraphQLError', {
	  enumerable: true,
	  get: function get() {
	    return _GraphQLError.GraphQLError;
	  }
	});

	var _syntaxError = __webpack_require__(6);

	Object.defineProperty(exports, 'syntaxError', {
	  enumerable: true,
	  get: function get() {
	    return _syntaxError.syntaxError;
	  }
	});

	var _locatedError = __webpack_require__(7);

	Object.defineProperty(exports, 'locatedError', {
	  enumerable: true,
	  get: function get() {
	    return _locatedError.locatedError;
	  }
	});

	var _formatError = __webpack_require__(8);

	Object.defineProperty(exports, 'formatError', {
	  enumerable: true,
	  get: function get() {
	    return _formatError.formatError;
	  }
	});

/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.GraphQLError = GraphQLError;

	var _location = __webpack_require__(5);

	/**
	 * A GraphQLError describes an Error found during the parse, validate, or
	 * execute phases of performing a GraphQL operation. In addition to a message
	 * and stack trace, it also includes information about the locations in a
	 * GraphQL document and/or execution result that correspond to the Error.
	 */
	function GraphQLError( // eslint-disable-line no-redeclare
	message, nodes, source, positions, path, originalError) {
	  // Include (non-enumerable) stack trace.
	  if (originalError && originalError.stack) {
	    Object.defineProperty(this, 'stack', {
	      value: originalError.stack,
	      writable: true,
	      configurable: true
	    });
	  } else if (Error.captureStackTrace) {
	    Error.captureStackTrace(this, GraphQLError);
	  } else {
	    Object.defineProperty(this, 'stack', {
	      value: Error().stack,
	      writable: true,
	      configurable: true
	    });
	  }

	  // Compute locations in the source for the given nodes/positions.
	  var _source = source;
	  if (!_source && nodes && nodes.length > 0) {
	    var node = nodes[0];
	    _source = node && node.loc && node.loc.source;
	  }

	  var _positions = positions;
	  if (!_positions && nodes) {
	    _positions = nodes.filter(function (node) {
	      return Boolean(node.loc);
	    }).map(function (node) {
	      return node.loc.start;
	    });
	  }
	  if (_positions && _positions.length === 0) {
	    _positions = undefined;
	  }

	  var _locations = void 0;
	  var _source2 = _source; // seems here Flow need a const to resolve type.
	  if (_source2 && _positions) {
	    _locations = _positions.map(function (pos) {
	      return (0, _location.getLocation)(_source2, pos);
	    });
	  }

	  Object.defineProperties(this, {
	    message: {
	      value: message,
	      // By being enumerable, JSON.stringify will include `message` in the
	      // resulting output. This ensures that the simplist possible GraphQL
	      // service adheres to the spec.
	      enumerable: true,
	      writable: true
	    },
	    locations: {
	      // Coercing falsey values to undefined ensures they will not be included
	      // in JSON.stringify() when not provided.
	      value: _locations || undefined,
	      // By being enumerable, JSON.stringify will include `locations` in the
	      // resulting output. This ensures that the simplist possible GraphQL
	      // service adheres to the spec.
	      enumerable: true
	    },
	    path: {
	      // Coercing falsey values to undefined ensures they will not be included
	      // in JSON.stringify() when not provided.
	      value: path || undefined,
	      // By being enumerable, JSON.stringify will include `path` in the
	      // resulting output. This ensures that the simplist possible GraphQL
	      // service adheres to the spec.
	      enumerable: true
	    },
	    nodes: {
	      value: nodes || undefined
	    },
	    source: {
	      value: _source || undefined
	    },
	    positions: {
	      value: _positions || undefined
	    },
	    originalError: {
	      value: originalError
	    }
	  });
	}
	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	GraphQLError.prototype = Object.create(Error.prototype, {
	  constructor: { value: GraphQLError },
	  name: { value: 'GraphQLError' }
	});

/***/ },
/* 5 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.getLocation = getLocation;


	/**
	 * Takes a Source and a UTF-8 character offset, and returns the corresponding
	 * line and column as a SourceLocation.
	 */

	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	function getLocation(source, position) {
	  var lineRegexp = /\r\n|[\n\r]/g;
	  var line = 1;
	  var column = position + 1;
	  var match = void 0;
	  while ((match = lineRegexp.exec(source.body)) && match.index < position) {
	    line += 1;
	    column = position + 1 - (match.index + match[0].length);
	  }
	  return { line: line, column: column };
	}

	/**
	 * Represents a location in a Source.
	 */

/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.syntaxError = syntaxError;

	var _location = __webpack_require__(5);

	var _GraphQLError = __webpack_require__(4);

	/**
	 * Produces a GraphQLError representing a syntax error, containing useful
	 * descriptive information about the syntax error's position in the source.
	 */

	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	function syntaxError(source, position, description) {
	  var location = (0, _location.getLocation)(source, position);
	  var error = new _GraphQLError.GraphQLError('Syntax Error ' + source.name + ' (' + location.line + ':' + location.column + ') ' + description + '\n\n' + highlightSourceAtLocation(source, location), undefined, source, [position]);
	  return error;
	}

	/**
	 * Render a helpful description of the location of the error in the GraphQL
	 * Source document.
	 */
	function highlightSourceAtLocation(source, location) {
	  var line = location.line;
	  var prevLineNum = (line - 1).toString();
	  var lineNum = line.toString();
	  var nextLineNum = (line + 1).toString();
	  var padLen = nextLineNum.length;
	  var lines = source.body.split(/\r\n|[\n\r]/g);
	  return (line >= 2 ? lpad(padLen, prevLineNum) + ': ' + lines[line - 2] + '\n' : '') + lpad(padLen, lineNum) + ': ' + lines[line - 1] + '\n' + Array(2 + padLen + location.column).join(' ') + '^\n' + (line < lines.length ? lpad(padLen, nextLineNum) + ': ' + lines[line] + '\n' : '');
	}

	function lpad(len, str) {
	  return Array(len - str.length + 1).join(' ') + str;
	}

/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.locatedError = locatedError;

	var _GraphQLError = __webpack_require__(4);

	/**
	 * Given an arbitrary Error, presumably thrown while attempting to execute a
	 * GraphQL operation, produce a new GraphQLError aware of the location in the
	 * document responsible for the original Error.
	 */
	function locatedError(originalError, nodes, path) {
	  // Note: this uses a brand-check to support GraphQL errors originating from
	  // other contexts.
	  if (originalError && originalError.path) {
	    return originalError;
	  }

	  var message = originalError ? originalError.message || String(originalError) : 'An unknown error occurred.';
	  return new _GraphQLError.GraphQLError(message, originalError && originalError.nodes || nodes, originalError && originalError.source, originalError && originalError.positions, path, originalError);
	}
	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.formatError = formatError;

	var _invariant = __webpack_require__(9);

	var _invariant2 = _interopRequireDefault(_invariant);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	/**
	 * Given a GraphQLError, format it according to the rules described by the
	 * Response Format, Errors section of the GraphQL Specification.
	 */
	function formatError(error) {
	  (0, _invariant2.default)(error, 'Received null or undefined error.');
	  return {
	    message: error.message,
	    locations: error.locations,
	    path: error.path
	  };
	}
	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

/***/ },
/* 9 */
/***/ function(module, exports) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.default = invariant;

	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	function invariant(condition, message) {
	  if (!condition) {
	    throw new Error(message);
	  }
	}

/***/ },
/* 10 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.TokenKind = undefined;
	exports.createLexer = createLexer;
	exports.getTokenDesc = getTokenDesc;

	var _error = __webpack_require__(3);

	/**
	 * Given a Source object, this returns a Lexer for that source.
	 * A Lexer is a stateful stream generator in that every time
	 * it is advanced, it returns the next token in the Source. Assuming the
	 * source lexes, the final Token emitted by the lexer will be of kind
	 * EOF, after which the lexer will repeatedly return the same EOF token
	 * whenever called.
	 */
	function createLexer(source, options) {
	  var startOfFileToken = new Tok(SOF, 0, 0, 0, 0, null);
	  var lexer = {
	    source: source,
	    options: options,
	    lastToken: startOfFileToken,
	    token: startOfFileToken,
	    line: 1,
	    lineStart: 0,
	    advance: advanceLexer
	  };
	  return lexer;
	} /*  /
	  /**
	   *  Copyright (c) 2015, Facebook, Inc.
	   *  All rights reserved.
	   *
	   *  This source code is licensed under the BSD-style license found in the
	   *  LICENSE file in the root directory of this source tree. An additional grant
	   *  of patent rights can be found in the PATENTS file in the same directory.
	   */

	function advanceLexer() {
	  var token = this.lastToken = this.token;
	  if (token.kind !== EOF) {
	    do {
	      token = token.next = readToken(this, token);
	    } while (token.kind === COMMENT);
	    this.token = token;
	  }
	  return token;
	}

	/**
	 * The return type of createLexer.
	 */


	// Each kind of token.
	var SOF = '<SOF>';
	var EOF = '<EOF>';
	var BANG = '!';
	var DOLLAR = '$';
	var PAREN_L = '(';
	var PAREN_R = ')';
	var SPREAD = '...';
	var COLON = ':';
	var EQUALS = '=';
	var AT = '@';
	var BRACKET_L = '[';
	var BRACKET_R = ']';
	var BRACE_L = '{';
	var PIPE = '|';
	var BRACE_R = '}';
	var NAME = 'Name';
	var INT = 'Int';
	var FLOAT = 'Float';
	var STRING = 'String';
	var COMMENT = 'Comment';

	/**
	 * An exported enum describing the different kinds of tokens that the
	 * lexer emits.
	 */
	var TokenKind = exports.TokenKind = {
	  SOF: SOF,
	  EOF: EOF,
	  BANG: BANG,
	  DOLLAR: DOLLAR,
	  PAREN_L: PAREN_L,
	  PAREN_R: PAREN_R,
	  SPREAD: SPREAD,
	  COLON: COLON,
	  EQUALS: EQUALS,
	  AT: AT,
	  BRACKET_L: BRACKET_L,
	  BRACKET_R: BRACKET_R,
	  BRACE_L: BRACE_L,
	  PIPE: PIPE,
	  BRACE_R: BRACE_R,
	  NAME: NAME,
	  INT: INT,
	  FLOAT: FLOAT,
	  STRING: STRING,
	  COMMENT: COMMENT
	};

	/**
	 * A helper function to describe a token as a string for debugging
	 */
	function getTokenDesc(token) {
	  var value = token.value;
	  return value ? token.kind + ' "' + value + '"' : token.kind;
	}

	var charCodeAt = String.prototype.charCodeAt;
	var slice = String.prototype.slice;

	/**
	 * Helper function for constructing the Token object.
	 */
	function Tok(kind, start, end, line, column, prev, value) {
	  this.kind = kind;
	  this.start = start;
	  this.end = end;
	  this.line = line;
	  this.column = column;
	  this.value = value;
	  this.prev = prev;
	  this.next = null;
	}

	// Print a simplified form when appearing in JSON/util.inspect.
	Tok.prototype.toJSON = Tok.prototype.inspect = function toJSON() {
	  return {
	    kind: this.kind,
	    value: this.value,
	    line: this.line,
	    column: this.column
	  };
	};

	function printCharCode(code) {
	  return (
	    // NaN/undefined represents access beyond the end of the file.
	    isNaN(code) ? EOF :
	    // Trust JSON for ASCII.
	    code < 0x007F ? JSON.stringify(String.fromCharCode(code)) :
	    // Otherwise print the escaped form.
	    '"\\u' + ('00' + code.toString(16).toUpperCase()).slice(-4) + '"'
	  );
	}

	/**
	 * Gets the next token from the source starting at the given position.
	 *
	 * This skips over whitespace and comments until it finds the next lexable
	 * token, then lexes punctuators immediately or calls the appropriate helper
	 * function for more complicated tokens.
	 */
	function readToken(lexer, prev) {
	  var source = lexer.source;
	  var body = source.body;
	  var bodyLength = body.length;

	  var position = positionAfterWhitespace(body, prev.end, lexer);
	  var line = lexer.line;
	  var col = 1 + position - lexer.lineStart;

	  if (position >= bodyLength) {
	    return new Tok(EOF, bodyLength, bodyLength, line, col, prev);
	  }

	  var code = charCodeAt.call(body, position);

	  // SourceCharacter
	  if (code < 0x0020 && code !== 0x0009 && code !== 0x000A && code !== 0x000D) {
	    throw (0, _error.syntaxError)(source, position, 'Cannot contain the invalid character ' + printCharCode(code) + '.');
	  }

	  switch (code) {
	    // !
	    case 33:
	      return new Tok(BANG, position, position + 1, line, col, prev);
	    // #
	    case 35:
	      return readComment(source, position, line, col, prev);
	    // $
	    case 36:
	      return new Tok(DOLLAR, position, position + 1, line, col, prev);
	    // (
	    case 40:
	      return new Tok(PAREN_L, position, position + 1, line, col, prev);
	    // )
	    case 41:
	      return new Tok(PAREN_R, position, position + 1, line, col, prev);
	    // .
	    case 46:
	      if (charCodeAt.call(body, position + 1) === 46 && charCodeAt.call(body, position + 2) === 46) {
	        return new Tok(SPREAD, position, position + 3, line, col, prev);
	      }
	      break;
	    // :
	    case 58:
	      return new Tok(COLON, position, position + 1, line, col, prev);
	    // =
	    case 61:
	      return new Tok(EQUALS, position, position + 1, line, col, prev);
	    // @
	    case 64:
	      return new Tok(AT, position, position + 1, line, col, prev);
	    // [
	    case 91:
	      return new Tok(BRACKET_L, position, position + 1, line, col, prev);
	    // ]
	    case 93:
	      return new Tok(BRACKET_R, position, position + 1, line, col, prev);
	    // {
	    case 123:
	      return new Tok(BRACE_L, position, position + 1, line, col, prev);
	    // |
	    case 124:
	      return new Tok(PIPE, position, position + 1, line, col, prev);
	    // }
	    case 125:
	      return new Tok(BRACE_R, position, position + 1, line, col, prev);
	    // A-Z _ a-z
	    case 65:case 66:case 67:case 68:case 69:case 70:case 71:case 72:
	    case 73:case 74:case 75:case 76:case 77:case 78:case 79:case 80:
	    case 81:case 82:case 83:case 84:case 85:case 86:case 87:case 88:
	    case 89:case 90:
	    case 95:
	    case 97:case 98:case 99:case 100:case 101:case 102:case 103:case 104:
	    case 105:case 106:case 107:case 108:case 109:case 110:case 111:
	    case 112:case 113:case 114:case 115:case 116:case 117:case 118:
	    case 119:case 120:case 121:case 122:
	      return readName(source, position, line, col, prev);
	    // - 0-9
	    case 45:
	    case 48:case 49:case 50:case 51:case 52:
	    case 53:case 54:case 55:case 56:case 57:
	      return readNumber(source, position, code, line, col, prev);
	    // "
	    case 34:
	      return readString(source, position, line, col, prev);
	  }

	  throw (0, _error.syntaxError)(source, position, unexpectedCharacterMessage(code));
	}

	/**
	 * Report a message that an unexpected character was encountered.
	 */
	function unexpectedCharacterMessage(code) {
	  if (code === 39) {
	    // '
	    return 'Unexpected single quote character (\'), did you mean to use ' + 'a double quote (")?';
	  }

	  return 'Cannot parse the unexpected character ' + printCharCode(code) + '.';
	}

	/**
	 * Reads from body starting at startPosition until it finds a non-whitespace
	 * or commented character, then returns the position of that character for
	 * lexing.
	 */
	function positionAfterWhitespace(body, startPosition, lexer) {
	  var bodyLength = body.length;
	  var position = startPosition;
	  while (position < bodyLength) {
	    var code = charCodeAt.call(body, position);
	    // tab | space | comma | BOM
	    if (code === 9 || code === 32 || code === 44 || code === 0xFEFF) {
	      ++position;
	    } else if (code === 10) {
	      // new line
	      ++position;
	      ++lexer.line;
	      lexer.lineStart = position;
	    } else if (code === 13) {
	      // carriage return
	      if (charCodeAt.call(body, position + 1) === 10) {
	        position += 2;
	      } else {
	        ++position;
	      }
	      ++lexer.line;
	      lexer.lineStart = position;
	    } else {
	      break;
	    }
	  }
	  return position;
	}

	/**
	 * Reads a comment token from the source file.
	 *
	 * #[\u0009\u0020-\uFFFF]*
	 */
	function readComment(source, start, line, col, prev) {
	  var body = source.body;
	  var code = void 0;
	  var position = start;

	  do {
	    code = charCodeAt.call(body, ++position);
	  } while (code !== null && (
	  // SourceCharacter but not LineTerminator
	  code > 0x001F || code === 0x0009));

	  return new Tok(COMMENT, start, position, line, col, prev, slice.call(body, start + 1, position));
	}

	/**
	 * Reads a number token from the source file, either a float
	 * or an int depending on whether a decimal point appears.
	 *
	 * Int:   -?(0|[1-9][0-9]*)
	 * Float: -?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)?
	 */
	function readNumber(source, start, firstCode, line, col, prev) {
	  var body = source.body;
	  var code = firstCode;
	  var position = start;
	  var isFloat = false;

	  if (code === 45) {
	    // -
	    code = charCodeAt.call(body, ++position);
	  }

	  if (code === 48) {
	    // 0
	    code = charCodeAt.call(body, ++position);
	    if (code >= 48 && code <= 57) {
	      throw (0, _error.syntaxError)(source, position, 'Invalid number, unexpected digit after 0: ' + printCharCode(code) + '.');
	    }
	  } else {
	    position = readDigits(source, position, code);
	    code = charCodeAt.call(body, position);
	  }

	  if (code === 46) {
	    // .
	    isFloat = true;

	    code = charCodeAt.call(body, ++position);
	    position = readDigits(source, position, code);
	    code = charCodeAt.call(body, position);
	  }

	  if (code === 69 || code === 101) {
	    // E e
	    isFloat = true;

	    code = charCodeAt.call(body, ++position);
	    if (code === 43 || code === 45) {
	      // + -
	      code = charCodeAt.call(body, ++position);
	    }
	    position = readDigits(source, position, code);
	  }

	  return new Tok(isFloat ? FLOAT : INT, start, position, line, col, prev, slice.call(body, start, position));
	}

	/**
	 * Returns the new position in the source after reading digits.
	 */
	function readDigits(source, start, firstCode) {
	  var body = source.body;
	  var position = start;
	  var code = firstCode;
	  if (code >= 48 && code <= 57) {
	    // 0 - 9
	    do {
	      code = charCodeAt.call(body, ++position);
	    } while (code >= 48 && code <= 57); // 0 - 9
	    return position;
	  }
	  throw (0, _error.syntaxError)(source, position, 'Invalid number, expected digit but got: ' + printCharCode(code) + '.');
	}

	/**
	 * Reads a string token from the source file.
	 *
	 * "([^"\\\u000A\u000D]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*"
	 */
	function readString(source, start, line, col, prev) {
	  var body = source.body;
	  var position = start + 1;
	  var chunkStart = position;
	  var code = 0;
	  var value = '';

	  while (position < body.length && (code = charCodeAt.call(body, position)) !== null &&
	  // not LineTerminator
	  code !== 0x000A && code !== 0x000D &&
	  // not Quote (")
	  code !== 34) {
	    // SourceCharacter
	    if (code < 0x0020 && code !== 0x0009) {
	      throw (0, _error.syntaxError)(source, position, 'Invalid character within String: ' + printCharCode(code) + '.');
	    }

	    ++position;
	    if (code === 92) {
	      // \
	      value += slice.call(body, chunkStart, position - 1);
	      code = charCodeAt.call(body, position);
	      switch (code) {
	        case 34:
	          value += '"';break;
	        case 47:
	          value += '/';break;
	        case 92:
	          value += '\\';break;
	        case 98:
	          value += '\b';break;
	        case 102:
	          value += '\f';break;
	        case 110:
	          value += '\n';break;
	        case 114:
	          value += '\r';break;
	        case 116:
	          value += '\t';break;
	        case 117:
	          // u
	          var charCode = uniCharCode(charCodeAt.call(body, position + 1), charCodeAt.call(body, position + 2), charCodeAt.call(body, position + 3), charCodeAt.call(body, position + 4));
	          if (charCode < 0) {
	            throw (0, _error.syntaxError)(source, position, 'Invalid character escape sequence: ' + ('\\u' + body.slice(position + 1, position + 5) + '.'));
	          }
	          value += String.fromCharCode(charCode);
	          position += 4;
	          break;
	        default:
	          throw (0, _error.syntaxError)(source, position, 'Invalid character escape sequence: \\' + String.fromCharCode(code) + '.');
	      }
	      ++position;
	      chunkStart = position;
	    }
	  }

	  if (code !== 34) {
	    // quote (")
	    throw (0, _error.syntaxError)(source, position, 'Unterminated string.');
	  }

	  value += slice.call(body, chunkStart, position);
	  return new Tok(STRING, start, position + 1, line, col, prev, value);
	}

	/**
	 * Converts four hexidecimal chars to the integer that the
	 * string represents. For example, uniCharCode('0','0','0','f')
	 * will return 15, and uniCharCode('0','0','f','f') returns 255.
	 *
	 * Returns a negative number on error, if a char was invalid.
	 *
	 * This is implemented by noting that char2hex() returns -1 on error,
	 * which means the result of ORing the char2hex() will also be negative.
	 */
	function uniCharCode(a, b, c, d) {
	  return char2hex(a) << 12 | char2hex(b) << 8 | char2hex(c) << 4 | char2hex(d);
	}

	/**
	 * Converts a hex character to its integer value.
	 * '0' becomes 0, '9' becomes 9
	 * 'A' becomes 10, 'F' becomes 15
	 * 'a' becomes 10, 'f' becomes 15
	 *
	 * Returns -1 on error.
	 */
	function char2hex(a) {
	  return a >= 48 && a <= 57 ? a - 48 : // 0-9
	  a >= 65 && a <= 70 ? a - 55 : // A-F
	  a >= 97 && a <= 102 ? a - 87 : // a-f
	  -1;
	}

	/**
	 * Reads an alphanumeric + underscore name from the source.
	 *
	 * [_A-Za-z][_0-9A-Za-z]*
	 */
	function readName(source, position, line, col, prev) {
	  var body = source.body;
	  var bodyLength = body.length;
	  var end = position + 1;
	  var code = 0;
	  while (end !== bodyLength && (code = charCodeAt.call(body, end)) !== null && (code === 95 || // _
	  code >= 48 && code <= 57 || // 0-9
	  code >= 65 && code <= 90 || // A-Z
	  code >= 97 && code <= 122 // a-z
	  )) {
	    ++end;
	  }
	  return new Tok(NAME, position, end, line, col, prev, slice.call(body, position, end));
	}

/***/ },
/* 11 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	// Name

	var NAME = exports.NAME = 'Name';

	// Document

	var DOCUMENT = exports.DOCUMENT = 'Document';
	var OPERATION_DEFINITION = exports.OPERATION_DEFINITION = 'OperationDefinition';
	var VARIABLE_DEFINITION = exports.VARIABLE_DEFINITION = 'VariableDefinition';
	var VARIABLE = exports.VARIABLE = 'Variable';
	var SELECTION_SET = exports.SELECTION_SET = 'SelectionSet';
	var FIELD = exports.FIELD = 'Field';
	var ARGUMENT = exports.ARGUMENT = 'Argument';

	// Fragments

	var FRAGMENT_SPREAD = exports.FRAGMENT_SPREAD = 'FragmentSpread';
	var INLINE_FRAGMENT = exports.INLINE_FRAGMENT = 'InlineFragment';
	var FRAGMENT_DEFINITION = exports.FRAGMENT_DEFINITION = 'FragmentDefinition';

	// Values

	var INT = exports.INT = 'IntValue';
	var FLOAT = exports.FLOAT = 'FloatValue';
	var STRING = exports.STRING = 'StringValue';
	var BOOLEAN = exports.BOOLEAN = 'BooleanValue';
	var NULL = exports.NULL = 'NullValue';
	var ENUM = exports.ENUM = 'EnumValue';
	var LIST = exports.LIST = 'ListValue';
	var OBJECT = exports.OBJECT = 'ObjectValue';
	var OBJECT_FIELD = exports.OBJECT_FIELD = 'ObjectField';

	// Directives

	var DIRECTIVE = exports.DIRECTIVE = 'Directive';

	// Types

	var NAMED_TYPE = exports.NAMED_TYPE = 'NamedType';
	var LIST_TYPE = exports.LIST_TYPE = 'ListType';
	var NON_NULL_TYPE = exports.NON_NULL_TYPE = 'NonNullType';

	// Type System Definitions

	var SCHEMA_DEFINITION = exports.SCHEMA_DEFINITION = 'SchemaDefinition';
	var OPERATION_TYPE_DEFINITION = exports.OPERATION_TYPE_DEFINITION = 'OperationTypeDefinition';

	// Type Definitions

	var SCALAR_TYPE_DEFINITION = exports.SCALAR_TYPE_DEFINITION = 'ScalarTypeDefinition';
	var OBJECT_TYPE_DEFINITION = exports.OBJECT_TYPE_DEFINITION = 'ObjectTypeDefinition';
	var FIELD_DEFINITION = exports.FIELD_DEFINITION = 'FieldDefinition';
	var INPUT_VALUE_DEFINITION = exports.INPUT_VALUE_DEFINITION = 'InputValueDefinition';
	var INTERFACE_TYPE_DEFINITION = exports.INTERFACE_TYPE_DEFINITION = 'InterfaceTypeDefinition';
	var UNION_TYPE_DEFINITION = exports.UNION_TYPE_DEFINITION = 'UnionTypeDefinition';
	var ENUM_TYPE_DEFINITION = exports.ENUM_TYPE_DEFINITION = 'EnumTypeDefinition';
	var ENUM_VALUE_DEFINITION = exports.ENUM_VALUE_DEFINITION = 'EnumValueDefinition';
	var INPUT_OBJECT_TYPE_DEFINITION = exports.INPUT_OBJECT_TYPE_DEFINITION = 'InputObjectTypeDefinition';

	// Type Extensions

	var TYPE_EXTENSION_DEFINITION = exports.TYPE_EXTENSION_DEFINITION = 'TypeExtensionDefinition';

	// Directive Definitions

	var DIRECTIVE_DEFINITION = exports.DIRECTIVE_DEFINITION = 'DirectiveDefinition';

/***/ }
/******/ ]);

/***/ }),
/* 102 */
/***/ (function(module, exports) {

module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	module.exports = __webpack_require__(1);


/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.print = print;

	var _visitor = __webpack_require__(2);

	/**
	 * Converts an AST into a string, using one set of reasonable
	 * formatting rules.
	 */
	function print(ast) {
	  return (0, _visitor.visit)(ast, { leave: printDocASTReducer });
	} /**
	   *  Copyright (c) 2015, Facebook, Inc.
	   *  All rights reserved.
	   *
	   *  This source code is licensed under the BSD-style license found in the
	   *  LICENSE file in the root directory of this source tree. An additional grant
	   *  of patent rights can be found in the PATENTS file in the same directory.
	   */

	var printDocASTReducer = {
	  Name: function Name(node) {
	    return node.value;
	  },
	  Variable: function Variable(node) {
	    return '$' + node.name;
	  },

	  // Document

	  Document: function Document(node) {
	    return join(node.definitions, '\n\n') + '\n';
	  },

	  OperationDefinition: function OperationDefinition(node) {
	    var op = node.operation;
	    var name = node.name;
	    var varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
	    var directives = join(node.directives, ' ');
	    var selectionSet = node.selectionSet;
	    // Anonymous queries with no directives or variable definitions can use
	    // the query short form.
	    return !name && !directives && !varDefs && op === 'query' ? selectionSet : join([op, join([name, varDefs]), directives, selectionSet], ' ');
	  },


	  VariableDefinition: function VariableDefinition(_ref) {
	    var variable = _ref.variable,
	        type = _ref.type,
	        defaultValue = _ref.defaultValue;
	    return variable + ': ' + type + wrap(' = ', defaultValue);
	  },

	  SelectionSet: function SelectionSet(_ref2) {
	    var selections = _ref2.selections;
	    return block(selections);
	  },

	  Field: function Field(_ref3) {
	    var alias = _ref3.alias,
	        name = _ref3.name,
	        args = _ref3.arguments,
	        directives = _ref3.directives,
	        selectionSet = _ref3.selectionSet;
	    return join([wrap('', alias, ': ') + name + wrap('(', join(args, ', '), ')'), join(directives, ' '), selectionSet], ' ');
	  },

	  Argument: function Argument(_ref4) {
	    var name = _ref4.name,
	        value = _ref4.value;
	    return name + ': ' + value;
	  },

	  // Fragments

	  FragmentSpread: function FragmentSpread(_ref5) {
	    var name = _ref5.name,
	        directives = _ref5.directives;
	    return '...' + name + wrap(' ', join(directives, ' '));
	  },

	  InlineFragment: function InlineFragment(_ref6) {
	    var typeCondition = _ref6.typeCondition,
	        directives = _ref6.directives,
	        selectionSet = _ref6.selectionSet;
	    return join(['...', wrap('on ', typeCondition), join(directives, ' '), selectionSet], ' ');
	  },

	  FragmentDefinition: function FragmentDefinition(_ref7) {
	    var name = _ref7.name,
	        typeCondition = _ref7.typeCondition,
	        directives = _ref7.directives,
	        selectionSet = _ref7.selectionSet;
	    return 'fragment ' + name + ' on ' + typeCondition + ' ' + wrap('', join(directives, ' '), ' ') + selectionSet;
	  },

	  // Value

	  IntValue: function IntValue(_ref8) {
	    var value = _ref8.value;
	    return value;
	  },
	  FloatValue: function FloatValue(_ref9) {
	    var value = _ref9.value;
	    return value;
	  },
	  StringValue: function StringValue(_ref10) {
	    var value = _ref10.value;
	    return JSON.stringify(value);
	  },
	  BooleanValue: function BooleanValue(_ref11) {
	    var value = _ref11.value;
	    return JSON.stringify(value);
	  },
	  NullValue: function NullValue() {
	    return 'null';
	  },
	  EnumValue: function EnumValue(_ref12) {
	    var value = _ref12.value;
	    return value;
	  },
	  ListValue: function ListValue(_ref13) {
	    var values = _ref13.values;
	    return '[' + join(values, ', ') + ']';
	  },
	  ObjectValue: function ObjectValue(_ref14) {
	    var fields = _ref14.fields;
	    return '{' + join(fields, ', ') + '}';
	  },
	  ObjectField: function ObjectField(_ref15) {
	    var name = _ref15.name,
	        value = _ref15.value;
	    return name + ': ' + value;
	  },

	  // Directive

	  Directive: function Directive(_ref16) {
	    var name = _ref16.name,
	        args = _ref16.arguments;
	    return '@' + name + wrap('(', join(args, ', '), ')');
	  },

	  // Type

	  NamedType: function NamedType(_ref17) {
	    var name = _ref17.name;
	    return name;
	  },
	  ListType: function ListType(_ref18) {
	    var type = _ref18.type;
	    return '[' + type + ']';
	  },
	  NonNullType: function NonNullType(_ref19) {
	    var type = _ref19.type;
	    return type + '!';
	  },

	  // Type System Definitions

	  SchemaDefinition: function SchemaDefinition(_ref20) {
	    var directives = _ref20.directives,
	        operationTypes = _ref20.operationTypes;
	    return join(['schema', join(directives, ' '), block(operationTypes)], ' ');
	  },

	  OperationTypeDefinition: function OperationTypeDefinition(_ref21) {
	    var operation = _ref21.operation,
	        type = _ref21.type;
	    return operation + ': ' + type;
	  },

	  ScalarTypeDefinition: function ScalarTypeDefinition(_ref22) {
	    var name = _ref22.name,
	        directives = _ref22.directives;
	    return join(['scalar', name, join(directives, ' ')], ' ');
	  },

	  ObjectTypeDefinition: function ObjectTypeDefinition(_ref23) {
	    var name = _ref23.name,
	        interfaces = _ref23.interfaces,
	        directives = _ref23.directives,
	        fields = _ref23.fields;
	    return join(['type', name, wrap('implements ', join(interfaces, ', ')), join(directives, ' '), block(fields)], ' ');
	  },

	  FieldDefinition: function FieldDefinition(_ref24) {
	    var name = _ref24.name,
	        args = _ref24.arguments,
	        type = _ref24.type,
	        directives = _ref24.directives;
	    return name + wrap('(', join(args, ', '), ')') + ': ' + type + wrap(' ', join(directives, ' '));
	  },

	  InputValueDefinition: function InputValueDefinition(_ref25) {
	    var name = _ref25.name,
	        type = _ref25.type,
	        defaultValue = _ref25.defaultValue,
	        directives = _ref25.directives;
	    return join([name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')], ' ');
	  },

	  InterfaceTypeDefinition: function InterfaceTypeDefinition(_ref26) {
	    var name = _ref26.name,
	        directives = _ref26.directives,
	        fields = _ref26.fields;
	    return join(['interface', name, join(directives, ' '), block(fields)], ' ');
	  },

	  UnionTypeDefinition: function UnionTypeDefinition(_ref27) {
	    var name = _ref27.name,
	        directives = _ref27.directives,
	        types = _ref27.types;
	    return join(['union', name, join(directives, ' '), '= ' + join(types, ' | ')], ' ');
	  },

	  EnumTypeDefinition: function EnumTypeDefinition(_ref28) {
	    var name = _ref28.name,
	        directives = _ref28.directives,
	        values = _ref28.values;
	    return join(['enum', name, join(directives, ' '), block(values)], ' ');
	  },

	  EnumValueDefinition: function EnumValueDefinition(_ref29) {
	    var name = _ref29.name,
	        directives = _ref29.directives;
	    return join([name, join(directives, ' ')], ' ');
	  },

	  InputObjectTypeDefinition: function InputObjectTypeDefinition(_ref30) {
	    var name = _ref30.name,
	        directives = _ref30.directives,
	        fields = _ref30.fields;
	    return join(['input', name, join(directives, ' '), block(fields)], ' ');
	  },

	  TypeExtensionDefinition: function TypeExtensionDefinition(_ref31) {
	    var definition = _ref31.definition;
	    return 'extend ' + definition;
	  },

	  DirectiveDefinition: function DirectiveDefinition(_ref32) {
	    var name = _ref32.name,
	        args = _ref32.arguments,
	        locations = _ref32.locations;
	    return 'directive @' + name + wrap('(', join(args, ', '), ')') + ' on ' + join(locations, ' | ');
	  }
	};

	/**
	 * Given maybeArray, print an empty string if it is null or empty, otherwise
	 * print all items together separated by separator if provided
	 */
	function join(maybeArray, separator) {
	  return maybeArray ? maybeArray.filter(function (x) {
	    return x;
	  }).join(separator || '') : '';
	}

	/**
	 * Given array, print each item on its own line, wrapped in an
	 * indented "{ }" block.
	 */
	function block(array) {
	  return array && array.length !== 0 ? indent('{\n' + join(array, '\n')) + '\n}' : '{}';
	}

	/**
	 * If maybeString is not null or empty, then wrap with start and end, otherwise
	 * print an empty string.
	 */
	function wrap(start, maybeString, end) {
	  return maybeString ? start + maybeString + (end || '') : '';
	}

	function indent(maybeString) {
	  return maybeString && maybeString.replace(/\n/g, '\n  ');
	}

/***/ },
/* 2 */
/***/ function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.visit = visit;
	exports.visitInParallel = visitInParallel;
	exports.visitWithTypeInfo = visitWithTypeInfo;
	/**
	 *  Copyright (c) 2015, Facebook, Inc.
	 *  All rights reserved.
	 *
	 *  This source code is licensed under the BSD-style license found in the
	 *  LICENSE file in the root directory of this source tree. An additional grant
	 *  of patent rights can be found in the PATENTS file in the same directory.
	 */

	var QueryDocumentKeys = exports.QueryDocumentKeys = {
	  Name: [],

	  Document: ['definitions'],
	  OperationDefinition: ['name', 'variableDefinitions', 'directives', 'selectionSet'],
	  VariableDefinition: ['variable', 'type', 'defaultValue'],
	  Variable: ['name'],
	  SelectionSet: ['selections'],
	  Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
	  Argument: ['name', 'value'],

	  FragmentSpread: ['name', 'directives'],
	  InlineFragment: ['typeCondition', 'directives', 'selectionSet'],
	  FragmentDefinition: ['name', 'typeCondition', 'directives', 'selectionSet'],

	  IntValue: [],
	  FloatValue: [],
	  StringValue: [],
	  BooleanValue: [],
	  NullValue: [],
	  EnumValue: [],
	  ListValue: ['values'],
	  ObjectValue: ['fields'],
	  ObjectField: ['name', 'value'],

	  Directive: ['name', 'arguments'],

	  NamedType: ['name'],
	  ListType: ['type'],
	  NonNullType: ['type'],

	  SchemaDefinition: ['directives', 'operationTypes'],
	  OperationTypeDefinition: ['type'],

	  ScalarTypeDefinition: ['name', 'directives'],
	  ObjectTypeDefinition: ['name', 'interfaces', 'directives', 'fields'],
	  FieldDefinition: ['name', 'arguments', 'type', 'directives'],
	  InputValueDefinition: ['name', 'type', 'defaultValue', 'directives'],
	  InterfaceTypeDefinition: ['name', 'directives', 'fields'],
	  UnionTypeDefinition: ['name', 'directives', 'types'],
	  EnumTypeDefinition: ['name', 'directives', 'values'],
	  EnumValueDefinition: ['name', 'directives'],
	  InputObjectTypeDefinition: ['name', 'directives', 'fields'],

	  TypeExtensionDefinition: ['definition'],

	  DirectiveDefinition: ['name', 'arguments', 'locations']
	};

	var BREAK = exports.BREAK = {};

	/**
	 * visit() will walk through an AST using a depth first traversal, calling
	 * the visitor's enter function at each node in the traversal, and calling the
	 * leave function after visiting that node and all of its child nodes.
	 *
	 * By returning different values from the enter and leave functions, the
	 * behavior of the visitor can be altered, including skipping over a sub-tree of
	 * the AST (by returning false), editing the AST by returning a value or null
	 * to remove the value, or to stop the whole traversal by returning BREAK.
	 *
	 * When using visit() to edit an AST, the original AST will not be modified, and
	 * a new version of the AST with the changes applied will be returned from the
	 * visit function.
	 *
	 *     const editedAST = visit(ast, {
	 *       enter(node, key, parent, path, ancestors) {
	 *         // @return
	 *         //   undefined: no action
	 *         //   false: skip visiting this node
	 *         //   visitor.BREAK: stop visiting altogether
	 *         //   null: delete this node
	 *         //   any value: replace this node with the returned value
	 *       },
	 *       leave(node, key, parent, path, ancestors) {
	 *         // @return
	 *         //   undefined: no action
	 *         //   false: no action
	 *         //   visitor.BREAK: stop visiting altogether
	 *         //   null: delete this node
	 *         //   any value: replace this node with the returned value
	 *       }
	 *     });
	 *
	 * Alternatively to providing enter() and leave() functions, a visitor can
	 * instead provide functions named the same as the kinds of AST nodes, or
	 * enter/leave visitors at a named key, leading to four permutations of
	 * visitor API:
	 *
	 * 1) Named visitors triggered when entering a node a specific kind.
	 *
	 *     visit(ast, {
	 *       Kind(node) {
	 *         // enter the "Kind" node
	 *       }
	 *     })
	 *
	 * 2) Named visitors that trigger upon entering and leaving a node of
	 *    a specific kind.
	 *
	 *     visit(ast, {
	 *       Kind: {
	 *         enter(node) {
	 *           // enter the "Kind" node
	 *         }
	 *         leave(node) {
	 *           // leave the "Kind" node
	 *         }
	 *       }
	 *     })
	 *
	 * 3) Generic visitors that trigger upon entering and leaving any node.
	 *
	 *     visit(ast, {
	 *       enter(node) {
	 *         // enter any node
	 *       },
	 *       leave(node) {
	 *         // leave any node
	 *       }
	 *     })
	 *
	 * 4) Parallel visitors for entering and leaving nodes of a specific kind.
	 *
	 *     visit(ast, {
	 *       enter: {
	 *         Kind(node) {
	 *           // enter the "Kind" node
	 *         }
	 *       },
	 *       leave: {
	 *         Kind(node) {
	 *           // leave the "Kind" node
	 *         }
	 *       }
	 *     })
	 */
	function visit(root, visitor, keyMap) {
	  var visitorKeys = keyMap || QueryDocumentKeys;

	  var stack = void 0;
	  var inArray = Array.isArray(root);
	  var keys = [root];
	  var index = -1;
	  var edits = [];
	  var parent = void 0;
	  var path = [];
	  var ancestors = [];
	  var newRoot = root;

	  do {
	    index++;
	    var isLeaving = index === keys.length;
	    var key = void 0;
	    var node = void 0;
	    var isEdited = isLeaving && edits.length !== 0;
	    if (isLeaving) {
	      key = ancestors.length === 0 ? undefined : path.pop();
	      node = parent;
	      parent = ancestors.pop();
	      if (isEdited) {
	        if (inArray) {
	          node = node.slice();
	        } else {
	          var clone = {};
	          for (var k in node) {
	            if (node.hasOwnProperty(k)) {
	              clone[k] = node[k];
	            }
	          }
	          node = clone;
	        }
	        var editOffset = 0;
	        for (var ii = 0; ii < edits.length; ii++) {
	          var editKey = edits[ii][0];
	          var editValue = edits[ii][1];
	          if (inArray) {
	            editKey -= editOffset;
	          }
	          if (inArray && editValue === null) {
	            node.splice(editKey, 1);
	            editOffset++;
	          } else {
	            node[editKey] = editValue;
	          }
	        }
	      }
	      index = stack.index;
	      keys = stack.keys;
	      edits = stack.edits;
	      inArray = stack.inArray;
	      stack = stack.prev;
	    } else {
	      key = parent ? inArray ? index : keys[index] : undefined;
	      node = parent ? parent[key] : newRoot;
	      if (node === null || node === undefined) {
	        continue;
	      }
	      if (parent) {
	        path.push(key);
	      }
	    }

	    var result = void 0;
	    if (!Array.isArray(node)) {
	      if (!isNode(node)) {
	        throw new Error('Invalid AST Node: ' + JSON.stringify(node));
	      }
	      var visitFn = getVisitFn(visitor, node.kind, isLeaving);
	      if (visitFn) {
	        result = visitFn.call(visitor, node, key, parent, path, ancestors);

	        if (result === BREAK) {
	          break;
	        }

	        if (result === false) {
	          if (!isLeaving) {
	            path.pop();
	            continue;
	          }
	        } else if (result !== undefined) {
	          edits.push([key, result]);
	          if (!isLeaving) {
	            if (isNode(result)) {
	              node = result;
	            } else {
	              path.pop();
	              continue;
	            }
	          }
	        }
	      }
	    }

	    if (result === undefined && isEdited) {
	      edits.push([key, node]);
	    }

	    if (!isLeaving) {
	      stack = { inArray: inArray, index: index, keys: keys, edits: edits, prev: stack };
	      inArray = Array.isArray(node);
	      keys = inArray ? node : visitorKeys[node.kind] || [];
	      index = -1;
	      edits = [];
	      if (parent) {
	        ancestors.push(parent);
	      }
	      parent = node;
	    }
	  } while (stack !== undefined);

	  if (edits.length !== 0) {
	    newRoot = edits[edits.length - 1][1];
	  }

	  return newRoot;
	}

	function isNode(maybeNode) {
	  return maybeNode && typeof maybeNode.kind === 'string';
	}

	/**
	 * Creates a new visitor instance which delegates to many visitors to run in
	 * parallel. Each visitor will be visited for each node before moving on.
	 *
	 * If a prior visitor edits a node, no following visitors will see that node.
	 */
	function visitInParallel(visitors) {
	  var skipping = new Array(visitors.length);

	  return {
	    enter: function enter(node) {
	      for (var i = 0; i < visitors.length; i++) {
	        if (!skipping[i]) {
	          var fn = getVisitFn(visitors[i], node.kind, /* isLeaving */false);
	          if (fn) {
	            var result = fn.apply(visitors[i], arguments);
	            if (result === false) {
	              skipping[i] = node;
	            } else if (result === BREAK) {
	              skipping[i] = BREAK;
	            } else if (result !== undefined) {
	              return result;
	            }
	          }
	        }
	      }
	    },
	    leave: function leave(node) {
	      for (var i = 0; i < visitors.length; i++) {
	        if (!skipping[i]) {
	          var fn = getVisitFn(visitors[i], node.kind, /* isLeaving */true);
	          if (fn) {
	            var result = fn.apply(visitors[i], arguments);
	            if (result === BREAK) {
	              skipping[i] = BREAK;
	            } else if (result !== undefined && result !== false) {
	              return result;
	            }
	          }
	        } else if (skipping[i] === node) {
	          skipping[i] = null;
	        }
	      }
	    }
	  };
	}

	/**
	 * Creates a new visitor instance which maintains a provided TypeInfo instance
	 * along with visiting visitor.
	 */
	function visitWithTypeInfo(typeInfo, visitor) {
	  return {
	    enter: function enter(node) {
	      typeInfo.enter(node);
	      var fn = getVisitFn(visitor, node.kind, /* isLeaving */false);
	      if (fn) {
	        var result = fn.apply(visitor, arguments);
	        if (result !== undefined) {
	          typeInfo.leave(node);
	          if (isNode(result)) {
	            typeInfo.enter(result);
	          }
	        }
	        return result;
	      }
	    },
	    leave: function leave(node) {
	      var fn = getVisitFn(visitor, node.kind, /* isLeaving */true);
	      var result = void 0;
	      if (fn) {
	        result = fn.apply(visitor, arguments);
	      }
	      typeInfo.leave(node);
	      return result;
	    }
	  };
	}

	/**
	 * Given a visitor instance, if it is leaving or not, and a node kind, return
	 * the function the visitor runtime should call.
	 */
	function getVisitFn(visitor, kind, isLeaving) {
	  var kindVisitor = visitor[kind];
	  if (kindVisitor) {
	    if (!isLeaving && typeof kindVisitor === 'function') {
	      // { Kind() {} }
	      return kindVisitor;
	    }
	    var kindSpecificVisitor = isLeaving ? kindVisitor.leave : kindVisitor.enter;
	    if (typeof kindSpecificVisitor === 'function') {
	      // { Kind: { enter() {}, leave() {} } }
	      return kindSpecificVisitor;
	    }
	  } else {
	    var specificVisitor = isLeaving ? visitor.leave : visitor.enter;
	    if (specificVisitor) {
	      if (typeof specificVisitor === 'function') {
	        // { enter() {}, leave() {} }
	        return specificVisitor;
	      }
	      var specificKindVisitor = specificVisitor[kind];
	      if (typeof specificKindVisitor === 'function') {
	        // { enter: { Kind() {} }, leave: { Kind() {} } }
	        return specificKindVisitor;
	      }
	    }
	  }
	}

/***/ }
/******/ ]);

/***/ }),
/* 103 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Symbol_js__ = __webpack_require__(28);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__getRawTag_js__ = __webpack_require__(106);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__objectToString_js__ = __webpack_require__(107);




/** `Object#toString` result references. */
var nullTag = '[object Null]',
    undefinedTag = '[object Undefined]';

/** Built-in value references. */
var symToStringTag = __WEBPACK_IMPORTED_MODULE_0__Symbol_js__["a" /* default */] ? __WEBPACK_IMPORTED_MODULE_0__Symbol_js__["a" /* default */].toStringTag : undefined;

/**
 * The base implementation of `getTag` without fallbacks for buggy environments.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  if (value == null) {
    return value === undefined ? undefinedTag : nullTag;
  }
  return (symToStringTag && symToStringTag in Object(value))
    ? __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1__getRawTag_js__["a" /* default */])(value)
    : __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__objectToString_js__["a" /* default */])(value);
}

/* harmony default export */ __webpack_exports__["a"] = (baseGetTag);


/***/ }),
/* 104 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/* harmony default export */ __webpack_exports__["a"] = (freeGlobal);

/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(5)))

/***/ }),
/* 105 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__overArg_js__ = __webpack_require__(108);


/** Built-in value references. */
var getPrototype = __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__overArg_js__["a" /* default */])(Object.getPrototypeOf, Object);

/* harmony default export */ __webpack_exports__["a"] = (getPrototype);


/***/ }),
/* 106 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Symbol_js__ = __webpack_require__(28);


/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/** Built-in value references. */
var symToStringTag = __WEBPACK_IMPORTED_MODULE_0__Symbol_js__["a" /* default */] ? __WEBPACK_IMPORTED_MODULE_0__Symbol_js__["a" /* default */].toStringTag : undefined;

/**
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the raw `toStringTag`.
 */
function getRawTag(value) {
  var isOwn = hasOwnProperty.call(value, symToStringTag),
      tag = value[symToStringTag];

  try {
    value[symToStringTag] = undefined;
    var unmasked = true;
  } catch (e) {}

  var result = nativeObjectToString.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag;
    } else {
      delete value[symToStringTag];
    }
  }
  return result;
}

/* harmony default export */ __webpack_exports__["a"] = (getRawTag);


/***/ }),
/* 107 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/**
 * Converts `value` to a string using `Object.prototype.toString`.
 *
 * @private
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 */
function objectToString(value) {
  return nativeObjectToString.call(value);
}

/* harmony default export */ __webpack_exports__["a"] = (objectToString);


/***/ }),
/* 108 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/* harmony default export */ __webpack_exports__["a"] = (overArg);


/***/ }),
/* 109 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__freeGlobal_js__ = __webpack_require__(104);


/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = __WEBPACK_IMPORTED_MODULE_0__freeGlobal_js__["a" /* default */] || freeSelf || Function('return this')();

/* harmony default export */ __webpack_exports__["a"] = (root);


/***/ }),
/* 110 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return value != null && typeof value == 'object';
}

/* harmony default export */ __webpack_exports__["a"] = (isObjectLike);


/***/ }),
/* 111 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global, module) {/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used to compose bitmasks for comparison styles. */
var UNORDERED_COMPARE_FLAG = 1,
    PARTIAL_COMPARE_FLAG = 2;

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0,
    MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
    reIsPlainProp = /^\w*$/,
    reLeadingDot = /^\./,
    rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && freeGlobal.process;

/** Used to access faster Node.js helpers. */
var nodeUtil = (function() {
  try {
    return freeProcess && freeProcess.binding('util');
  } catch (e) {}
}());

/* Node.js helper references. */
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

/**
 * A specialized version of `baseAggregator` for arrays.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} setter The function to set `accumulator` values.
 * @param {Function} iteratee The iteratee to transform keys.
 * @param {Object} accumulator The initial aggregated object.
 * @returns {Function} Returns `accumulator`.
 */
function arrayAggregator(array, setter, iteratee, accumulator) {
  var index = -1,
      length = array ? array.length : 0;

  while (++index < length) {
    var value = array[index];
    setter(accumulator, value, iteratee(value), array);
  }
  return accumulator;
}

/**
 * A specialized version of `_.some` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array ? array.length : 0;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

/**
 * The base implementation of `_.property` without support for deep paths.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function baseProperty(key) {
  return function(object) {
    return object == null ? undefined : object[key];
  };
}

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * The base implementation of `_.unary` without support for storing metadata.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @returns {Function} Returns the new capped function.
 */
function baseUnary(func) {
  return function(value) {
    return func(value);
  };
}

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Checks if `value` is a host object in IE < 9.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
 */
function isHostObject(value) {
  // Many host objects are `Object` objects that can coerce to strings
  // despite having improperly defined `toString` methods.
  var result = false;
  if (value != null && typeof value.toString != 'function') {
    try {
      result = !!(value + '');
    } catch (e) {}
  }
  return result;
}

/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function(value, key) {
    result[++index] = [key, value];
  });
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/** Built-in value references. */
var Symbol = root.Symbol,
    Uint8Array = root.Uint8Array,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    splice = arrayProto.splice;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeKeys = overArg(Object.keys, Object);

/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView'),
    Map = getNative(root, 'Map'),
    Promise = getNative(root, 'Promise'),
    Set = getNative(root, 'Set'),
    WeakMap = getNative(root, 'WeakMap'),
    nativeCreate = getNative(Object, 'create');

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
    mapCtorString = toSource(Map),
    promiseCtorString = toSource(Promise),
    setCtorString = toSource(Set),
    weakMapCtorString = toSource(WeakMap);

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
    symbolToString = symbolProto ? symbolProto.toString : undefined;

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  return this.has(key) && delete this.__data__[key];
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.__data__ = {
    'hash': new Hash,
    'map': new (Map || ListCache),
    'string': new Hash
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  return getMapData(this, key)['delete'](key);
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  getMapData(this, key).set(key, value);
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
  var index = -1,
      length = values ? values.length : 0;

  this.__data__ = new MapCache;
  while (++index < length) {
    this.add(values[index]);
  }
}

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;

/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  this.__data__ = new ListCache(entries);
}

/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new ListCache;
}

/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  return this.__data__['delete'](key);
}

/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var cache = this.__data__;
  if (cache instanceof ListCache) {
    var pairs = cache.__data__;
    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
      pairs.push([key, value]);
      return this;
    }
    cache = this.__data__ = new MapCache(pairs);
  }
  cache.set(key, value);
  return this;
}

// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  // Safari 9 makes `arguments.length` enumerable in strict mode.
  var result = (isArray(value) || isArguments(value))
    ? baseTimes(value.length, String)
    : [];

  var length = result.length,
      skipIndexes = !!length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * Aggregates elements of `collection` on `accumulator` with keys transformed
 * by `iteratee` and values set by `setter`.
 *
 * @private
 * @param {Array|Object} collection The collection to iterate over.
 * @param {Function} setter The function to set `accumulator` values.
 * @param {Function} iteratee The iteratee to transform keys.
 * @param {Object} accumulator The initial aggregated object.
 * @returns {Function} Returns `accumulator`.
 */
function baseAggregator(collection, setter, iteratee, accumulator) {
  baseEach(collection, function(value, key, collection) {
    setter(accumulator, value, iteratee(value), collection);
  });
  return accumulator;
}

/**
 * The base implementation of `_.forEach` without support for iteratee shorthands.
 *
 * @private
 * @param {Array|Object} collection The collection to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array|Object} Returns `collection`.
 */
var baseEach = createBaseEach(baseForOwn);

/**
 * The base implementation of `baseForOwn` which iterates over `object`
 * properties returned by `keysFunc` and invokes `iteratee` for each property.
 * Iteratee functions may exit iteration early by explicitly returning `false`.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @returns {Object} Returns `object`.
 */
var baseFor = createBaseFor();

/**
 * The base implementation of `_.forOwn` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function baseForOwn(object, iteratee) {
  return object && baseFor(object, iteratee, keys);
}

/**
 * The base implementation of `_.get` without support for default values.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @returns {*} Returns the resolved value.
 */
function baseGet(object, path) {
  path = isKey(path, object) ? [path] : castPath(path);

  var index = 0,
      length = path.length;

  while (object != null && index < length) {
    object = object[toKey(path[index++])];
  }
  return (index && index == length) ? object : undefined;
}

/**
 * The base implementation of `getTag`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  return objectToString.call(value);
}

/**
 * The base implementation of `_.hasIn` without support for deep paths.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {Array|string} key The key to check.
 * @returns {boolean} Returns `true` if `key` exists, else `false`.
 */
function baseHasIn(object, key) {
  return object != null && key in Object(object);
}

/**
 * The base implementation of `_.isEqual` which supports partial comparisons
 * and tracks traversed objects.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {boolean} [bitmask] The bitmask of comparison flags.
 *  The bitmask may be composed of the following flags:
 *     1 - Unordered comparison
 *     2 - Partial comparison
 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, customizer, bitmask, stack) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
    return value !== value && other !== other;
  }
  return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
}

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
  var objIsArr = isArray(object),
      othIsArr = isArray(other),
      objTag = arrayTag,
      othTag = arrayTag;

  if (!objIsArr) {
    objTag = getTag(object);
    objTag = objTag == argsTag ? objectTag : objTag;
  }
  if (!othIsArr) {
    othTag = getTag(other);
    othTag = othTag == argsTag ? objectTag : othTag;
  }
  var objIsObj = objTag == objectTag && !isHostObject(object),
      othIsObj = othTag == objectTag && !isHostObject(other),
      isSameTag = objTag == othTag;

  if (isSameTag && !objIsObj) {
    stack || (stack = new Stack);
    return (objIsArr || isTypedArray(object))
      ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
      : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
  }
  if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      var objUnwrapped = objIsWrapped ? object.value() : object,
          othUnwrapped = othIsWrapped ? other.value() : other;

      stack || (stack = new Stack);
      return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
    }
  }
  if (!isSameTag) {
    return false;
  }
  stack || (stack = new Stack);
  return equalObjects(object, other, equalFunc, customizer, bitmask, stack);
}

/**
 * The base implementation of `_.isMatch` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to inspect.
 * @param {Object} source The object of property values to match.
 * @param {Array} matchData The property names, values, and compare flags to match.
 * @param {Function} [customizer] The function to customize comparisons.
 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
 */
function baseIsMatch(object, source, matchData, customizer) {
  var index = matchData.length,
      length = index,
      noCustomizer = !customizer;

  if (object == null) {
    return !length;
  }
  object = Object(object);
  while (index--) {
    var data = matchData[index];
    if ((noCustomizer && data[2])
          ? data[1] !== object[data[0]]
          : !(data[0] in object)
        ) {
      return false;
    }
  }
  while (++index < length) {
    data = matchData[index];
    var key = data[0],
        objValue = object[key],
        srcValue = data[1];

    if (noCustomizer && data[2]) {
      if (objValue === undefined && !(key in object)) {
        return false;
      }
    } else {
      var stack = new Stack;
      if (customizer) {
        var result = customizer(objValue, srcValue, key, object, source, stack);
      }
      if (!(result === undefined
            ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
            : result
          )) {
        return false;
      }
    }
  }
  return true;
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 */
function baseIsTypedArray(value) {
  return isObjectLike(value) &&
    isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
}

/**
 * The base implementation of `_.iteratee`.
 *
 * @private
 * @param {*} [value=_.identity] The value to convert to an iteratee.
 * @returns {Function} Returns the iteratee.
 */
function baseIteratee(value) {
  // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
  // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
  if (typeof value == 'function') {
    return value;
  }
  if (value == null) {
    return identity;
  }
  if (typeof value == 'object') {
    return isArray(value)
      ? baseMatchesProperty(value[0], value[1])
      : baseMatches(value);
  }
  return property(value);
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * The base implementation of `_.matches` which doesn't clone `source`.
 *
 * @private
 * @param {Object} source The object of property values to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatches(source) {
  var matchData = getMatchData(source);
  if (matchData.length == 1 && matchData[0][2]) {
    return matchesStrictComparable(matchData[0][0], matchData[0][1]);
  }
  return function(object) {
    return object === source || baseIsMatch(object, source, matchData);
  };
}

/**
 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
 *
 * @private
 * @param {string} path The path of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatchesProperty(path, srcValue) {
  if (isKey(path) && isStrictComparable(srcValue)) {
    return matchesStrictComparable(toKey(path), srcValue);
  }
  return function(object) {
    var objValue = get(object, path);
    return (objValue === undefined && objValue === srcValue)
      ? hasIn(object, path)
      : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
  };
}

/**
 * A specialized version of `baseProperty` which supports deep paths.
 *
 * @private
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function basePropertyDeep(path) {
  return function(object) {
    return baseGet(object, path);
  };
}

/**
 * The base implementation of `_.toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value;
  }
  if (isSymbol(value)) {
    return symbolToString ? symbolToString.call(value) : '';
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/**
 * Casts `value` to a path array if it's not one.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {Array} Returns the cast property path array.
 */
function castPath(value) {
  return isArray(value) ? value : stringToPath(value);
}

/**
 * Creates a function like `_.groupBy`.
 *
 * @private
 * @param {Function} setter The function to set accumulator values.
 * @param {Function} [initializer] The accumulator object initializer.
 * @returns {Function} Returns the new aggregator function.
 */
function createAggregator(setter, initializer) {
  return function(collection, iteratee) {
    var func = isArray(collection) ? arrayAggregator : baseAggregator,
        accumulator = initializer ? initializer() : {};

    return func(collection, setter, baseIteratee(iteratee, 2), accumulator);
  };
}

/**
 * Creates a `baseEach` or `baseEachRight` function.
 *
 * @private
 * @param {Function} eachFunc The function to iterate over a collection.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseEach(eachFunc, fromRight) {
  return function(collection, iteratee) {
    if (collection == null) {
      return collection;
    }
    if (!isArrayLike(collection)) {
      return eachFunc(collection, iteratee);
    }
    var length = collection.length,
        index = fromRight ? length : -1,
        iterable = Object(collection);

    while ((fromRight ? index-- : ++index < length)) {
      if (iteratee(iterable[index], index, iterable) === false) {
        break;
      }
    }
    return collection;
  };
}

/**
 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
 *
 * @private
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseFor(fromRight) {
  return function(object, iteratee, keysFunc) {
    var index = -1,
        iterable = Object(object),
        props = keysFunc(object),
        length = props.length;

    while (length--) {
      var key = props[fromRight ? length : ++index];
      if (iteratee(iterable[key], key, iterable) === false) {
        break;
      }
    }
    return object;
  };
}

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} customizer The function to customize comparisons.
 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} stack Tracks traversed `array` and `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
  var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
    return false;
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(array);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var index = -1,
      result = true,
      seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined;

  stack.set(array, other);
  stack.set(other, array);

  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, arrValue, index, other, array, stack)
        : customizer(arrValue, othValue, index, array, other, stack);
    }
    if (compared !== undefined) {
      if (compared) {
        continue;
      }
      result = false;
      break;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (seen) {
      if (!arraySome(other, function(othValue, othIndex) {
            if (!seen.has(othIndex) &&
                (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
              return seen.add(othIndex);
            }
          })) {
        result = false;
        break;
      }
    } else if (!(
          arrValue === othValue ||
            equalFunc(arrValue, othValue, customizer, bitmask, stack)
        )) {
      result = false;
      break;
    }
  }
  stack['delete'](array);
  stack['delete'](other);
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} customizer The function to customize comparisons.
 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {
  switch (tag) {
    case dataViewTag:
      if ((object.byteLength != other.byteLength) ||
          (object.byteOffset != other.byteOffset)) {
        return false;
      }
      object = object.buffer;
      other = other.buffer;

    case arrayBufferTag:
      if ((object.byteLength != other.byteLength) ||
          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
        return false;
      }
      return true;

    case boolTag:
    case dateTag:
    case numberTag:
      // Coerce booleans to `1` or `0` and dates to milliseconds.
      // Invalid dates are coerced to `NaN`.
      return eq(+object, +other);

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings, primitives and objects,
      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
      // for more details.
      return object == (other + '');

    case mapTag:
      var convert = mapToArray;

    case setTag:
      var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
      convert || (convert = setToArray);

      if (object.size != other.size && !isPartial) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked) {
        return stacked == other;
      }
      bitmask |= UNORDERED_COMPARE_FLAG;

      // Recursively compare objects (susceptible to call stack limits).
      stack.set(object, other);
      var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);
      stack['delete'](object);
      return result;

    case symbolTag:
      if (symbolValueOf) {
        return symbolValueOf.call(object) == symbolValueOf.call(other);
      }
  }
  return false;
}

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Function} customizer The function to customize comparisons.
 * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 *  for more details.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
  var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
      objProps = keys(object),
      objLength = objProps.length,
      othProps = keys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isPartial) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(object);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var result = true;
  stack.set(object, other);
  stack.set(other, object);

  var skipCtor = isPartial;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, objValue, key, other, object, stack)
        : customizer(objValue, othValue, key, object, other, stack);
    }
    // Recursively compare objects (susceptible to call stack limits).
    if (!(compared === undefined
          ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
          : compared
        )) {
      result = false;
      break;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (result && !skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor &&
        ('constructor' in object && 'constructor' in other) &&
        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      result = false;
    }
  }
  stack['delete'](object);
  stack['delete'](other);
  return result;
}

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/**
 * Gets the property names, values, and compare flags of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the match data of `object`.
 */
function getMatchData(object) {
  var result = keys(object),
      length = result.length;

  while (length--) {
    var key = result[length],
        value = object[key];

    result[length] = [key, value, isStrictComparable(value)];
  }
  return result;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = baseGetTag;

// Fallback for data views, maps, sets, and weak maps in IE 11,
// for data views in Edge < 14, and promises in Node.js.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
    (Map && getTag(new Map) != mapTag) ||
    (Promise && getTag(Promise.resolve()) != promiseTag) ||
    (Set && getTag(new Set) != setTag) ||
    (WeakMap && getTag(new WeakMap) != weakMapTag)) {
  getTag = function(value) {
    var result = objectToString.call(value),
        Ctor = result == objectTag ? value.constructor : undefined,
        ctorString = Ctor ? toSource(Ctor) : undefined;

    if (ctorString) {
      switch (ctorString) {
        case dataViewCtorString: return dataViewTag;
        case mapCtorString: return mapTag;
        case promiseCtorString: return promiseTag;
        case setCtorString: return setTag;
        case weakMapCtorString: return weakMapTag;
      }
    }
    return result;
  };
}

/**
 * Checks if `path` exists on `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @param {Function} hasFunc The function to check properties.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 */
function hasPath(object, path, hasFunc) {
  path = isKey(path, object) ? [path] : castPath(path);

  var result,
      index = -1,
      length = path.length;

  while (++index < length) {
    var key = toKey(path[index]);
    if (!(result = object != null && hasFunc(object, key))) {
      break;
    }
    object = object[key];
  }
  if (result) {
    return result;
  }
  var length = object ? object.length : 0;
  return !!length && isLength(length) && isIndex(key, length) &&
    (isArray(object) || isArguments(object));
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if `value` is a property name and not a property path.
 *
 * @private
 * @param {*} value The value to check.
 * @param {Object} [object] The object to query keys on.
 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 */
function isKey(value, object) {
  if (isArray(value)) {
    return false;
  }
  var type = typeof value;
  if (type == 'number' || type == 'symbol' || type == 'boolean' ||
      value == null || isSymbol(value)) {
    return true;
  }
  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
    (object != null && value in Object(object));
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` if suitable for strict
 *  equality comparisons, else `false`.
 */
function isStrictComparable(value) {
  return value === value && !isObject(value);
}

/**
 * A specialized version of `matchesProperty` for source values suitable
 * for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function matchesStrictComparable(key, srcValue) {
  return function(object) {
    if (object == null) {
      return false;
    }
    return object[key] === srcValue &&
      (srcValue !== undefined || (key in Object(object)));
  };
}

/**
 * Converts `string` to a property path array.
 *
 * @private
 * @param {string} string The string to convert.
 * @returns {Array} Returns the property path array.
 */
var stringToPath = memoize(function(string) {
  string = toString(string);

  var result = [];
  if (reLeadingDot.test(string)) {
    result.push('');
  }
  string.replace(rePropName, function(match, number, quote, string) {
    result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
  });
  return result;
});

/**
 * Converts `value` to a string key if it's not a string or symbol.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {string|symbol} Returns the key.
 */
function toKey(value) {
  if (typeof value == 'string' || isSymbol(value)) {
    return value;
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to process.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/**
 * Creates an object composed of keys generated from the results of running
 * each element of `collection` thru `iteratee`. The corresponding value of
 * each key is the number of times the key was returned by `iteratee`. The
 * iteratee is invoked with one argument: (value).
 *
 * @static
 * @memberOf _
 * @since 0.5.0
 * @category Collection
 * @param {Array|Object} collection The collection to iterate over.
 * @param {Function} [iteratee=_.identity]
 *  The iteratee to transform keys.
 * @returns {Object} Returns the composed aggregate object.
 * @example
 *
 * _.countBy([6.1, 4.2, 6.3], Math.floor);
 * // => { '4': 1, '6': 2 }
 *
 * // The `_.property` iteratee shorthand.
 * _.countBy(['one', 'two', 'three'], 'length');
 * // => { '3': 2, '5': 1 }
 */
var countBy = createAggregator(function(result, value, key) {
  hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
});

/**
 * Creates a function that memoizes the result of `func`. If `resolver` is
 * provided, it determines the cache key for storing the result based on the
 * arguments provided to the memoized function. By default, the first argument
 * provided to the memoized function is used as the map cache key. The `func`
 * is invoked with the `this` binding of the memoized function.
 *
 * **Note:** The cache is exposed as the `cache` property on the memoized
 * function. Its creation may be customized by replacing the `_.memoize.Cache`
 * constructor with one whose instances implement the
 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
 * method interface of `delete`, `get`, `has`, and `set`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to have its output memoized.
 * @param {Function} [resolver] The function to resolve the cache key.
 * @returns {Function} Returns the new memoized function.
 * @example
 *
 * var object = { 'a': 1, 'b': 2 };
 * var other = { 'c': 3, 'd': 4 };
 *
 * var values = _.memoize(_.values);
 * values(object);
 * // => [1, 2]
 *
 * values(other);
 * // => [3, 4]
 *
 * object.a = 2;
 * values(object);
 * // => [1, 2]
 *
 * // Modify the result cache.
 * values.cache.set(object, ['a', 'b']);
 * values(object);
 * // => ['a', 'b']
 *
 * // Replace `_.memoize.Cache`.
 * _.memoize.Cache = WeakMap;
 */
function memoize(func, resolver) {
  if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  var memoized = function() {
    var args = arguments,
        key = resolver ? resolver.apply(this, args) : args[0],
        cache = memoized.cache;

    if (cache.has(key)) {
      return cache.get(key);
    }
    var result = func.apply(this, args);
    memoized.cache = cache.set(key, result);
    return result;
  };
  memoized.cache = new (memoize.Cache || MapCache);
  return memoized;
}

// Assign cache to `_.memoize`.
memoize.Cache = MapCache;

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return typeof value == 'symbol' ||
    (isObjectLike(value) && objectToString.call(value) == symbolTag);
}

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 * @example
 *
 * _.toString(null);
 * // => ''
 *
 * _.toString(-0);
 * // => '-0'
 *
 * _.toString([1, 2, 3]);
 * // => '1,2,3'
 */
function toString(value) {
  return value == null ? '' : baseToString(value);
}

/**
 * Gets the value at `path` of `object`. If the resolved value is
 * `undefined`, the `defaultValue` is returned in its place.
 *
 * @static
 * @memberOf _
 * @since 3.7.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
 * @returns {*} Returns the resolved value.
 * @example
 *
 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
 *
 * _.get(object, 'a[0].b.c');
 * // => 3
 *
 * _.get(object, ['a', '0', 'b', 'c']);
 * // => 3
 *
 * _.get(object, 'a.b.c', 'default');
 * // => 'default'
 */
function get(object, path, defaultValue) {
  var result = object == null ? undefined : baseGet(object, path);
  return result === undefined ? defaultValue : result;
}

/**
 * Checks if `path` is a direct or inherited property of `object`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 * @example
 *
 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
 *
 * _.hasIn(object, 'a');
 * // => true
 *
 * _.hasIn(object, 'a.b');
 * // => true
 *
 * _.hasIn(object, ['a', 'b']);
 * // => true
 *
 * _.hasIn(object, 'b');
 * // => false
 */
function hasIn(object, path) {
  return object != null && hasPath(object, path, baseHasIn);
}

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

/**
 * This method returns the first argument it receives.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Util
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'a': 1 };
 *
 * console.log(_.identity(object) === object);
 * // => true
 */
function identity(value) {
  return value;
}

/**
 * Creates a function that returns the value at `path` of a given object.
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Util
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 * @example
 *
 * var objects = [
 *   { 'a': { 'b': 2 } },
 *   { 'a': { 'b': 1 } }
 * ];
 *
 * _.map(objects, _.property('a.b'));
 * // => [2, 1]
 *
 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
 * // => [1, 2]
 */
function property(path) {
  return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}

module.exports = countBy;

/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5), __webpack_require__(12)(module)))

/***/ }),
/* 112 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]';

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Built-in value references. */
var Symbol = root.Symbol,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;

/**
 * The base implementation of `_.flatten` with support for restricting flattening.
 *
 * @private
 * @param {Array} array The array to flatten.
 * @param {number} depth The maximum recursion depth.
 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
 * @param {Array} [result=[]] The initial result value.
 * @returns {Array} Returns the new flattened array.
 */
function baseFlatten(array, depth, predicate, isStrict, result) {
  var index = -1,
      length = array.length;

  predicate || (predicate = isFlattenable);
  result || (result = []);

  while (++index < length) {
    var value = array[index];
    if (depth > 0 && predicate(value)) {
      if (depth > 1) {
        // Recursively flatten arrays (susceptible to call stack limits).
        baseFlatten(value, depth - 1, predicate, isStrict, result);
      } else {
        arrayPush(result, value);
      }
    } else if (!isStrict) {
      result[result.length] = value;
    }
  }
  return result;
}

/**
 * Checks if `value` is a flattenable `arguments` object or array.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
 */
function isFlattenable(value) {
  return isArray(value) || isArguments(value) ||
    !!(spreadableSymbol && value && value[spreadableSymbol]);
}

/**
 * Flattens `array` a single level deep.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Array
 * @param {Array} array The array to flatten.
 * @returns {Array} Returns the new flattened array.
 * @example
 *
 * _.flatten([1, [2, [3, [4]], 5]]);
 * // => [1, 2, [3, [4]], 5]
 */
function flatten(array) {
  var length = array ? array.length : 0;
  return length ? baseFlatten(array, 1) : [];
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

module.exports = flatten;

/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5)))

/***/ }),
/* 113 */
/***/ (function(module, exports) {

/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]';

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Built-in value references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeKeys = overArg(Object.keys, Object);

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  // Safari 9 makes `arguments.length` enumerable in strict mode.
  var result = (isArray(value) || isArguments(value))
    ? baseTimes(value.length, String)
    : [];

  var length = result.length,
      skipIndexes = !!length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * The base implementation of `baseForOwn` which iterates over `object`
 * properties returned by `keysFunc` and invokes `iteratee` for each property.
 * Iteratee functions may exit iteration early by explicitly returning `false`.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @returns {Object} Returns `object`.
 */
var baseFor = createBaseFor();

/**
 * The base implementation of `_.forOwn` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function baseForOwn(object, iteratee) {
  return object && baseFor(object, iteratee, keys);
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
 *
 * @private
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseFor(fromRight) {
  return function(object, iteratee, keysFunc) {
    var index = -1,
        iterable = Object(object),
        props = keysFunc(object),
        length = props.length;

    while (length--) {
      var key = props[fromRight ? length : ++index];
      if (iteratee(iterable[key], key, iterable) === false) {
        break;
      }
    }
    return object;
  };
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Iterates over own enumerable string keyed properties of an object and
 * invokes `iteratee` for each property. The iteratee is invoked with three
 * arguments: (value, key, object). Iteratee functions may exit iteration
 * early by explicitly returning `false`.
 *
 * @static
 * @memberOf _
 * @since 0.3.0
 * @category Object
 * @param {Object} object The object to iterate over.
 * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 * @returns {Object} Returns `object`.
 * @see _.forOwnRight
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.forOwn(new Foo, function(value, key) {
 *   console.log(key);
 * });
 * // => Logs 'a' then 'b' (iteration order is not guaranteed).
 */
function forOwn(object, iteratee) {
  return object && baseForOwn(object, typeof iteratee == 'function' ? iteratee : identity);
}

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

/**
 * This method returns the first argument it receives.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Util
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'a': 1 };
 *
 * console.log(_.identity(object) === object);
 * // => true
 */
function identity(value) {
  return value;
}

module.exports = forOwn;


/***/ }),
/* 114 */
/***/ (function(module, exports) {

/**
 * lodash 3.0.0 (Custom Build) <https://lodash.com/>
 * Build: `lodash modern modularize exports="npm" -o ./`
 * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
 * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>
 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 * Available under MIT license <https://lodash.com/license>
 */

/**
 * This method returns the first argument provided to it.
 *
 * @static
 * @memberOf _
 * @category Utility
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'user': 'fred' };
 * _.identity(object) === object;
 * // => true
 */
function identity(value) {
  return value;
}

module.exports = identity;


/***/ }),
/* 115 */
/***/ (function(module, exports) {

/**
 * lodash 3.0.0 (Custom Build) <https://lodash.com/>
 * Build: `lodash modern modularize exports="npm" -o ./`
 * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
 * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>
 * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 * Available under MIT license <https://lodash.com/license>
 */

/**
 * Checks if `value` is `null`.
 *
 * @static
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
 * @example
 *
 * _.isNull(null);
 * // => true
 *
 * _.isNull(void 0);
 * // => false
 */
function isNull(value) {
  return value === null;
}

module.exports = isNull;


/***/ }),
/* 116 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0,
    MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    symbolTag = '[object Symbol]';

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/**
 * A faster alternative to `Function#apply`, this function invokes `func`
 * with the `this` binding of `thisArg` and the arguments of `args`.
 *
 * @private
 * @param {Function} func The function to invoke.
 * @param {*} thisArg The `this` binding of `func`.
 * @param {Array} args The arguments to invoke `func` with.
 * @returns {*} Returns the result of `func`.
 */
function apply(func, thisArg, args) {
  switch (args.length) {
    case 0: return func.call(thisArg);
    case 1: return func.call(thisArg, args[0]);
    case 2: return func.call(thisArg, args[0], args[1]);
    case 3: return func.call(thisArg, args[0], args[1], args[2]);
  }
  return func.apply(thisArg, args);
}

/**
 * A specialized version of `_.map` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the new mapped array.
 */
function arrayMap(array, iteratee) {
  var index = -1,
      length = array ? array.length : 0,
      result = Array(length);

  while (++index < length) {
    result[index] = iteratee(array[index], index, array);
  }
  return result;
}

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Built-in value references. */
var Symbol = root.Symbol,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * The base implementation of `_.flatten` with support for restricting flattening.
 *
 * @private
 * @param {Array} array The array to flatten.
 * @param {number} depth The maximum recursion depth.
 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
 * @param {Array} [result=[]] The initial result value.
 * @returns {Array} Returns the new flattened array.
 */
function baseFlatten(array, depth, predicate, isStrict, result) {
  var index = -1,
      length = array.length;

  predicate || (predicate = isFlattenable);
  result || (result = []);

  while (++index < length) {
    var value = array[index];
    if (depth > 0 && predicate(value)) {
      if (depth > 1) {
        // Recursively flatten arrays (susceptible to call stack limits).
        baseFlatten(value, depth - 1, predicate, isStrict, result);
      } else {
        arrayPush(result, value);
      }
    } else if (!isStrict) {
      result[result.length] = value;
    }
  }
  return result;
}

/**
 * The base implementation of `_.pick` without support for individual
 * property identifiers.
 *
 * @private
 * @param {Object} object The source object.
 * @param {string[]} props The property identifiers to pick.
 * @returns {Object} Returns the new object.
 */
function basePick(object, props) {
  object = Object(object);
  return basePickBy(object, props, function(value, key) {
    return key in object;
  });
}

/**
 * The base implementation of  `_.pickBy` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The source object.
 * @param {string[]} props The property identifiers to pick from.
 * @param {Function} predicate The function invoked per property.
 * @returns {Object} Returns the new object.
 */
function basePickBy(object, props, predicate) {
  var index = -1,
      length = props.length,
      result = {};

  while (++index < length) {
    var key = props[index],
        value = object[key];

    if (predicate(value, key)) {
      result[key] = value;
    }
  }
  return result;
}

/**
 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @returns {Function} Returns the new function.
 */
function baseRest(func, start) {
  start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
  return function() {
    var args = arguments,
        index = -1,
        length = nativeMax(args.length - start, 0),
        array = Array(length);

    while (++index < length) {
      array[index] = args[start + index];
    }
    index = -1;
    var otherArgs = Array(start + 1);
    while (++index < start) {
      otherArgs[index] = args[index];
    }
    otherArgs[start] = array;
    return apply(func, this, otherArgs);
  };
}

/**
 * Checks if `value` is a flattenable `arguments` object or array.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
 */
function isFlattenable(value) {
  return isArray(value) || isArguments(value) ||
    !!(spreadableSymbol && value && value[spreadableSymbol]);
}

/**
 * Converts `value` to a string key if it's not a string or symbol.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {string|symbol} Returns the key.
 */
function toKey(value) {
  if (typeof value == 'string' || isSymbol(value)) {
    return value;
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
function isArguments(value) {
  // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
  return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
    (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
}

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return isObjectLike(value) && isArrayLike(value);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return typeof value == 'symbol' ||
    (isObjectLike(value) && objectToString.call(value) == symbolTag);
}

/**
 * Creates an object composed of the picked `object` properties.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The source object.
 * @param {...(string|string[])} [props] The property identifiers to pick.
 * @returns {Object} Returns the new object.
 * @example
 *
 * var object = { 'a': 1, 'b': '2', 'c': 3 };
 *
 * _.pick(object, ['a', 'c']);
 * // => { 'a': 1, 'c': 3 }
 */
var pick = baseRest(function(object, props) {
  return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey));
});

module.exports = pick;

/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5)))

/***/ }),
/* 117 */
/***/ (function(module, exports, __webpack_require__) {

/* WEBPACK VAR INJECTION */(function(global) {/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/** `Object#toString` result references. */
var funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]';

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/**
 * A specialized version of `_.includes` for arrays without support for
 * specifying an index to search from.
 *
 * @private
 * @param {Array} [array] The array to inspect.
 * @param {*} target The value to search for.
 * @returns {boolean} Returns `true` if `target` is found, else `false`.
 */
function arrayIncludes(array, value) {
  var length = array ? array.length : 0;
  return !!length && baseIndexOf(array, value, 0) > -1;
}

/**
 * This function is like `arrayIncludes` except that it accepts a comparator.
 *
 * @private
 * @param {Array} [array] The array to inspect.
 * @param {*} target The value to search for.
 * @param {Function} comparator The comparator invoked per element.
 * @returns {boolean} Returns `true` if `target` is found, else `false`.
 */
function arrayIncludesWith(array, value, comparator) {
  var index = -1,
      length = array ? array.length : 0;

  while (++index < length) {
    if (comparator(value, array[index])) {
      return true;
    }
  }
  return false;
}

/**
 * The base implementation of `_.findIndex` and `_.findLastIndex` without
 * support for iteratee shorthands.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {Function} predicate The function invoked per iteration.
 * @param {number} fromIndex The index to search from.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function baseFindIndex(array, predicate, fromIndex, fromRight) {
  var length = array.length,
      index = fromIndex + (fromRight ? 1 : -1);

  while ((fromRight ? index-- : ++index < length)) {
    if (predicate(array[index], index, array)) {
      return index;
    }
  }
  return -1;
}

/**
 * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} value The value to search for.
 * @param {number} fromIndex The index to search from.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function baseIndexOf(array, value, fromIndex) {
  if (value !== value) {
    return baseFindIndex(array, baseIsNaN, fromIndex);
  }
  var index = fromIndex - 1,
      length = array.length;

  while (++index < length) {
    if (array[index] === value) {
      return index;
    }
  }
  return -1;
}

/**
 * The base implementation of `_.isNaN` without support for number objects.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
 */
function baseIsNaN(value) {
  return value !== value;
}

/**
 * Checks if a cache value for `key` exists.
 *
 * @private
 * @param {Object} cache The cache to query.
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function cacheHas(cache, key) {
  return cache.has(key);
}

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Checks if `value` is a host object in IE < 9.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
 */
function isHostObject(value) {
  // Many host objects are `Object` objects that can coerce to strings
  // despite having improperly defined `toString` methods.
  var result = false;
  if (value != null && typeof value.toString != 'function') {
    try {
      result = !!(value + '');
    } catch (e) {}
  }
  return result;
}

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/** Built-in value references. */
var splice = arrayProto.splice;

/* Built-in method references that are verified to be native. */
var Map = getNative(root, 'Map'),
    Set = getNative(root, 'Set'),
    nativeCreate = getNative(Object, 'create');

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  return this.has(key) && delete this.__data__[key];
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries ? entries.length : 0;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.__data__ = {
    'hash': new Hash,
    'map': new (Map || ListCache),
    'string': new Hash
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  return getMapData(this, key)['delete'](key);
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  getMapData(this, key).set(key, value);
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
  var index = -1,
      length = values ? values.length : 0;

  this.__data__ = new MapCache;
  while (++index < length) {
    this.add(values[index]);
  }
}

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.uniqBy` without support for iteratee shorthands.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {Function} [iteratee] The iteratee invoked per element.
 * @param {Function} [comparator] The comparator invoked per element.
 * @returns {Array} Returns the new duplicate free array.
 */
function baseUniq(array, iteratee, comparator) {
  var index = -1,
      includes = arrayIncludes,
      length = array.length,
      isCommon = true,
      result = [],
      seen = result;

  if (comparator) {
    isCommon = false;
    includes = arrayIncludesWith;
  }
  else if (length >= LARGE_ARRAY_SIZE) {
    var set = iteratee ? null : createSet(array);
    if (set) {
      return setToArray(set);
    }
    isCommon = false;
    includes = cacheHas;
    seen = new SetCache;
  }
  else {
    seen = iteratee ? [] : result;
  }
  outer:
  while (++index < length) {
    var value = array[index],
        computed = iteratee ? iteratee(value) : value;

    value = (comparator || value !== 0) ? value : 0;
    if (isCommon && computed === computed) {
      var seenIndex = seen.length;
      while (seenIndex--) {
        if (seen[seenIndex] === computed) {
          continue outer;
        }
      }
      if (iteratee) {
        seen.push(computed);
      }
      result.push(value);
    }
    else if (!includes(seen, computed, comparator)) {
      if (seen !== result) {
        seen.push(computed);
      }
      result.push(value);
    }
  }
  return result;
}

/**
 * Creates a set object of `values`.
 *
 * @private
 * @param {Array} values The values to add to the set.
 * @returns {Object} Returns the new set.
 */
var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
  return new Set(values);
};

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to process.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/**
 * Creates a duplicate-free version of an array, using
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * for equality comparisons, in which only the first occurrence of each
 * element is kept.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Array
 * @param {Array} array The array to inspect.
 * @returns {Array} Returns the new duplicate free array.
 * @example
 *
 * _.uniq([2, 1, 2]);
 * // => [2, 1]
 */
function uniq(array) {
  return (array && array.length)
    ? baseUniq(array)
    : [];
}

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 8-9 which returns 'object' for typed array and other constructors.
  var tag = isObject(value) ? objectToString.call(value) : '';
  return tag == funcTag || tag == genTag;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return !!value && (type == 'object' || type == 'function');
}

/**
 * This method returns `undefined`.
 *
 * @static
 * @memberOf _
 * @since 2.3.0
 * @category Util
 * @example
 *
 * _.times(2, _.noop);
 * // => [undefined, undefined]
 */
function noop() {
  // No operation performed.
}

module.exports = uniq;

/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5)))

/***/ }),
/* 118 */
/***/ (function(module, exports) {

/**
 * Checks if `value` is `undefined`.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
 * @example
 *
 * _.isUndefined(void 0);
 * // => true
 *
 * _.isUndefined(null);
 * // => false
 */
function isUndefined(value) {
  return value === undefined;
}

module.exports = isUndefined;


/***/ }),
/* 119 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = applyMiddleware;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__compose__ = __webpack_require__(36);
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };



/**
 * Creates a store enhancer that applies middleware to the dispatch method
 * of the Redux store. This is handy for a variety of tasks, such as expressing
 * asynchronous actions in a concise manner, or logging every action payload.
 *
 * See `redux-thunk` package as an example of the Redux middleware.
 *
 * Because middleware is potentially asynchronous, this should be the first
 * store enhancer in the composition chain.
 *
 * Note that each middleware will be given the `dispatch` and `getState` functions
 * as named arguments.
 *
 * @param {...Function} middlewares The middleware chain to be applied.
 * @returns {Function} A store enhancer applying the middleware.
 */
function applyMiddleware() {
  for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
    middlewares[_key] = arguments[_key];
  }

  return function (createStore) {
    return function (reducer, preloadedState, enhancer) {
      var store = createStore(reducer, preloadedState, enhancer);
      var _dispatch = store.dispatch;
      var chain = [];

      var middlewareAPI = {
        getState: store.getState,
        dispatch: function dispatch(action) {
          return _dispatch(action);
        }
      };
      chain = middlewares.map(function (middleware) {
        return middleware(middlewareAPI);
      });
      _dispatch = __WEBPACK_IMPORTED_MODULE_0__compose__["a" /* default */].apply(undefined, chain)(store.dispatch);

      return _extends({}, store, {
        dispatch: _dispatch
      });
    };
  };
}

/***/ }),
/* 120 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = bindActionCreators;
function bindActionCreator(actionCreator, dispatch) {
  return function () {
    return dispatch(actionCreator.apply(undefined, arguments));
  };
}

/**
 * Turns an object whose values are action creators, into an object with the
 * same keys, but with every function wrapped into a `dispatch` call so they
 * may be invoked directly. This is just a convenience method, as you can call
 * `store.dispatch(MyActionCreators.doSomething())` yourself just fine.
 *
 * For convenience, you can also pass a single function as the first argument,
 * and get a function in return.
 *
 * @param {Function|Object} actionCreators An object whose values are action
 * creator functions. One handy way to obtain it is to use ES6 `import * as`
 * syntax. You may also pass a single function.
 *
 * @param {Function} dispatch The `dispatch` function available on your Redux
 * store.
 *
 * @returns {Function|Object} The object mimicking the original object, but with
 * every action creator wrapped into the `dispatch` call. If you passed a
 * function as `actionCreators`, the return value will also be a single
 * function.
 */
function bindActionCreators(actionCreators, dispatch) {
  if (typeof actionCreators === 'function') {
    return bindActionCreator(actionCreators, dispatch);
  }

  if (typeof actionCreators !== 'object' || actionCreators === null) {
    throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?');
  }

  var keys = Object.keys(actionCreators);
  var boundActionCreators = {};
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var actionCreator = actionCreators[key];
    if (typeof actionCreator === 'function') {
      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch);
    }
  }
  return boundActionCreators;
}

/***/ }),
/* 121 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* WEBPACK VAR INJECTION */(function(process) {/* harmony export (immutable) */ __webpack_exports__["a"] = combineReducers;
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__createStore__ = __webpack_require__(37);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_es_isPlainObject__ = __webpack_require__(29);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__utils_warning__ = __webpack_require__(38);




function getUndefinedStateErrorMessage(key, action) {
  var actionType = action && action.type;
  var actionName = actionType && '"' + actionType.toString() + '"' || 'an action';

  return 'Given action ' + actionName + ', reducer "' + key + '" returned undefined. ' + 'To ignore an action, you must explicitly return the previous state. ' + 'If you want this reducer to hold no value, you can return null instead of undefined.';
}

function getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) {
  var reducerKeys = Object.keys(reducers);
  var argumentName = action && action.type === __WEBPACK_IMPORTED_MODULE_0__createStore__["b" /* ActionTypes */].INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer';

  if (reducerKeys.length === 0) {
    return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';
  }

  if (!__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_1_lodash_es_isPlainObject__["a" /* default */])(inputState)) {
    return 'The ' + argumentName + ' has unexpected type of "' + {}.toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"');
  }

  var unexpectedKeys = Object.keys(inputState).filter(function (key) {
    return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key];
  });

  unexpectedKeys.forEach(function (key) {
    unexpectedKeyCache[key] = true;
  });

  if (unexpectedKeys.length > 0) {
    return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.');
  }
}

function assertReducerShape(reducers) {
  Object.keys(reducers).forEach(function (key) {
    var reducer = reducers[key];
    var initialState = reducer(undefined, { type: __WEBPACK_IMPORTED_MODULE_0__createStore__["b" /* ActionTypes */].INIT });

    if (typeof initialState === 'undefined') {
      throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined. If you don\'t want to set a value for this reducer, ' + 'you can use null instead of undefined.');
    }

    var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.');
    if (typeof reducer(undefined, { type: type }) === 'undefined') {
      throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + __WEBPACK_IMPORTED_MODULE_0__createStore__["b" /* ActionTypes */].INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined, but can be null.');
    }
  });
}

/**
 * Turns an object whose values are different reducer functions, into a single
 * reducer function. It will call every child reducer, and gather their results
 * into a single state object, whose keys correspond to the keys of the passed
 * reducer functions.
 *
 * @param {Object} reducers An object whose values correspond to different
 * reducer functions that need to be combined into one. One handy way to obtain
 * it is to use ES6 `import * as reducers` syntax. The reducers may never return
 * undefined for any action. Instead, they should return their initial state
 * if the state passed to them was undefined, and the current state for any
 * unrecognized action.
 *
 * @returns {Function} A reducer function that invokes every reducer inside the
 * passed object, and builds a state object with the same shape.
 */
function combineReducers(reducers) {
  var reducerKeys = Object.keys(reducers);
  var finalReducers = {};
  for (var i = 0; i < reducerKeys.length; i++) {
    var key = reducerKeys[i];

    if (process.env.NODE_ENV !== 'production') {
      if (typeof reducers[key] === 'undefined') {
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__utils_warning__["a" /* default */])('No reducer provided for key "' + key + '"');
      }
    }

    if (typeof reducers[key] === 'function') {
      finalReducers[key] = reducers[key];
    }
  }
  var finalReducerKeys = Object.keys(finalReducers);

  var unexpectedKeyCache = void 0;
  if (process.env.NODE_ENV !== 'production') {
    unexpectedKeyCache = {};
  }

  var shapeAssertionError = void 0;
  try {
    assertReducerShape(finalReducers);
  } catch (e) {
    shapeAssertionError = e;
  }

  return function combination() {
    var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    var action = arguments[1];

    if (shapeAssertionError) {
      throw shapeAssertionError;
    }

    if (process.env.NODE_ENV !== 'production') {
      var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache);
      if (warningMessage) {
        __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_2__utils_warning__["a" /* default */])(warningMessage);
      }
    }

    var hasChanged = false;
    var nextState = {};
    for (var _i = 0; _i < finalReducerKeys.length; _i++) {
      var _key = finalReducerKeys[_i];
      var reducer = finalReducers[_key];
      var previousStateForKey = state[_key];
      var nextStateForKey = reducer(previousStateForKey, action);
      if (typeof nextStateForKey === 'undefined') {
        var errorMessage = getUndefinedStateErrorMessage(_key, action);
        throw new Error(errorMessage);
      }
      nextState[_key] = nextStateForKey;
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
    }
    return hasChanged ? nextState : state;
  };
}
/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(11)))

/***/ }),
/* 122 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* WEBPACK VAR INJECTION */(function(process) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__createStore__ = __webpack_require__(37);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__combineReducers__ = __webpack_require__(121);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__bindActionCreators__ = __webpack_require__(120);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__applyMiddleware__ = __webpack_require__(119);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__compose__ = __webpack_require__(36);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__utils_warning__ = __webpack_require__(38);
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "createStore", function() { return __WEBPACK_IMPORTED_MODULE_0__createStore__["a"]; });
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "combineReducers", function() { return __WEBPACK_IMPORTED_MODULE_1__combineReducers__["a"]; });
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "bindActionCreators", function() { return __WEBPACK_IMPORTED_MODULE_2__bindActionCreators__["a"]; });
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "applyMiddleware", function() { return __WEBPACK_IMPORTED_MODULE_3__applyMiddleware__["a"]; });
/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "compose", function() { return __WEBPACK_IMPORTED_MODULE_4__compose__["a"]; });







/*
* This is a dummy function to check if the function name has been altered by minification.
* If the function has been minified and NODE_ENV !== 'production', warn the user.
*/
function isCrushed() {}

if (process.env.NODE_ENV !== 'production' && typeof isCrushed.name === 'string' && isCrushed.name !== 'isCrushed') {
  __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_5__utils_warning__["a" /* default */])('You are currently using minified code outside of NODE_ENV === \'production\'. ' + 'This means that you are running a slower development build of Redux. ' + 'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' + 'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' + 'to ensure you have the correct code for your production build.');
}


/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(11)))

/***/ }),
/* 123 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = symbolObservablePonyfill;
function symbolObservablePonyfill(root) {
	var result;
	var Symbol = root.Symbol;

	if (typeof Symbol === 'function') {
		if (Symbol.observable) {
			result = Symbol.observable;
		} else {
			result = Symbol('observable');
			Symbol.observable = result;
		}
	} else {
		result = '@@observable';
	}

	return result;
};


/***/ }),
/* 124 */
/***/ (function(module, exports) {

module.exports = function(originalModule) {
	if(!originalModule.webpackPolyfill) {
		var module = Object.create(originalModule);
		// module.parent = undefined by default
		if(!module.children) module.children = [];
		Object.defineProperty(module, "loaded", {
			enumerable: true,
			get: function() {
				return module.l;
			}
		});
		Object.defineProperty(module, "id", {
			enumerable: true,
			get: function() {
				return module.i;
			}
		});
		Object.defineProperty(module, "exports", {
			enumerable: true,
		});
		module.webpackPolyfill = 1;
	}
	return module;
};


/***/ }),
/* 125 */,
/* 126 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _angular = __webpack_require__(131);

var _angular2 = _interopRequireDefault(_angular);

var _client = __webpack_require__(0);

var _featuredTracks = __webpack_require__(57);

var _featuredTracks2 = _interopRequireDefault(_featuredTracks);

var _nextRaces = __webpack_require__(66);

var _nextRaces2 = _interopRequireDefault(_nextRaces);

var _fullScheduleTracks = __webpack_require__(61);

var _fullScheduleTracks2 = _interopRequireDefault(_fullScheduleTracks);

var _fullScheduleRaces = __webpack_require__(59);

var _fullScheduleRaces2 = _interopRequireDefault(_fullScheduleRaces);

var _leftBarTracks = __webpack_require__(64);

var _leftBarTracks2 = _interopRequireDefault(_leftBarTracks);

var _racesMtpStatus = __webpack_require__(86);

var _racesMtpStatus2 = _interopRequireDefault(_racesMtpStatus);

var _racesNavigation = __webpack_require__(88);

var _racesNavigation2 = _interopRequireDefault(_racesNavigation);

var _raceProgram = __webpack_require__(78);

var _raceProgram2 = _interopRequireDefault(_raceProgram);

var _raceRunners = __webpack_require__(82);

var _raceRunners2 = _interopRequireDefault(_raceRunners);

var _raceResults = __webpack_require__(80);

var _raceResults2 = _interopRequireDefault(_raceResults);

var _racesListResults = __webpack_require__(129);

var _racesListResults2 = _interopRequireDefault(_racesListResults);

var _raceWillpays = __webpack_require__(84);

var _raceWillpays2 = _interopRequireDefault(_raceWillpays);

var _trackList = __webpack_require__(94);

var _trackList2 = _interopRequireDefault(_trackList);

var _raceBettingInterests = __webpack_require__(72);

var _raceBettingInterests2 = _interopRequireDefault(_raceBettingInterests);

var _raceListInfo = __webpack_require__(76);

var _raceListInfo2 = _interopRequireDefault(_raceListInfo);

var _carryOverPools = __webpack_require__(53);

var _carryOverPools2 = _interopRequireDefault(_carryOverPools);

var _talentPicks = __webpack_require__(92);

var _talentPicks2 = _interopRequireDefault(_talentPicks);

var _racesRssFeed = __webpack_require__(90);

var _racesRssFeed2 = _interopRequireDefault(_racesRssFeed);

var _pastTracks = __webpack_require__(70);

var _pastTracks2 = _interopRequireDefault(_pastTracks);

var _horseSearch = __webpack_require__(63);

var _horseSearch2 = _interopRequireDefault(_horseSearch);

var _pastRaces = __webpack_require__(68);

var _pastRaces2 = _interopRequireDefault(_pastRaces);

var _raceEntities = __webpack_require__(74);

var _raceEntities2 = _interopRequireDefault(_raceEntities);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var graphql = new _client.GraphQLClient();
var graphqlFcp = new _client.GraphQLClient();

exports.default = _angular2.default.module('TVG.Graph', []).service('GraphClient', function () {
  return graphql;
}).service('GraphFCPClient', function () {
  return graphqlFcp;
}).service('GraphFeaturedTracks', function () {
  return new _featuredTracks2.default(graphql);
}).service('GraphNextRaces', function () {
  return new _nextRaces2.default(graphql);
}).service('GraphFullScheduleRaces', function () {
  return new _fullScheduleRaces2.default(graphql);
}).service('GraphLeftBarTracks', function () {
  return new _leftBarTracks2.default(graphql);
}).service('GraphRacesMtpStatus', function () {
  return new _racesMtpStatus2.default(graphql);
}).service('GraphRaceProgram', function () {
  return new _raceProgram2.default(graphql);
}).service('GraphFullScheduleRaces', function () {
  return new _fullScheduleRaces2.default(graphql);
}).service('GraphFullScheduleTracks', function () {
  return new _fullScheduleTracks2.default(graphql);
}).service('GraphRaceRunners', function () {
  return new _raceRunners2.default(graphql);
}).service('GraphRaceResults', function () {
  return new _raceResults2.default(graphql);
}).service('GraphRacesNavigation', function () {
  return new _racesNavigation2.default(graphql);
}).service('GraphRaceWillPays', function () {
  return new _raceWillpays2.default(graphql);
}).service('GraphRacesListResults', function () {
  return new _racesListResults2.default(graphql);
}).service('GraphTrackList', function () {
  return new _trackList2.default(graphql);
}).service('GraphRaceBettingInterests', function () {
  return new _raceBettingInterests2.default(graphql);
}).service('GraphRaceListInfo', function () {
  return new _raceListInfo2.default(graphql);
}).service('GraphCarryOverPools', function () {
  return new _carryOverPools2.default(graphql);
}).service('GraphTalentPicks', function () {
  return new _talentPicks2.default(graphql);
}).service('GraphRssFeed', function () {
  return new _racesRssFeed2.default(graphql);
}).service('GraphPastTracks', function () {
  return new _pastTracks2.default(graphqlFcp);
}).service('GraphHorseSearch', function () {
  return new _horseSearch2.default(graphqlFcp);
}).service('GraphPastRaces', function () {
  return new _pastRaces2.default(graphqlFcp);
}).service('GraphRaceEntities', function () {
  return new _raceEntities2.default(graphqlFcp);
}).name;

/***/ }),
/* 127 */,
/* 128 */,
/* 129 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _racesListResults = __webpack_require__(130);

var _racesListResults2 = _interopRequireDefault(_racesListResults);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.default = _racesListResults2.default;

/***/ }),
/* 130 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _templateObject = _taggedTemplateLiteral(['\n      query getRacesListResults(\n        $wagerProfile: String,\n        $sortBy: RaceListSort,\n        $filterBy: RaceListFilter) {\n          races (sort: $sortBy, filter: $filterBy, profile: $wagerProfile) {\n            number\n            postTime\n            status {\n              code\n            }\n            video {\n              onTvg\n              liveStreaming\n              replayFileName\n            }\n            trackCode\n            track {\n              name\n              perfAbbr\n              code\n            }\n            type {\n              id\n              code\n              name\n            }\n            class {\n              name\n            }\n            raceDistance {\n              value\n              code\n            }\n            surface {\n              code\n            }\n            isGreyhound\n          }\n        }'], ['\n      query getRacesListResults(\n        $wagerProfile: String,\n        $sortBy: RaceListSort,\n        $filterBy: RaceListFilter) {\n          races (sort: $sortBy, filter: $filterBy, profile: $wagerProfile) {\n            number\n            postTime\n            status {\n              code\n            }\n            video {\n              onTvg\n              liveStreaming\n              replayFileName\n            }\n            trackCode\n            track {\n              name\n              perfAbbr\n              code\n            }\n            type {\n              id\n              code\n              name\n            }\n            class {\n              name\n            }\n            raceDistance {\n              value\n              code\n            }\n            surface {\n              code\n            }\n            isGreyhound\n          }\n        }']);

var _graphqlTag = __webpack_require__(1);

var _graphqlTag2 = _interopRequireDefault(_graphqlTag);

var _client = __webpack_require__(0);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
                                                                                                                                                           * Races List Results Module
                                                                                                                                                           * @module RacesListResults
                                                                                                                                                           */


var Race =
/**
 * Returns RacesListResults object
 * @param {string} code
 * @param {string} name
 * @param {int} number
 * @param {Date} postTime
 * @param {String} status
 * @param {boolean} onTvg
 * @param {boolean} liveStreaming
 * @param {String} perfAbbr
 */
function Race(code, name, number, postTime, status, onTvg, liveStreaming, perfAbbr, isGreyhound, typeId, typeName, className, distanceValue, distanceCode, replayFileName) {
  _classCallCheck(this, Race);

  this.trackAbbr = code;
  this.trackName = name;
  this.raceNumber = number;
  this.postTime = postTime;
  this.status = status;
  this.onTvg = onTvg; // its on the video
  this.liveStreaming = liveStreaming; // its on the video
  this.raceId = code + '_' + number;
  this.id = code + '_' + number;
  this.perfAbbr = perfAbbr;
  this.isGreyhound = isGreyhound;
  this.typeId = typeId;
  this.typeName = typeName;
  this.className = className;
  this.distanceValue = distanceValue;
  this.distanceCode = distanceCode;
  this.replayFileName = replayFileName;
};

var RacesListResults = function (_GraphQLSubscribeInte) {
  _inherits(RacesListResults, _GraphQLSubscribeInte);

  function RacesListResults() {
    _classCallCheck(this, RacesListResults);

    return _possibleConstructorReturn(this, (RacesListResults.__proto__ || Object.getPrototypeOf(RacesListResults)).apply(this, arguments));
  }

  _createClass(RacesListResults, [{
    key: 'get',


    /**
     * Gets query result from graphql
     * @param {string} wagerProfile
     * @param {array} favorites
     * @returns {Promise.<T>}
     */
    value: function get(wagerProfile, filterBy, page) {
      var _this2 = this;

      var options = {
        wagerProfile: wagerProfile,
        filterBy: filterBy,
        page: page
      };

      return Promise.resolve(options).then(RacesListResults.verifyValidOptions).then(function (queryOptions) {
        _this2.options = queryOptions;
        var graphQuery = RacesListResults.buildQuery(wagerProfile, RacesListResults.prepareFilters(filterBy), page);

        return _this2.graphql.query(graphQuery.string, graphQuery.variables);
      }).then(RacesListResults.verifyNotFoundResult).then(function (result) {
        return options.rawData ? result.data : RacesListResults.buildRaces(result.data.races);
      });
    }

    /**
     * Subscribes to graphql query
     * @param options {wagerProfile, filterBy}
     * @param callback {success, fail}
     * @param {int} pollInterval (ms)
     * @param {boolean} forceFetch
     * @returns {object} Observable
     */

  }, {
    key: 'subscribe',
    value: function subscribe(options, callback) {
      var _this3 = this;

      var pollInterval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var forceFetch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

      var graphQuery = void 0;

      try {
        this.options = RacesListResults.verifyValidOptions(options);
        graphQuery = RacesListResults.buildQuery(this.options.wagerProfile, RacesListResults.prepareFilters(this.options.filterBy), this.options.page);
      } catch (error) {
        callback.fail(error);
        return false;
      }

      return _get(RacesListResults.prototype.__proto__ || Object.getPrototypeOf(RacesListResults.prototype), 'subscribe', this).call(this, graphQuery.string, graphQuery.variables, pollInterval, forceFetch)(function (results) {
        return Promise.resolve(RacesListResults.verifyNotFoundResult(results)).then(function (result) {
          return options.rawData ? result.data : RacesListResults.buildRaces(result.data.races);
        }).then(callback.success).catch(callback.fail);
      }, function (error) {
        if (error.networkError) {
          _get(RacesListResults.prototype.__proto__ || Object.getPrototypeOf(RacesListResults.prototype), 'fetchRetry', _this3).call(_this3, pollInterval);
        } else {
          callback.fail(error);
        }
      });
    }

    /**
     * Refetches data from graqhpl
     * @param options {wagerProfile, filterBy}
     * @returns {Promise.<T>}
     */

  }, {
    key: 'refetch',
    value: function refetch(options) {
      var _this4 = this;

      return Promise.resolve(options).then(RacesListResults.verifyValidOptions).then(function (queryOptions) {
        _this4.options = queryOptions;
        var queryVariables = {
          filterBy: queryOptions.filterBy,
          wagerProfile: queryOptions.wagerProfile
        };

        return _get(RacesListResults.prototype.__proto__ || Object.getPrototypeOf(RacesListResults.prototype), 'refetch', _this4).call(_this4, queryVariables)(function (result) {
          return result;
        }, function (error) {
          throw new Error(error);
        }).then(RacesListResults.verifyNotFoundResult).then(function (result) {
          return options.rawData ? result.data : RacesListResults.buildRaces(result.data.races);
        });
      });
    }
  }], [{
    key: 'buildRaces',


    /**
     *  Builds array with Race from raceData
     * @param {Array} raceData
     * @returns {Race|Array}
     */
    value: function buildRaces(raceData) {
      return raceData.map(function (race) {
        return new Race(race.track.code, race.track.name, race.number, new Date(race.postTime), race.status.code, race.video ? race.video.onTvg : false, race.video ? race.video.liveStreaming : false, race.track.perfAbbr, race.isGreyhound, race.type.id, race.type.name, race.class.name, race.raceDistance.value, race.raceDistance.code, race.video ? race.video.replayFileName : false);
      });
    }

    /**
     * Builds the query to be used on the refetch / subscribe / get methods
     * @param wagerProfile
     * @param filterBy
     * @param page
     * @returns {{string: *, variables: {sortBy: {byPostTime: string}, filterBy: {}, wagerProfile: *, page: {}}}}
     */

  }, {
    key: 'buildQuery',
    value: function buildQuery(wagerProfile) {
      var filterBy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var page = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

      var queryString = (0, _graphqlTag2.default)(_templateObject);

      var queryVariables = {
        sortBy: { byPostTime: 'DESC' },
        filterBy: filterBy,
        wagerProfile: wagerProfile,
        page: page
      };

      return {
        string: queryString,
        variables: queryVariables
      };
    }

    /**
     * Prepares filter object for query
     * @param {object} filterBy
     * @returns {*}
     */

  }, {
    key: 'prepareFilters',
    value: function prepareFilters(filterBy) {
      // Remove empty typeCode filter
      if (filterBy && filterBy.typeCode && filterBy.typeCode.length === 0) {
        delete filterBy.typeCode;
      }

      return filterBy;
    }

    /**
     * Verify if the options the required for query
     * @param options
     */

  }, {
    key: 'verifyValidOptions',
    value: function verifyValidOptions(options) {
      if (!options || !options.wagerProfile) {
        throw new Error('You must specify a wagerProfile in the options');
      }

      var _options$wagerProfile = options.wagerProfile,
          wagerProfile = _options$wagerProfile === undefined ? '' : _options$wagerProfile,
          _options$filterBy = options.filterBy,
          filterBy = _options$filterBy === undefined ? {} : _options$filterBy,
          page = options.page;


      return {
        wagerProfile: wagerProfile,
        filterBy: RacesListResults.prepareFilters(filterBy),
        page: page
      };
    }

    /**
     * Verify if no results are returned
     * @param result
     * @returns {*}
     */

  }, {
    key: 'verifyNotFoundResult',
    value: function verifyNotFoundResult(result) {
      if (!result.data) {
        throw new Error('Races Results not found');
      }
      return result;
    }
  }]);

  return RacesListResults;
}(_client.GraphQLSubscribeInterface);

exports.default = RacesListResults;

/***/ }),
/* 131 */
/***/ (function(module, exports) {

module.exports = __WEBPACK_EXTERNAL_MODULE_131__;

/***/ }),
/* 132 */,
/* 133 */
/***/ (function(module, exports, __webpack_require__) {

__webpack_require__(13);
module.exports = __webpack_require__(126);


/***/ })
/******/ ]);
});
//# sourceMappingURL=tvg-graph.mod.umd.js.map;
modules/GTM/providers/gtmFacDecorator.js
'use strict';

define('GTMFacDecorator',[],
    function () {
        /**
         * The objective of this decorator is to extend the GTM parameters object with a temporary
         * property: 'navigationPosition'. The idea is to remove this when the next races bar A/B testing finishes.
         *
         * Q: Why not changing the original GTMFac?
         * A: Because it's a temporary add-on to the GTM dataLayers, for A/B test reporting. This way its removal
         * will be easier.
         *
         */
        function gtmFacDecorator($delegate, $rootScope) {
            var gtmEventFn = $delegate.GTMEvent;

            function _getAdditionalParamsExtended(additionalParams) {
                var navigationPositionObject = {};
                var params = additionalParams || {};

                if ($rootScope.showNextRacesBar) {
                    navigationPositionObject.navigationPosition = !$rootScope.showLeftBar ? 'Top Nav' : 'Left Nav';
                }

                return angular.extend(params, navigationPositionObject);
            }

            function newGTMEventFn() {
                // Let's call the original GTMEvent function to get the object that we want to modify.
                var gtmEventObj = gtmEventFn.apply($delegate);
                // This is the function we want to change.
                // We keep a reference to it because this function will continue to be called.
                // The difference is that we want to extend one of its arguments.
                var oldGTMEventObjSendFn = gtmEventObj.send;

                gtmEventObj.send = function (scope, eventName, additionalParams, sendEvent) {
                    return oldGTMEventObjSendFn(
                        scope,
                        eventName,
                        _getAdditionalParamsExtended(additionalParams),
                        sendEvent);
                };

                return gtmEventObj;
            }

            $delegate.GTMEvent = newGTMEventFn;
            return $delegate;
        }

        gtmFacDecorator.$inject = [
            '$delegate',
            '$rootScope'
        ];

        return gtmFacDecorator;
    }
);

modules/GTM/gtmDesktopMod.js
'use strict';

define('GTMDesktopMod',[
        'GTMFacDecorator',
        'GTMMod'
    ],
    function (GTMFacDecorator) {
        angular.module('TVG.GTM', [
            'TVG.Common.GTM'
        ])
            .decorator('GTMFac', GTMFacDecorator);
    }
);
app.js
/* global angular */

'use strict';

define('app',[
        'TVGCommon',
        'DepositGTM',
        'Configuration',
        'Content',
        'AppCore',
        'Layout',
        'RaceInfo',
        'Races',
        'Security',
        'UserProfile',
        'Utilities',
        'BetService',
        'BetSlipWindow',
        'uibootstrap',
        'uibootstraptpls',
        'Poller',
        'angularCookies',
        'Deposit',
        'Features',
        'ngMd5',
        'TrackSelector',
        'tvgTemplates',
        'BetslipMainMod',
        'FavoriteTracks',
        'Preferences',
        'Graph',
        'GTMDesktopMod'
    ], function (TVGCommon, DepositGTM) {

        angular.module('TVG', [
            'ngRoute',
            'ngCookies',
            'ipCookie',
            'ab-base64',
            'ngSanitize',
            'ngMd5',
            'ngAnimate',
            'ui.bootstrap',
            'TVG.Configuration',
            'TVG.Content',
            'TVG.AppCore',
            'TVG.Layout',
            'TVG.RaceInfo',
            'TVG.Races',
            'TVG.Security',
            'TVG.UserProfile',
            'TVG.Utilities',
            'TVG.BetService',
            'TVG.BetSlipWindow',
            'TVG.Deposit',
            'TVG.Withdraw',
            'TVG.poller',
            'TVG.Features',
            'TVG.TrackSelector',
            'TVG.Templates',
            'TVG.BetslipMain',
            'TVG.FavoriteTracks',
            'TVG.Preferences',
            'TVG.Graph',
            'TVG.GTM'
        ])
            .config([
                '$routeProvider',
                '$locationProvider',
                '$httpProvider',
                '$compileProvider',
                '$uibTooltipProvider',
                'ConfigurationFacProvider',
                'AppRequestInterceptorProvider',
                function ($routeProvider, $locationProvider, $httpProvider, $compileProvider, $uibTooltipProvider, ConfigurationFac, AppRequestInterceptor) {

                    if(envName === 'prod') {
                        $compileProvider.debugInfoEnabled(false);
                    }

                    $uibTooltipProvider.setTriggers({'triggerTooltip': 'triggerTooltip'});

                    AppRequestInterceptor.setMetadata();
                    AppRequestInterceptor.setFeatures();
                    AppRequestInterceptor.setCmsContent();

                    AppRequestInterceptor.setHeadersRequest();
                    AppRequestInterceptor.setInterceptResponse();

                    $locationProvider.html5Mode(true);
                    $routeProvider
                        .when('/betslip/:trackAbbr?/:perfAbbr?/:raceNumber?', {
                            templateUrl: 'js/views/betslip-window.html',
                            title: 'Bet Ticket',
                            hasTopBarNavigation: true
                        });

                }
            ]).run([
                'AppRootFac',
                '$rootScope',
                'CrossWindowMessaging',
                'UserBalanceSvc',
                'ConfigurationFac',
                'GraphClient',
                function (
                        AppRootFac,
                        $rootScope,
                        CrossWindowMessaging,
                        UserBalanceSvc,
                        ConfigurationFac,
                        GraphClient
                    ) {
                    var graphUrl = ConfigurationFac.getServiceApiUrl('graph');

                    // cosmo migration
                    var url = graphUrl
                        .replace("service", "api")
                        .replace("/graph/v2/query", "/cosmo/v1/graphql")
                        .replace("api.us.betfair.com", "tvg-api.us.betfair.com")
                        .replace(
                            "api-qa.us.betfair.com",
                            "tvg-api-qa.us.betfair.com"
                        )
                        .replace(
                            "api-staging.us.betfair.com",
                            "tvg-api-staging.us.betfair.com"
                        )

                    GraphClient.configureGraphClient(url);

                    DepositGTM.default($rootScope);


                    // @HACK - DO NOT REMOVE THIS!
                    // otherwise, UserBalanceSvc won't bind to rootScope's "user" events
                    // and there will be no balance available
                    if (!UserBalanceSvc) {
                        console.warn('UserBalanceSvc must be loaded during app startup!');
                    }

                    if(typeof window !== "undefined" && window.appboy){
                        var environment = {
                            dev: "qa",
                            qa: "qa",
                            staging: "staging",
                            prod: "production"
                        };
                        window.appboy.initialize(ConfigurationFac.getStartupConfig(environment[envName], "braze", "key"),{
                            minimumIntervalBetweenTriggerActionsInSeconds: 5,
                            enableHtmlInAppMessages: true
                        });
                        if($rootScope.user && $rootScope.user.accountNumber){
                            window.appboy.changeUser($rootScope.user.accountNumber);
                        }
                    }

                    AppRootFac.initBetSlip();

                    if ((envName === 'dev' || envName === 'qa') && ($rootScope.activeFeatures && $rootScope.activeFeatures.qaConsumingStagingGraph)) {
                        // when on QA environment, set the graph url to the staging graph so that we have more production-like feeds
                        // this is under toggle so every time anyone wants to consume qa graph we just need to disable the toggle manually
                        graphUrl = ConfigurationFac.getStartupConfig('staging', 'baseUrl', 'service_api') +
                            ConfigurationFac.getStartupConfig('staging', 'service', 'graph');
                    }

                    /* ----- RootScope Functions ----- */
                    AppRootFac.fnGo();
                    AppRootFac.fnGetLocationPath();

                    /* ----- RootScope Listeneners ----- */
                    AppRootFac.onUser();
                    AppRootFac.onLocationChangeStart();
                    AppRootFac.onRouteChangeStart();
                    AppRootFac.onLogin();
                    AppRootFac.onLogout();

                    CrossWindowMessaging.onAccountBalanceUpdate();
                    CrossWindowMessaging.onBetPlaced();
                }]
        );
    }
);

bootstrap.js
function bootApplication() { //eslint-disable-line no-unused-vars
    angular.bootstrap(document, ['TVG']);
}

require([
    'app'
], function () {
    initializeApp();
});

define("bootstrap", function(){});

main.js
require.config({
    baseUrl: 'js', // Relative to index

    paths: {
        // node modules
        lodash: '../node_modules/lodash/lodash',
        moment: '../node_modules/moment/min/moment.min',
        momentTimezone: '../node_modules/moment-timezone/builds/moment-timezone-with-data-2010-2020.min',
        Graph: '../node_modules/@tvg/graph/dist/tvg-graph.mod.umd',
        DepositGTM: '../node_modules/@tvg/deposit-gtm/build/bundle',
        Deposit: '../node_modules/@tvg/deposit/modules',

        //Vendors
        angular: 'vendors/angular/angular.min',
        angularRoute: 'vendors/angular-route/angular-route.min',
        angularSanitize: 'vendors/angular-sanitize/angular-sanitize.min',
        angularAnimate: 'vendors/angular-animate/angular-animate.min',
        ngMd5: 'vendors/angular-md5/angular-md5.min',
        uibootstrap: 'vendors/angular-bootstrap/ui-bootstrap.min',
        uibootstraptpls: 'vendors/angular-bootstrap/ui-bootstrap-tpls.min',
        angularCookies: 'vendors/angular-cookies/angular-cookies.min',
        angularCookie: 'vendors/angular-cookie/angular-cookie.min',
        angularUTF8Base64: 'vendors/angular-utf8-base64/angular-utf8-base64.min',
        muton: 'vendors/muton/muton.window',
        Configuration: 'vendors/tvg-configuration/configurationMod.min',
        Content: 'vendors/tvg-content/contentMod.min',
        matchMedia: 'vendors/matchMedia/matchMedia',
        ngDialog: 'vendors/ng-dialog/js/ngDialog',
        angularFilter: 'vendors/angular-filter/dist/angular-filter',
        TVGCommon: 'vendors/tvg-common/dist/TVGCommon.umd.min',
        uiMask: 'vendors/angular-ui-mask/dist/mask.min',

        //App core module
        app: 'app',
        AppCore: 'modules/AppCore/appCoreMod',
        AppRootFac: 'modules/AppCore/providers/appRootFac',
        AppRequestInterceptor: 'modules/AppCore/providers/appRequestInterceptor',

        //Poller module
        Poller: 'modules/Poller/pollerMod',

        //  BetTicket Module
        BetService: 'modules/BetService/betServiceBase',
        BetsSvc: 'modules/BetService/providers/betsSvcV2',
        StepSelectionsStringFilter: 'modules/BetService/filters/stepSelectionsStringFilter',

        //  BetSlip Window Module
        BetSlipWindow: 'modules/BetSlipWindow/betSlipWindowMod',
        BetSlipWindowCtrl: 'modules/BetSlipWindow/controllers/betSlipWindowCtrl',
        BetSlipWindowDir: 'modules/BetSlipWindow/directives/betslip-window-directive',
        BetSlipAccountInfoDir: 'modules/BetSlipWindow/directives/betslip-account-info-directive',
        BetSlipAlertBannerDir: 'modules/BetSlipWindow/directives/betslip-alert-banner-directive',
        BetSlipAccountInfoCtrl: 'modules/BetSlipWindow/controllers/betSlipAccountInfoCtrl',
        BetSlipWindowAlertsFac: 'modules/BetSlipWindow/providers/betSlipWindowAlertsFac',
        TrackSelectorWindowCtrl: 'modules/BetSlipWindow/controllers/trackSelectorWindowCtrl',
        TrackSelectorWindowDir: 'modules/BetSlipWindow/directives/track-selector-window-directive',
        RunnerSaddleModel: 'modules/BetSlipWindow/models/runnerSaddleModel',

        //Features Module
        Features: 'modules/Features/featuresMod',
        FeaturesFac: 'modules/Features/providers/factories/featuresFac',
        FeaturesConfigController: 'modules/Features/controllers/featuresConfigController',

        // GTM
        GTMMod                                           : 'modules/GTM/gtmMod',
        GTMFac                                           : 'modules/GTM/providers/GTMFac',
        RegistrationPageGTMFac                           : 'modules/GTM/providers/registrationPageGTMFac',
        ScreenNames                                      : 'modules/GTM/constants/screenNames',
        SectionNames                                     : 'modules/GTM/constants/sectionNames',

        //RaceInfo Module
        RaceInfo: 'modules/RaceInfo/raceInfoMod',
        RaceUrlFac: 'modules/RaceInfo/providers/raceUrlFac',
        RaceParamsEntity: 'modules/RaceInfo/entities/raceParamsEntity',
        RaceParamsEntityBuilder: 'modules/RaceInfo/builders/raceParamsEntityBuilder',
        RaceInfoFac: 'modules/RaceInfo/providers/raceInfoFac',
        RaceMTP: 'modules/RaceInfo/filters/raceMTP',
        RaceLinkFilter: 'modules/RaceInfo/filters/raceLinkFilter',
        RaceMtpStatusFac: 'modules/RaceInfo/providers/raceMtpStatusFac',

        //Races Module
        Races: 'modules/Races/racesMod',
        RaceMTPFilter: 'modules/Races/filters/raceMTPFilter',
        MtpDisplayModel: 'modules/Races/controllers/models/mtpDisplay',
        RaceStatusUtils: 'modules/Utilities/tools/raceStatusUtils',
        RaceStatusLabelDir: 'modules/Races/directives/race-status-label-directive',
        RaceMtpLabelDir: 'modules/Races/components/raceMtpLabel/directives/raceMtpLabelDir',
        RaceMtpLabelMod: 'modules/Races/components/raceMtpLabel/raceMtpLabelMod',

        //Track Selector Module
        TrackSelectorCtrl: 'modules/Tracks/components/trackSelector/controllers/trackSelectorCtrl',
        TrackSelectorDir: 'modules/Tracks/components/trackSelector/directives/track-selector-directive',
        TrackSelectorItem: 'modules/Tracks/components/trackSelector/models/trackSelectorItem',
        TrackSelectorItemBuilder: 'modules/Tracks/components/trackSelector/models/builders/trackSelectorItemBuilder',
        TrackSelectorItemFactory: 'modules/Tracks/components/trackSelector/factories/trackSelectorItemFactory',
        TrackSelectorItemCurrentRaceFactory: 'modules/Tracks/components/trackSelector/factories/trackSelectorItemCurrentRaceFactory',
        TrackSelector: 'modules/Tracks/components/trackSelector/trackSelectorMod',

        // Track Module
        Track: 'modules/Track/trackMod',
        TrackSvc: 'modules/Track/providers/trackSvc',

        // Security Module
        Security: 'modules/Security/securityMod',
        SecuritySvc: 'modules/Security/providers/securitySvc',
        UserSessionSvc: 'modules/Security/providers/userSessionSvc',
        GeoComplyLoginSvc: 'modules/Security/providers/geoComplyLoginSvc',
        GeoComplySvc: 'modules/Security/providers/geoComplySvc',
        PollingScheduler: 'modules/Security/providers/pollingScheduler',

        // UserProfile Module
        UserProfile: 'modules/UserProfile/userProfileMod',
        UserProfileSvc: 'modules/UserProfile/providers/services/userProfileSvc',
        UserBalanceSvc: 'modules/UserProfile/providers/services/userBalanceSvc',
        StatesSvc: 'modules/UserProfile/providers/services/statesSvc',
        PasswordValidatorSvc: 'modules/UserProfile/providers/helpers/passwordValidatorSvc',
        UsernameValidatorSvc: 'modules/UserProfile/providers/helpers/usernameValidatorSvc',
        ProfileHelperSvc: 'modules/UserProfile/providers/helpers/profileHelperSvc',
        QuickDepositCtrl: 'modules/UserProfile/controllers/quickDepositCtrl',

        // Layout Module
        Layout: 'modules/Layout/layoutMod',
        LayoutDir: 'modules/Layout/directives/layout-directive',
        SwitchLayoutForDir: 'modules/Layout/directives/switch-layout-for-directive',
        LayoutFac: 'modules/Layout/providers/factories/layoutFac',

        // Utilities Module
        Utilities: 'modules/Utilities/utilitiesMod',
        CookieFac: 'modules/Utilities/providers/factories/cookieFac',
        PreferencesCookieFac: 'modules/Utilities/providers/factories/preferencesCookieFac',
        FavoriteCookieFac: 'modules/Utilities/providers/factories/favoriteCookieFac',
        LocalStorageFac: 'modules/Utilities/providers/factories/localStorageFac',
        LocationUnreloadFac: 'modules/Utilities/providers/factories/locationUnreloadFac',
        DateTimeFormatters: 'modules/Utilities/formatters/dateTimeFormatters',
        StatePersistenceFac: 'modules/Utilities/providers/factories/statePersistenceFac',
        FeaturesHandlerSvc: 'modules/Utilities/providers/service/featuresHandlerSvc',
        UserPropertiesSvc: 'modules/Utilities/providers/service/userPropertiesSvc',
        RaceMtpDisplay: 'modules/Utilities/tools/raceMtpDisplay',
        WagerProfileFac: 'modules/Utilities/providers/factories/wagerProfileFac',
        TvgHostsFac: 'modules/Utilities/providers/factories/tvgHostsFac',
        AmountOptionsFac: 'modules/Utilities/providers/factories/amountOptionsFac',

        PreventDefaultDir: 'modules/Utilities/directives/prevent-default-directive',

        NewWindowGridFac: 'modules/Utilities/providers/factories/newWindowGridFac',
        GetNestedPropertyValueFilter: 'modules/Utilities/filters/getNestedPropertyValueFilter',
        GetRelativeDayBasedOnGivenDateFilter: 'modules/Utilities/filters/getRelativeDayBasedOnGivenDateFilter',

        DateComparators: 'modules/Utilities/formatters/dateComparators',
        RoundAmountFilter: 'modules/Utilities/filters/roundAmountFilter',
        ReverseFilter: 'modules/Utilities/filters/reverseFilter',
        RaceTypeIDFilter: 'modules/Utilities/filters/raceTypeIDFilter',

        tvgTemplates: 'tvg.templates',

        //Favorite Tracks
        FavoriteTracks: 'modules/FavoriteTracks/favoriteTracksMod',
        FavoriteTracksFac: 'modules/FavoriteTracks/providers/favoriteTracksFac',

        //Preferences
        Preferences: 'modules/Preferences/preferencesMod',
        PreferencesFac: 'modules/Preferences/providers/preferencesFac',
        PreferencesEntity: 'modules/Preferences/entities/preferencesEntity',
        PreferencesEntityBuilder: 'modules/Preferences/builders/preferencesEntityBuilder',

        //Features JSON
        defaultFeatures: 'defaultFeatures',

        MathAbsoluteValueFilter : 'modules/Utilities/filters/mathAbsoluteValueFilter',

        // BetSlip Main Module
        BetslipMainMod: 'modules/Main/betslipMainMod',
        CrossWindowMessagingFac: 'modules/Main/providers/crossWindowMessagingFac',

        // GTM factory decorator
        GTMFacDecorator: 'modules/GTM/providers/gtmFacDecorator',
        GTMDesktopMod: 'modules/GTM/gtmDesktopMod',

        //Common
        initData: 'initData'
    },
    shim: {
        angular: { exports: 'angular' },
        lodash: { exports: '_' },
        muton: { exports: 'muton' },
        angularRoute: ['angular'],
        angularAnimate: ['angular'],
        ngMd5: ['angular'],
        angularCookies: ['angular'],
        angularCookie: ['angular'],
        angularUTF8Base64: ['angular'],
        uibootstrap: ['angular'],
        uibootstraptpls: ['uibootstrap'],
        Poller: ['angular'],
        Deposit: ['angular'],
        Configuration: ['angular', 'matchMedia'],
        Content: ['angular'],
        angularSanitize: ['angular'],
        ngDialog: ['angular'],
        angularFilter: ['angular'],
        TVGCommon: ['angular'],
        uiMask: ['angular'],
        app: [
            'initData',
            'defaultFeatures',
            'Poller',
            'angularRoute',
            'uibootstraptpls',
            'angularSanitize',
            'angularAnimate',
            'angularCookies',
            'angularCookie',
            'angularUTF8Base64',
            'lodash',
            'ngMd5',
            'muton',
            'moment',
            'ngDialog',
            'angularFilter',
            'TVGCommon',
            'uiMask',
            'Deposit'
        ]
    },
    priority: ['angular'],
    deps: ['./bootstrap']
});

define("main", function(){});