/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @author       Felipe Alfonso <@bitnenfer>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Container = require('./Container');
var GameObjectFactory = require('../GameObjectFactory');

/**
 * Creates a new Container Game Object and adds it to the Scene.
 *
 * Note: This method will only be available if the Container Game Object has been built into Phaser.
 *
 * @method Phaser.GameObjects.GameObjectFactory#container
 * @since 3.4.0
 *
 * @param {number} x - The horizontal position of this Game Object in the world.
 * @param {number} y - The vertical position of this Game Object in the world.
 * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} [children] - An optional array of Game Objects to add to this Container.
 *
 * @return {Phaser.GameObjects.Container} The Game Object that was created.
 */
GameObjectFactory.register('container', function (x, y, children)
{
    return this.displayList.add(new Container(this.scene, x, y, children));
});


* GameObjects added to and removed from Containers no longer listen for the `shutdown` event at all (thanks Vitali)

* The Loader has been updated to handle the impact of you destroying the game instance while still processing files. It will no longer throw cache and texture related errors. Fix #4049 (thanks @pantoninho)

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * @namespace Phaser.Utils.Array.Matrix
 */

module.exports = {

    CheckMatrix: require('./CheckMatrix'),
    MatrixToString: require('./MatrixToString'),
    ReverseColumns: require('./ReverseColumns'),
    ReverseRows: require('./ReverseRows'),
    Rotate180: require('./Rotate180'),
    RotateLeft: require('./RotateLeft'),
    RotateMatrix: require('./RotateMatrix'),
    RotateRight: require('./RotateRight'),
    TransposeMatrix: require('./TransposeMatrix')

};


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var GetFastValue = require('../../../src/utils/object/GetFastValue');

/**
 * @typedef {object} Product
 *
 * @property {string} [title] - The title of the product.
 * @property {string} [productID] - The product's game-specified identifier.
 * @property {string} [description] - The product description.
 * @property {string} [imageURI] - A link to the product's associated image.
 * @property {string} [price] - The price of the product.
 * @property {string} [priceCurrencyCode] - The currency code for the product.
 */

var Product = function (data)
{
    return {
        title: GetFastValue(data, 'title', ''),
        productID: GetFastValue(data, 'productID', ''),
        description: GetFastValue(data, 'description', ''),
        imageURI: GetFastValue(data, 'imageURI', ''),
        price: GetFastValue(data, 'price', ''),
        priceCurrencyCode: GetFastValue(data, 'priceCurrencyCode', '')
    };
};

module.exports = Product;


keep keep keep keep add keep keep keep keep

//  Has the game been destroyed during load? If so, bail out now.

/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Class = require('../utils/Class');
var CONST = require('./const');
var CustomSet = require('../structs/Set');
var EventEmitter = require('eventemitter3');
var FileTypesManager = require('./FileTypesManager');
var GetFastValue = require('../utils/object/GetFastValue');
var PluginCache = require('../plugins/PluginCache');
var XHRSettings = require('./XHRSettings');

/**
 * @classdesc
 * The Loader handles loading all external content such as Images, Sounds, Texture Atlases and data files.
 * You typically interact with it via `this.load` in your Scene. Scenes can have a `preload` method, which is always
 * called before the Scenes `create` method, allowing you to preload assets that the Scene may need.
 *
 * If you call any `this.load` methods from outside of `Scene.preload` then you need to start the Loader going
 * yourself by calling `Loader.start()`. It's only automatically started during the Scene preload.
 *
 * The Loader uses a combination of tag loading (eg. Audio elements) and XHR and provides progress and completion events.
 * Files are loaded in parallel by default. The amount of concurrent connections can be controlled in your Game Configuration.
 *
 * Once the Loader has started loading you are still able to add files to it. These can be injected as a result of a loader
 * event, the type of file being loaded (such as a pack file) or other external events. As long as the Loader hasn't finished
 * simply adding a new file to it, while running, will ensure it's added into the current queue.
 *
 * Every Scene has its own instance of the Loader and they are bound to the Scene in which they are created. However,
 * assets loaded by the Loader are placed into global game-level caches. For example, loading an XML file will place that
 * file inside `Game.cache.xml`, which is accessible from every Scene in your game, no matter who was responsible
 * for loading it. The same is true of Textures. A texture loaded in one Scene is instantly available to all other Scenes
 * in your game.
 *
 * The Loader works by using custom File Types. These are stored in the FileTypesManager, which injects them into the Loader
 * when it's instantiated. You can create your own custom file types by extending either the File or MultiFile classes.
 * See those files for more details.
 *
 * @class LoaderPlugin
 * @extends Phaser.Events.EventEmitter
 * @memberOf Phaser.Loader
 * @constructor
 * @since 3.0.0
 *
 * @param {Phaser.Scene} scene - The Scene which owns this Loader instance.
 */
var LoaderPlugin = new Class({

    Extends: EventEmitter,

    initialize:

    function LoaderPlugin (scene)
    {
        EventEmitter.call(this);

        var gameConfig = scene.sys.game.config;
        var sceneConfig = scene.sys.settings.loader;

        /**
         * The Scene which owns this Loader instance.
         *
         * @name Phaser.Loader.LoaderPlugin#scene
         * @type {Phaser.Scene}
         * @protected
         * @since 3.0.0
         */
        this.scene = scene;

        /**
         * A reference to the Scene Systems.
         *
         * @name Phaser.Loader.LoaderPlugin#systems
         * @type {Phaser.Scenes.Systems}
         * @protected
         * @since 3.0.0
         */
        this.systems = scene.sys;

        /**
         * A reference to the global Cache Manager.
         *
         * @name Phaser.Loader.LoaderPlugin#cacheManager
         * @type {Phaser.Cache.CacheManager}
         * @protected
         * @since 3.7.0
         */
        this.cacheManager = scene.sys.cache;

        /**
         * A reference to the global Texture Manager.
         *
         * @name Phaser.Loader.LoaderPlugin#textureManager
         * @type {Phaser.Textures.TextureManager}
         * @protected
         * @since 3.7.0
         */
        this.textureManager = scene.sys.textures;

        //  Inject the available filetypes into the Loader
        FileTypesManager.install(this);

        /**
         * An optional prefix that is automatically prepended to the start of every file key.
         * If prefix was `MENU.` and you load an image with the key 'Background' the resulting key would be `MENU.Background`.
         * You can set this directly, or call `Loader.setPrefix()`. It will then affect every file added to the Loader
         * from that point on. It does _not_ change any file already in the load queue.
         *
         * @name Phaser.Loader.LoaderPlugin#prefix
         * @type {string}
         * @default ''
         * @since 3.7.0
         */
        this.prefix = '';

        /**
         * The value of `path`, if set, is placed before any _relative_ file path given. For example:
         *
         * ```javascript
         * this.load.path = "images/sprites/";
         * this.load.image("ball", "ball.png");
         * this.load.image("tree", "level1/oaktree.png");
         * this.load.image("boom", "http://server.com/explode.png");
         * ```
         *
         * Would load the `ball` file from `images/sprites/ball.png` and the tree from
         * `images/sprites/level1/oaktree.png` but the file `boom` would load from the URL
         * given as it's an absolute URL.
         *
         * Please note that the path is added before the filename but *after* the baseURL (if set.)
         *
         * If you set this property directly then it _must_ end with a "/". Alternatively, call `setPath()` and it'll do it for you.
         *
         * @name Phaser.Loader.LoaderPlugin#path
         * @type {string}
         * @default ''
         * @since 3.0.0
         */
        this.path = '';

        /**
         * If you want to append a URL before the path of any asset you can set this here.
         *
         * Useful if allowing the asset base url to be configured outside of the game code.
         *
         * If you set this property directly then it _must_ end with a "/". Alternatively, call `setBaseURL()` and it'll do it for you.
         *
         * @name Phaser.Loader.LoaderPlugin#baseURL
         * @type {string}
         * @default ''
         * @since 3.0.0
         */
        this.baseURL = '';

        this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL));

        this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath));

        this.setPrefix(GetFastValue(sceneConfig, 'prefix', gameConfig.loaderPrefix));

        /**
         * The number of concurrent / parallel resources to try and fetch at once.
         *
         * Old browsers limit 6 requests per domain; modern ones, especially those with HTTP/2 don't limit it at all.
         *
         * The default is 32 but you can change this in your Game Config, or by changing this property before the Loader starts.
         *
         * @name Phaser.Loader.LoaderPlugin#maxParallelDownloads
         * @type {integer}
         * @since 3.0.0
         */
        this.maxParallelDownloads = GetFastValue(sceneConfig, 'maxParallelDownloads', gameConfig.loaderMaxParallelDownloads);

        /**
         * xhr specific global settings (can be overridden on a per-file basis)
         *
         * @name Phaser.Loader.LoaderPlugin#xhr
         * @type {XHRSettingsObject}
         * @since 3.0.0
         */
        this.xhr = XHRSettings(
            GetFastValue(sceneConfig, 'responseType', gameConfig.loaderResponseType),
            GetFastValue(sceneConfig, 'async', gameConfig.loaderAsync),
            GetFastValue(sceneConfig, 'user', gameConfig.loaderUser),
            GetFastValue(sceneConfig, 'password', gameConfig.loaderPassword),
            GetFastValue(sceneConfig, 'timeout', gameConfig.loaderTimeout)
        );

        /**
         * The crossOrigin value applied to loaded images. Very often this needs to be set to 'anonymous'.
         *
         * @name Phaser.Loader.LoaderPlugin#crossOrigin
         * @type {string}
         * @since 3.0.0
         */
        this.crossOrigin = GetFastValue(sceneConfig, 'crossOrigin', gameConfig.loaderCrossOrigin);

        /**
         * The total number of files to load. It may not always be accurate because you may add to the Loader during the process
         * of loading, especially if you load a Pack File. Therefore this value can change, but in most cases remains static.
         *
         * @name Phaser.Loader.LoaderPlugin#totalToLoad
         * @type {integer}
         * @default 0
         * @since 3.0.0
         */
        this.totalToLoad = 0;

        /**
         * The progress of the current load queue, as a float value between 0 and 1.
         * This is updated automatically as files complete loading.
         * Note that it is possible for this value to go down again if you add content to the current load queue during a load.
         *
         * @name Phaser.Loader.LoaderPlugin#progress
         * @type {number}
         * @default 0
         * @since 3.0.0
         */
        this.progress = 0;

        /**
         * Files are placed in this Set when they're added to the Loader via `addFile`.
         *
         * They are moved to the `inflight` Set when they start loading, and assuming a successful
         * load, to the `queue` Set for further processing.
         *
         * By the end of the load process this Set will be empty.
         *
         * @name Phaser.Loader.LoaderPlugin#list
         * @type {Phaser.Structs.Set.<Phaser.Loader.File>}
         * @since 3.0.0
         */
        this.list = new CustomSet();

        /**
         * Files are stored in this Set while they're in the process of being loaded.
         *
         * Upon a successful load they are moved to the `queue` Set.
         *
         * By the end of the load process this Set will be empty.
         *
         * @name Phaser.Loader.LoaderPlugin#inflight
         * @type {Phaser.Structs.Set.<Phaser.Loader.File>}
         * @since 3.0.0
         */
        this.inflight = new CustomSet();

        /**
         * Files are stored in this Set while they're being processed.
         *
         * If the process is successful they are moved to their final destination, which could be
         * a Cache or the Texture Manager.
         *
         * At the end of the load process this Set will be empty.
         *
         * @name Phaser.Loader.LoaderPlugin#queue
         * @type {Phaser.Structs.Set.<Phaser.Loader.File>}
         * @since 3.0.0
         */
        this.queue = new CustomSet();

        /**
         * A temporary Set in which files are stored after processing,
         * awaiting destruction at the end of the load process.
         *
         * @name Phaser.Loader.LoaderPlugin#_deleteQueue
         * @type {Phaser.Structs.Set.<Phaser.Loader.File>}
         * @private
         * @since 3.7.0
         */
        this._deleteQueue = new CustomSet();

        /**
         * The total number of files that failed to load during the most recent load.
         * This value is reset when you call `Loader.start`.
         *
         * @name Phaser.Loader.LoaderPlugin#totalFailed
         * @type {integer}
         * @default 0
         * @since 3.7.0
         */
        this.totalFailed = 0;

        /**
         * The total number of files that successfully loaded during the most recent load.
         * This value is reset when you call `Loader.start`.
         *
         * @name Phaser.Loader.LoaderPlugin#totalComplete
         * @type {integer}
         * @default 0
         * @since 3.7.0
         */
        this.totalComplete = 0;

        /**
         * The current state of the Loader.
         *
         * @name Phaser.Loader.LoaderPlugin#state
         * @type {integer}
         * @readOnly
         * @since 3.0.0
         */
        this.state = CONST.LOADER_IDLE;

        scene.sys.events.once('boot', this.boot, this);
        scene.sys.events.on('start', this.pluginStart, this);
    },

    /**
     * This method is called automatically, only once, when the Scene is first created.
     * Do not invoke it directly.
     *
     * @method Phaser.Loader.LoaderPlugin#boot
     * @private
     * @since 3.5.1
     */
    boot: function ()
    {
        this.systems.events.once('destroy', this.destroy, this);
    },

    /**
     * This method is called automatically by the Scene when it is starting up.
     * It is responsible for creating local systems, properties and listening for Scene events.
     * Do not invoke it directly.
     *
     * @method Phaser.Loader.LoaderPlugin#pluginStart
     * @private
     * @since 3.5.1
     */
    pluginStart: function ()
    {
        this.systems.events.once('shutdown', this.shutdown, this);
    },

    /**
     * If you want to append a URL before the path of any asset you can set this here.
     *
     * Useful if allowing the asset base url to be configured outside of the game code.
     *
     * Once a base URL is set it will affect every file loaded by the Loader from that point on. It does _not_ change any
     * file _already_ being loaded. To reset it, call this method with no arguments.
     *
     * @method Phaser.Loader.LoaderPlugin#setBaseURL
     * @since 3.0.0
     *
     * @param {string} [url] - The URL to use. Leave empty to reset.
     *
     * @return {Phaser.Loader.LoaderPlugin} This Loader object.
     */
    setBaseURL: function (url)
    {
        if (url === undefined) { url = ''; }

        if (url !== '' && url.substr(-1) !== '/')
        {
            url = url.concat('/');
        }

        this.baseURL = url;

        return this;
    },

    /**
     * The value of `path`, if set, is placed before any _relative_ file path given. For example:
     *
     * ```javascript
     * this.load.setPath("images/sprites/");
     * this.load.image("ball", "ball.png");
     * this.load.image("tree", "level1/oaktree.png");
     * this.load.image("boom", "http://server.com/explode.png");
     * ```
     *
     * Would load the `ball` file from `images/sprites/ball.png` and the tree from
     * `images/sprites/level1/oaktree.png` but the file `boom` would load from the URL
     * given as it's an absolute URL.
     *
     * Please note that the path is added before the filename but *after* the baseURL (if set.)
     *
     * Once a path is set it will then affect every file added to the Loader from that point on. It does _not_ change any
     * file _already_ in the load queue. To reset it, call this method with no arguments.
     *
     * @method Phaser.Loader.LoaderPlugin#setPath
     * @since 3.0.0
     *
     * @param {string} [path] - The path to use. Leave empty to reset.
     *
     * @return {Phaser.Loader.LoaderPlugin} This Loader object.
     */
    setPath: function (path)
    {
        if (path === undefined) { path = ''; }

        if (path !== '' && path.substr(-1) !== '/')
        {
            path = path.concat('/');
        }

        this.path = path;

        return this;
    },

    /**
     * An optional prefix that is automatically prepended to the start of every file key.
     *
     * If prefix was `MENU.` and you load an image with the key 'Background' the resulting key would be `MENU.Background`.
     *
     * Once a prefix is set it will then affect every file added to the Loader from that point on. It does _not_ change any
     * file _already_ in the load queue. To reset it, call this method with no arguments.
     *
     * @method Phaser.Loader.LoaderPlugin#setPrefix
     * @since 3.7.0
     *
     * @param {string} [prefix] - The prefix to use. Leave empty to reset.
     *
     * @return {Phaser.Loader.LoaderPlugin} This Loader object.
     */
    setPrefix: function (prefix)
    {
        if (prefix === undefined) { prefix = ''; }

        this.prefix = prefix;

        return this;
    },

    /**
     * Sets the Cross Origin Resource Sharing value used when loading files.
     *
     * Files can override this value on a per-file basis by specifying an alternative `crossOrigin` value in their file config.
     *
     * Once CORs is set it will then affect every file loaded by the Loader from that point on, as long as they don't have
     * their own CORs setting. To reset it, call this method with no arguments.
     *
     * For more details about CORs see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
     *
     * @method Phaser.Loader.LoaderPlugin#setCORS
     * @since 3.0.0
     *
     * @param {string} [crossOrigin] - The value to use for the `crossOrigin` property in the load request.
     *
     * @return {Phaser.Loader.LoaderPlugin} This Loader object.
     */
    setCORS: function (crossOrigin)
    {
        this.crossOrigin = crossOrigin;

        return this;
    },

    /**
     * This event is fired when a Loader successfully begins to load its queue.
     *
     * @event Phaser.Loader.LoaderPlugin#addFileEvent
     * @param {string} key - The key of the file that was added.
     * @param {string} type - The type of the file that was added.
     * @param {Phaser.Loader.LoaderPlugin} loader - The Loader that had the file added to it.
     * @param {Phaser.Loader.File} loader - The File object that was added to the Loader.
     */

    /**
     * Adds a file, or array of files, into the load queue.
     *
     * The file must be an instance of `Phaser.Loader.File`, or a class that extends it. The Loader will check that the key
     * used by the file won't conflict with any other key either in the loader, the inflight queue or the target cache.
     * If allowed it will then add the file into the pending list, read for the load to start. Or, if the load has already
     * started, ready for the next batch of files to be pulled from the list to the inflight queue.
     *
     * You should not normally call this method directly, but rather use one of the Loader methods like `image` or `atlas`,
     * however you can call this as long as the file given to it is well formed.
     *
     * @method Phaser.Loader.LoaderPlugin#addFile
     * @fires Phaser.Loader.LoaderPlugin#addFileEvent
     * @since 3.0.0
     *
     * @param {(Phaser.Loader.File|Phaser.Loader.File[])} file - The file, or array of files, to be added to the load queue.
     */
    addFile: function (file)
    {
        if (!Array.isArray(file))
        {
            file = [ file ];
        }

        for (var i = 0; i < file.length; i++)
        {
            var item = file[i];

            //  Does the file already exist in the cache or texture manager?
            //  Or will it conflict with a file already in the queue or inflight?
            if (!this.keyExists(item))
            {
                this.list.set(item);

                this.emit('addfile', item.key, item.type, this, item);

                if (this.isLoading())
                {
                    this.totalToLoad++;
                    this.updateProgress();
                }
            }
        }
    },

    /**
     * Checks the key and type of the given file to see if it will conflict with anything already
     * in a Cache, the Texture Manager, or the list or inflight queues.
     *
     * @method Phaser.Loader.LoaderPlugin#keyExists
     * @since 3.7.0
     *
     * @param {Phaser.Loader.File} file - The file to check the key of.
     *
     * @return {boolean} `true` if adding this file will cause a cache or queue conflict, otherwise `false`.
     */
    keyExists: function (file)
    {
        var keyConflict = file.hasCacheConflict();

        if (!keyConflict)
        {
            this.list.iterate(function (item)
            {
                if (item.type === file.type && item.key === file.key)
                {
                    keyConflict = true;

                    return false;
                }

            });
        }

        if (!keyConflict && this.isLoading())
        {
            this.inflight.iterate(function (item)
            {
                if (item.type === file.type && item.key === file.key)
                {
                    keyConflict = true;

                    return false;
                }

            });

            this.queue.iterate(function (item)
            {
                if (item.type === file.type && item.key === file.key)
                {
                    keyConflict = true;

                    return false;
                }

            });
        }

        return keyConflict;
    },

    /**
     * Takes a well formed, fully parsed pack file object and adds its entries into the load queue. Usually you do not call
     * this method directly, but instead use `Loader.pack` and supply a path to a JSON file that holds the
     * pack data. However, if you've got the data prepared you can pass it to this method.
     *
     * You can also provide an optional key. If you do then it will only add the entries from that part of the pack into
     * to the load queue. If not specified it will add all entries it finds. For more details about the pack file format
     * see the `LoaderPlugin.pack` method.
     *
     * @method Phaser.Loader.LoaderPlugin#addPack
     * @since 3.7.0
     *
     * @param {any} data - The Pack File data to be parsed and each entry of it to added to the load queue.
     * @param {string} [packKey] - An optional key to use from the pack file data.
     *
     * @return {boolean} `true` if any files were added to the queue, otherwise `false`.
     */
    addPack: function (pack, packKey)
    {
        //  if no packKey provided we'll add everything to the queue
        if (packKey && pack.hasOwnProperty(packKey))
        {
            pack = { packKey: pack[packKey] };
        }

        var total = 0;

        //  Store the loader settings in case this pack replaces them
        var currentBaseURL = this.baseURL;
        var currentPath = this.path;
        var currentPrefix = this.prefix;

        //  Here we go ...
        for (var key in pack)
        {
            var config = pack[key];

            //  Any meta data to process?
            var baseURL = GetFastValue(config, 'baseURL', currentBaseURL);
            var path = GetFastValue(config, 'path', currentPath);
            var prefix = GetFastValue(config, 'prefix', currentPrefix);
            var files = GetFastValue(config, 'files', null);
            var defaultType = GetFastValue(config, 'defaultType', 'void');

            if (Array.isArray(files))
            {
                this.setBaseURL(baseURL);
                this.setPath(path);
                this.setPrefix(prefix);

                for (var i = 0; i < files.length; i++)
                {
                    var file = files[i];
                    var type = (file.hasOwnProperty('type')) ? file.type : defaultType;

                    if (this[type])
                    {
                        this[type](file);
                        total++;
                    }
                }
            }
        }

        //  Reset the loader settings
        this.setBaseURL(currentBaseURL);
        this.setPath(currentPath);
        this.setPrefix(currentPrefix);

        return (total > 0);
    },

    /**
     * Is the Loader actively loading, or processing loaded files?
     *
     * @method Phaser.Loader.LoaderPlugin#isLoading
     * @since 3.0.0
     *
     * @return {boolean} `true` if the Loader is busy loading or processing, otherwise `false`.
     */
    isLoading: function ()
    {
        return (this.state === CONST.LOADER_LOADING || this.state === CONST.LOADER_PROCESSING);
    },

    /**
     * Is the Loader ready to start a new load?
     *
     * @method Phaser.Loader.LoaderPlugin#isReady
     * @since 3.0.0
     *
     * @return {boolean} `true` if the Loader is ready to start a new load, otherwise `false`.
     */
    isReady: function ()
    {
        return (this.state === CONST.LOADER_IDLE || this.state === CONST.LOADER_COMPLETE);
    },

    /**
     * This event is fired when a Loader successfully begins to load its queue.
     *
     * @event Phaser.Loader.LoaderPlugin#startEvent
     * @param {Phaser.Loader.LoaderPlugin} loader - The Loader instance that started.
     */

    /**
     * Starts the Loader running. This will reset the progress and totals and then emit a `start` event.
     * If there is nothing in the queue the Loader will immediately complete, otherwise it will start
     * loading the first batch of files.
     *
     * The Loader is started automatically if the queue is populated within your Scenes `preload` method.
     *
     * However, outside of this, you need to call this method to start it.
     *
     * If the Loader is already running this method will simply return.
     *
     * @method Phaser.Loader.LoaderPlugin#start
     * @fires Phaser.Loader.LoaderPlugin#startEvent
     * @since 3.0.0
     */
    start: function ()
    {
        if (!this.isReady())
        {
            return;
        }

        this.progress = 0;

        this.totalFailed = 0;
        this.totalComplete = 0;
        this.totalToLoad = this.list.size;

        this.emit('start', this);

        if (this.list.size === 0)
        {
            this.loadComplete();
        }
        else
        {
            this.state = CONST.LOADER_LOADING;

            this.inflight.clear();
            this.queue.clear();

            this.updateProgress();

            this.checkLoadQueue();

            this.systems.events.on('update', this.update, this);
        }
    },

    /**
     * This event is fired when the Loader updates its progress, typically as a result of
     * a file having completed loading.
     *
     * @event Phaser.Loader.LoaderPlugin#progressEvent
     * @param {number} progress - The current progress of the load. A value between 0 and 1.
     */

    /**
     * Called automatically during the load process.
     * It updates the `progress` value and then emits a progress event, which you can use to
     * display a loading bar in your game.
     *
     * @method Phaser.Loader.LoaderPlugin#updateProgress
     * @fires Phaser.Loader.LoaderPlugin#progressEvent
     * @since 3.0.0
     */
    updateProgress: function ()
    {
        this.progress = 1 - ((this.list.size + this.inflight.size) / this.totalToLoad);

        this.emit('progress', this.progress);
    },

    /**
     * Called automatically during the load process.
     *
     * @method Phaser.Loader.LoaderPlugin#update
     * @since 3.10.0
     */
    update: function ()
    {
        if (this.state === CONST.LOADER_LOADING && this.list.size > 0 && this.inflight.size < this.maxParallelDownloads)
        {
            this.checkLoadQueue();
        }
    },

    /**
     * An internal method called by the Loader.
     *
     * It will check to see if there are any more files in the pending list that need loading, and if so it will move
     * them from the list Set into the inflight Set, set their CORs flag and start them loading.
     *
     * It will carrying on doing this for each file in the pending list until it runs out, or hits the max allowed parallel downloads.
     *
     * @method Phaser.Loader.LoaderPlugin#checkLoadQueue
     * @private
     * @since 3.7.0
     */
    checkLoadQueue: function ()
    {
        this.list.each(function (file)
        {
            if (file.state === CONST.FILE_POPULATED || (file.state === CONST.FILE_PENDING && this.inflight.size < this.maxParallelDownloads))
            {
                this.inflight.set(file);

                this.list.delete(file);

                //  If the file doesn't have its own crossOrigin set, we'll use the Loaders (which is undefined by default)
                if (!file.crossOrigin)
                {
                    file.crossOrigin = this.crossOrigin;
                }

                file.load();
            }

            if (this.inflight.size === this.maxParallelDownloads)
            {
                //  Tells the Set iterator to abort
                return false;
            }

        }, this);
    },

    /**
     * This event is fired when the a file successfully completes loading, _before_ it is processed.
     *
     * @event Phaser.Loader.LoaderPlugin#loadEvent
     * @param {Phaser.Loader.File} file - The file that has completed loading.
     */

    /**
     * This event is fired when the a file errors during load.
     *
     * @event Phaser.Loader.LoaderPlugin#loadErrorEvent
     * @param {Phaser.Loader.File} file - The file that has failed to load.
     */

    /**
     * An internal method called automatically by the XHRLoader belong to a File.
     *
     * This method will remove the given file from the inflight Set and update the load progress.
     * If the file was successful its `onProcess` method is called, otherwise it is added to the delete queue.
     *
     * @method Phaser.Loader.LoaderPlugin#nextFile
     * @fires Phaser.Loader.LoaderPlugin#loadEvent
     * @fires Phaser.Loader.LoaderPlugin#loadErrorEvent
     * @since 3.0.0
     *
     * @param {Phaser.Loader.File} file - The File that just finished loading, or errored during load.
     * @param {boolean} success - `true` if the file loaded successfully, otherwise `false`.
     */
    nextFile: function (file, success)
    {
        this.inflight.delete(file);

        this.updateProgress();

        if (success)
        {
            this.totalComplete++;

            this.queue.set(file);

            this.emit('load', file);

            file.onProcess();
        }
        else
        {
            this.totalFailed++;

            this._deleteQueue.set(file);

            this.emit('loaderror', file);

            this.fileProcessComplete(file);
        }
    },

    /**
     * An internal method that is called automatically by the File when it has finished processing.
     *
     * If the process was successful, and the File isn't part of a MultiFile, its `addToCache` method is called.
     *
     * It this then removed from the queue. If there are no more files to load `loadComplete` is called.
     *
     * @method Phaser.Loader.LoaderPlugin#fileProcessComplete
     * @since 3.7.0
     *
     * @param {Phaser.Loader.File} file - The file that has finished processing.
     */
    fileProcessComplete: function (file)
    {
        //  This file has failed, so move it to the failed Set
        if (file.state === CONST.FILE_ERRORED)
        {
            if (file.multiFile)
            {
                file.multiFile.onFileFailed(file);
            }
        }
        else if (file.state === CONST.FILE_COMPLETE)
        {
            if (file.multiFile)
            {
                if (file.multiFile.isReadyToProcess())
                {
                    //  If we got here then all files the link file needs are ready to add to the cache
                    file.multiFile.addToCache();
                }
            }
            else
            {
                //  If we got here, then the file processed, so let it add itself to its cache
                file.addToCache();
            }
        }

        //  Remove it from the queue
        this.queue.delete(file);

        //  Nothing left to do?

        if (this.list.size === 0 && this.inflight.size === 0 && this.queue.size === 0)
        {
            this.loadComplete();
        }
    },

    /**
     * This event is fired when the Loader has finished loading everything and the queue is empty.
     * By this point every loaded file will now be in its associated cache and ready for use.
     *
     * @event Phaser.Loader.LoaderPlugin#completeEvent
     * @param {Phaser.Loader.File} file - The file that has failed to load.
     */

    /**
     * Called at the end when the load queue is exhausted and all files have either loaded or errored.
     * By this point every loaded file will now be in its associated cache and ready for use.
     *
     * Also clears down the Sets, puts progress to 1 and clears the deletion queue.
     *
     * @method Phaser.Loader.LoaderPlugin#loadComplete
     * @fires Phaser.Loader.LoaderPlugin#completeEvent
     * @since 3.7.0
     */
    loadComplete: function ()
    {
        this.emit('loadcomplete', this);

        this.list.clear();
        this.inflight.clear();
        this.queue.clear();

        this.progress = 1;

        this.state = CONST.LOADER_COMPLETE;

        this.systems.events.off('update', this.update, this);

        //  Call 'destroy' on each file ready for deletion
        this._deleteQueue.iterateLocal('destroy');

        this._deleteQueue.clear();

        this.emit('complete', this, this.totalComplete, this.totalFailed);
    },

    /**
     * Adds a File into the pending-deletion queue.
     *
     * @method Phaser.Loader.LoaderPlugin#flagForRemoval
     * @since 3.7.0
     *
     * @param {Phaser.Loader.File} file - The File to be queued for deletion when the Loader completes.
     */
    flagForRemoval: function (file)
    {
        this._deleteQueue.set(file);
    },

    /**
     * Converts the given JSON data into a file that the browser then prompts you to download so you can save it locally.
     *
     * The data must be well formed JSON and ready-parsed, not a JavaScript object.
     *
     * @method Phaser.Loader.LoaderPlugin#saveJSON
     * @since 3.0.0
     *
     * @param {*} data - The JSON data, ready parsed.
     * @param {string} [filename=file.json] - The name to save the JSON file as.
     *
     * @return {Phaser.Loader.LoaderPlugin} This Loader plugin.
     */
    saveJSON: function (data, filename)
    {
        return this.save(JSON.stringify(data), filename);
    },

    /**
     * Causes the browser to save the given data as a file to its default Downloads folder.
     *
     * Creates a DOM level anchor link, assigns it as being a `download` anchor, sets the href
     * to be an ObjectURL based on the given data, and then invokes a click event.
     *
     * @method Phaser.Loader.LoaderPlugin#save
     * @since 3.0.0
     *
     * @param {*} data - The data to be saved. Will be passed through URL.createObjectURL.
     * @param {string} [filename=file.json] - The filename to save the file as.
     * @param {string} [filetype=application/json] - The file type to use when saving the file. Defaults to JSON.
     *
     * @return {Phaser.Loader.LoaderPlugin} This Loader plugin.
     */
    save: function (data, filename, filetype)
    {
        if (filename === undefined) { filename = 'file.json'; }
        if (filetype === undefined) { filetype = 'application/json'; }

        var blob = new Blob([ data ], { type: filetype });

        var url = URL.createObjectURL(blob);

        var a = document.createElement('a');

        a.download = filename;
        a.textContent = 'Download ' + filename;
        a.href = url;
        a.click();

        return this;
    },

    /**
     * Resets the Loader.
     *
     * This will clear all lists and reset the base URL, path and prefix.
     *
     * Warning: If the Loader is currently downloading files, or has files in its queue, they will be aborted.
     *
     * @method Phaser.Loader.LoaderPlugin#reset
     * @since 3.0.0
     */
    reset: function ()
    {
        this.list.clear();
        this.inflight.clear();
        this.queue.clear();

        var gameConfig = this.systems.game.config;
        var sceneConfig = this.systems.settings.loader;

        this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL));
        this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath));
        this.setPrefix(GetFastValue(sceneConfig, 'prefix', gameConfig.loaderPrefix));

        this.state = CONST.LOADER_IDLE;
    },

    /**
     * The Scene that owns this plugin is shutting down.
     * We need to kill and reset all internal properties as well as stop listening to Scene events.
     *
     * @method Phaser.Loader.LoaderPlugin#shutdown
     * @private
     * @since 3.0.0
     */
    shutdown: function ()
    {
        this.reset();

        this.state = CONST.LOADER_SHUTDOWN;

        this.systems.events.off('update', this.update, this);
        this.systems.events.off('shutdown', this.shutdown, this);
    },

    /**
     * The Scene that owns this plugin is being destroyed.
     * We need to shutdown and then kill off all external references.
     *
     * @method Phaser.Loader.LoaderPlugin#destroy
     * @private
     * @since 3.0.0
     */
    destroy: function ()
    {
        this.shutdown();

        this.state = CONST.LOADER_DESTROYED;

        this.systems.events.off('update', this.update, this);
        this.systems.events.off('start', this.pluginStart, this);

        this.list = null;
        this.inflight = null;
        this.queue = null;

        this.scene = null;
        this.systems = null;
        this.textureManager = null;
        this.cacheManager = null;
    }

});

PluginCache.register('Loader', LoaderPlugin, 'load');

module.exports = LoaderPlugin;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * @typedef {object} HSVColorObject
 *
 * @property {number} h - The hue color value. A number between 0 and 1
 * @property {number} s - The saturation color value. A number between 0 and 1
 * @property {number} v - The lightness color value. A number between 0 and 1
 */

/**
 * Converts an RGB color value to HSV (hue, saturation and value).
 * Conversion forumla from http://en.wikipedia.org/wiki/HSL_color_space.
 * Assumes RGB values are contained in the set [0, 255] and returns h, s and v in the set [0, 1].
 * Based on code by Michael Jackson (https://github.com/mjijackson)
 *
 * @function Phaser.Display.Color.RGBToHSV
 * @since 3.0.0
 *
 * @param {integer} r - The red color value. A number between 0 and 255.
 * @param {integer} g - The green color value. A number between 0 and 255.
 * @param {integer} b - The blue color value. A number between 0 and 255.
 * @param {(HSVColorObject|Phaser.Display.Color)} [out] - An object to store the color values in. If not given an HSV Color Object will be created.
 *
 * @return {(HSVColorObject|Phaser.Display.Color)} An object with the properties `h`, `s` and `v` set.
 */
var RGBToHSV = function (r, g, b, out)
{
    if (out === undefined) { out = { h: 0, s: 0, v: 0 }; }

    r /= 255;
    g /= 255;
    b /= 255;

    var min = Math.min(r, g, b);
    var max = Math.max(r, g, b);
    var d = max - min;

    // achromatic by default
    var h = 0;
    var s = (max === 0) ? 0 : d / max;
    var v = max;

    if (max !== min)
    {
        if (max === r)
        {
            h = (g - b) / d + ((g < b) ? 6 : 0);
        }
        else if (max === g)
        {
            h = (b - r) / d + 2;
        }
        else if (max === b)
        {
            h = (r - g) / d + 4;
        }

        h /= 6;
    }

    if (out.hasOwnProperty('_h'))
    {
        out._h = h;
        out._s = s;
        out._v = v;
    }
    else
    {
        out.h = h;
        out.s = s;
        out.v = v;
    }

    return out;
};

module.exports = RGBToHSV;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

//  Contains the plugins that Phaser uses globally and locally.
//  These are the source objects, not instantiated.
var corePlugins = {};

//  Contains the plugins that the dev has loaded into their game
//  These are the source objects, not instantiated.
var customPlugins = {};

/**
 * @typedef {object} CorePluginContainer
 *
 * @property {string} key - The unique name of this plugin in the core plugin cache.
 * @property {function} plugin - The plugin to be stored. Should be the source object, not instantiated.
 * @property {string} [mapping] - If this plugin is to be injected into the Scene Systems, this is the property key map used.
 * @property {boolean} [custom=false] - Core Scene plugin or a Custom Scene plugin?
 */

/**
 * @typedef {object} CustomPluginContainer
 *
 * @property {string} key - The unique name of this plugin in the custom plugin cache.
 * @property {function} plugin - The plugin to be stored. Should be the source object, not instantiated.
 */

var PluginCache = {};

/**
 * Static method called directly by the Core internal Plugins.
 * Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin)
 * Plugin is the object to instantiate to create the plugin
 * Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
 *
 * @method Phaser.Plugins.PluginCache.register
 * @since 3.8.0
 *
 * @param {string} key - A reference used to get this plugin from the plugin cache.
 * @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated.
 * @param {string} mapping - If this plugin is to be injected into the Scene Systems, this is the property key map used.
 * @param {boolean} [custom=false] - Core Scene plugin or a Custom Scene plugin?
 */
PluginCache.register = function (key, plugin, mapping, custom)
{
    if (custom === undefined) { custom = false; }

    corePlugins[key] = { plugin: plugin, mapping: mapping, custom: custom };
};

/**
 * Stores a custom plugin in the global plugin cache.
 * The key must be unique, within the scope of the cache.
 *
 * @method Phaser.Plugins.PluginCache.registerCustom
 * @since 3.8.0
 *
 * @param {string} key - A reference used to get this plugin from the plugin cache.
 * @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated.
 * @param {string} mapping - If this plugin is to be injected into the Scene Systems, this is the property key map used.
 * @param {?any} data - A value to be passed to the plugin's `init` method.
 */
PluginCache.registerCustom = function (key, plugin, mapping, data)
{
    customPlugins[key] = { plugin: plugin, mapping: mapping, data: data };
};

/**
 * Checks if the given key is already being used in the core plugin cache.
 *
 * @method Phaser.Plugins.PluginCache.hasCore
 * @since 3.8.0
 *
 * @param {string} key - The key to check for.
 *
 * @return {boolean} `true` if the key is already in use in the core cache, otherwise `false`.
 */
PluginCache.hasCore = function (key)
{
    return corePlugins.hasOwnProperty(key);
};

/**
 * Checks if the given key is already being used in the custom plugin cache.
 *
 * @method Phaser.Plugins.PluginCache.hasCustom
 * @since 3.8.0
 *
 * @param {string} key - The key to check for.
 *
 * @return {boolean} `true` if the key is already in use in the custom cache, otherwise `false`.
 */
PluginCache.hasCustom = function (key)
{
    return customPlugins.hasOwnProperty(key);
};

/**
 * Returns the core plugin object from the cache based on the given key.
 *
 * @method Phaser.Plugins.PluginCache.getCore
 * @since 3.8.0
 *
 * @param {string} key - The key of the core plugin to get.
 *
 * @return {CorePluginContainer} The core plugin object.
 */
PluginCache.getCore = function (key)
{
    return corePlugins[key];
};

/**
 * Returns the custom plugin object from the cache based on the given key.
 *
 * @method Phaser.Plugins.PluginCache.getCustom
 * @since 3.8.0
 *
 * @param {string} key - The key of the custom plugin to get.
 *
 * @return {CustomPluginContainer} The custom plugin object.
 */
PluginCache.getCustom = function (key)
{
    return customPlugins[key];
};

/**
 * Returns an object from the custom cache based on the given key that can be instantiated.
 *
 * @method Phaser.Plugins.PluginCache.getCustomClass
 * @since 3.8.0
 *
 * @param {string} key - The key of the custom plugin to get.
 *
 * @return {function} The custom plugin object.
 */
PluginCache.getCustomClass = function (key)
{
    return (customPlugins.hasOwnProperty(key)) ? customPlugins[key].plugin : null;
};

/**
 * Removes a core plugin based on the given key.
 *
 * @method Phaser.Plugins.PluginCache.remove
 * @since 3.8.0
 *
 * @param {string} key - The key of the core plugin to remove.
 */
PluginCache.remove = function (key)
{
    if (corePlugins.hasOwnProperty(key))
    {
        delete corePlugins[key];
    }
};

/**
 * Removes a custom plugin based on the given key.
 *
 * @method Phaser.Plugins.PluginCache.removeCustom
 * @since 3.8.0
 *
 * @param {string} key - The key of the custom plugin to remove.
 */
PluginCache.removeCustom = function (key)
{
    if (customPlugins.hasOwnProperty(key))
    {
        delete customPlugins[key];
    }
};

/**
 * Removes all Core Plugins.
 *
 * This includes all of the internal system plugins that Phaser needs, like the Input Plugin and Loader Plugin.
 * So be sure you only call this if you do not wish to run Phaser again.
 *
 * @method Phaser.Plugins.PluginCache.destroyCorePlugins
 * @since 3.12.0
 */
PluginCache.destroyCorePlugins = function ()
{
    for (var key in corePlugins)
    {
        if (corePlugins.hasOwnProperty(key))
        {
            delete corePlugins[key];
        }
    }
};

/**
 * Removes all Custom Plugins.
 *
 * @method Phaser.Plugins.PluginCache.destroyCustomPlugins
 * @since 3.12.0
 */
PluginCache.destroyCustomPlugins = function ()
{
    for (var key in customPlugins)
    {
        if (customPlugins.hasOwnProperty(key))
        {
            delete customPlugins[key];
        }
    }
};

module.exports = PluginCache;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var PropertyValueSet = require('./PropertyValueSet');

/**
 * Takes an array of Game Objects, or any objects that have the public property `depth`
 * and then sets it to the given value.
 *
 * The optional `step` property is applied incrementally, multiplied by each item in the array.
 *
 * To use this with a Group: `SetDepth(group.getChildren(), value, step)`
 *
 * @function Phaser.Actions.SetDepth
 * @since 3.0.0
 *
 * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return]
 *
 * @param {(array|Phaser.GameObjects.GameObject[])} items - The array of items to be updated by this action.
 * @param {number} value - The amount to set the property to.
 * @param {number} [step=0] - This is added to the `value` amount, multiplied by the iteration counter.
 * @param {integer} [index=0] - An optional offset to start searching from within the items array.
 * @param {integer} [direction=1] - The direction to iterate through the array. 1 is from beginning to end, -1 from end to beginning.
 *
 * @return {(array|Phaser.GameObjects.GameObject[])} The array of objects that were passed to this Action.
 */
var SetDepth = function (items, value, step, index, direction)
{
    return PropertyValueSet(items, 'depth', value, step, index, direction);
};

module.exports = SetDepth;


//  This file has failed, so move it to the failed Set

if (!this.scene || !this.systems || !this.systems.game || this.systems.game.pendingDestroy)


/**
* The `Matter.Engine` module contains methods for creating and manipulating engines.
* An engine is a controller that manages updating the simulation of the world.
* See `Matter.Runner` for an optional game loop utility.
*
* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
*
* @class Engine
*/

var Engine = {};

module.exports = Engine;

var World = require('../body/World');
var Sleeping = require('./Sleeping');
var Resolver = require('../collision/Resolver');
var Pairs = require('../collision/Pairs');
var Metrics = require('./Metrics');
var Grid = require('../collision/Grid');
var Events = require('./Events');
var Composite = require('../body/Composite');
var Constraint = require('../constraint/Constraint');
var Common = require('./Common');
var Body = require('../body/Body');

(function() {

    /**
     * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults.
     * All properties have default values, and many are pre-calculated automatically based on other properties.
     * See the properties section below for detailed information on what you can pass via the `options` object.
     * @method create
     * @param {object} [options]
     * @return {engine} engine
     */
    Engine.create = function(element, options) {
        // options may be passed as the first (and only) argument
        options = Common.isElement(element) ? options : element;
        element = Common.isElement(element) ? element : null;
        options = options || {};

        if (element || options.render) {
            Common.warn('Engine.create: engine.render is deprecated (see docs)');
        }

        var defaults = {
            positionIterations: 6,
            velocityIterations: 4,
            constraintIterations: 2,
            enableSleeping: false,
            events: [],
            plugin: {},
            timing: {
                timestamp: 0,
                timeScale: 1
            },
            broadphase: {
                controller: Grid
            }
        };

        var engine = Common.extend(defaults, options);

        // @deprecated
        if (element || engine.render) {
            var renderDefaults = {
                element: element,
                controller: Render
            };

            engine.render = Common.extend(renderDefaults, engine.render);
        }

        // @deprecated
        if (engine.render && engine.render.controller) {
            engine.render = engine.render.controller.create(engine.render);
        }

        // @deprecated
        if (engine.render) {
            engine.render.engine = engine;
        }

        engine.world = options.world || World.create(engine.world);
        engine.pairs = Pairs.create();
        engine.broadphase = engine.broadphase.controller.create(engine.broadphase);
        engine.metrics = engine.metrics || { extended: false };

        // @if DEBUG
        engine.metrics = Metrics.create(engine.metrics);
        // @endif

        return engine;
    };

    /**
     * Moves the simulation forward in time by `delta` ms.
     * The `correction` argument is an optional `Number` that specifies the time correction factor to apply to the update.
     * This can help improve the accuracy of the simulation in cases where `delta` is changing between updates.
     * The value of `correction` is defined as `delta / lastDelta`, i.e. the percentage change of `delta` over the last step.
     * Therefore the value is always `1` (no correction) when `delta` constant (or when no correction is desired, which is the default).
     * See the paper on Time Corrected Verlet for more information.
     *
     * Triggers `beforeUpdate` and `afterUpdate` events.
     * Triggers `collisionStart`, `collisionActive` and `collisionEnd` events.
     * @method update
     * @param {engine} engine
     * @param {number} [delta=16.666]
     * @param {number} [correction=1]
     */
    Engine.update = function(engine, delta, correction) {
        delta = delta || 1000 / 60;
        correction = correction || 1;

        var world = engine.world,
            timing = engine.timing,
            broadphase = engine.broadphase,
            broadphasePairs = [],
            i;

        // increment timestamp
        timing.timestamp += delta * timing.timeScale;

        // create an event object
        var event = {
            timestamp: timing.timestamp
        };

        Events.trigger(engine, 'beforeUpdate', event);

        // get lists of all bodies and constraints, no matter what composites they are in
        var allBodies = Composite.allBodies(world),
            allConstraints = Composite.allConstraints(world);

        // @if DEBUG
        // reset metrics logging
        Metrics.reset(engine.metrics);
        // @endif

        // if sleeping enabled, call the sleeping controller
        if (engine.enableSleeping)
            Sleeping.update(allBodies, timing.timeScale);

        // applies gravity to all bodies
        Engine._bodiesApplyGravity(allBodies, world.gravity);

        // update all body position and rotation by integration
        Engine._bodiesUpdate(allBodies, delta, timing.timeScale, correction, world.bounds);

        // update all constraints (first pass)
        Constraint.preSolveAll(allBodies);
        for (i = 0; i < engine.constraintIterations; i++) {
            Constraint.solveAll(allConstraints, timing.timeScale);
        }
        Constraint.postSolveAll(allBodies);

        // broadphase pass: find potential collision pairs
        if (broadphase.controller) {
            // if world is dirty, we must flush the whole grid
            if (world.isModified)
                broadphase.controller.clear(broadphase);

            // update the grid buckets based on current bodies
            broadphase.controller.update(broadphase, allBodies, engine, world.isModified);
            broadphasePairs = broadphase.pairsList;
        } else {
            // if no broadphase set, we just pass all bodies
            broadphasePairs = allBodies;
        }

        // clear all composite modified flags
        if (world.isModified) {
            Composite.setModified(world, false, false, true);
        }

        // narrowphase pass: find actual collisions, then create or update collision pairs
        var collisions = broadphase.detector(broadphasePairs, engine);

        // update collision pairs
        var pairs = engine.pairs,
            timestamp = timing.timestamp;
        Pairs.update(pairs, collisions, timestamp);
        Pairs.removeOld(pairs, timestamp);

        // wake up bodies involved in collisions
        if (engine.enableSleeping)
            Sleeping.afterCollisions(pairs.list, timing.timeScale);

        // trigger collision events
        if (pairs.collisionStart.length > 0)
            Events.trigger(engine, 'collisionStart', { pairs: pairs.collisionStart });

        // iteratively resolve position between collisions
        Resolver.preSolvePosition(pairs.list);
        for (i = 0; i < engine.positionIterations; i++) {
            Resolver.solvePosition(pairs.list, allBodies, timing.timeScale);
        }
        Resolver.postSolvePosition(allBodies);

        // update all constraints (second pass)
        Constraint.preSolveAll(allBodies);
        for (i = 0; i < engine.constraintIterations; i++) {
            Constraint.solveAll(allConstraints, timing.timeScale);
        }
        Constraint.postSolveAll(allBodies);

        // iteratively resolve velocity between collisions
        Resolver.preSolveVelocity(pairs.list);
        for (i = 0; i < engine.velocityIterations; i++) {
            Resolver.solveVelocity(pairs.list, timing.timeScale);
        }

        // trigger collision events
        if (pairs.collisionActive.length > 0)
            Events.trigger(engine, 'collisionActive', { pairs: pairs.collisionActive });

        if (pairs.collisionEnd.length > 0)
            Events.trigger(engine, 'collisionEnd', { pairs: pairs.collisionEnd });

        // @if DEBUG
        // update metrics log
        Metrics.update(engine.metrics, engine);
        // @endif

        // clear force buffers
        Engine._bodiesClearForces(allBodies);

        Events.trigger(engine, 'afterUpdate', event);

        return engine;
    };

    /**
     * Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`.
     * @method merge
     * @param {engine} engineA
     * @param {engine} engineB
     */
    Engine.merge = function(engineA, engineB) {
        Common.extend(engineA, engineB);

        if (engineB.world) {
            engineA.world = engineB.world;

            Engine.clear(engineA);

            var bodies = Composite.allBodies(engineA.world);

            for (var i = 0; i < bodies.length; i++) {
                var body = bodies[i];
                Sleeping.set(body, false);
                body.id = Common.nextId();
            }
        }
    };

    /**
     * Clears the engine including the world, pairs and broadphase.
     * @method clear
     * @param {engine} engine
     */
    Engine.clear = function(engine) {
        var world = engine.world;

        Pairs.clear(engine.pairs);

        var broadphase = engine.broadphase;
        if (broadphase.controller) {
            var bodies = Composite.allBodies(world);
            broadphase.controller.clear(broadphase);
            broadphase.controller.update(broadphase, bodies, engine, true);
        }
    };

    /**
     * Zeroes the `body.force` and `body.torque` force buffers.
     * @method _bodiesClearForces
     * @private
     * @param {body[]} bodies
     */
    Engine._bodiesClearForces = function(bodies) {
        for (var i = 0; i < bodies.length; i++) {
            var body = bodies[i];

            // reset force buffers
            body.force.x = 0;
            body.force.y = 0;
            body.torque = 0;
        }
    };

    /**
     * Applys a mass dependant force to all given bodies.
     * @method _bodiesApplyGravity
     * @private
     * @param {body[]} bodies
     * @param {vector} gravity
     */
    Engine._bodiesApplyGravity = function(bodies, gravity) {
        var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001;

        if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) {
            return;
        }

        for (var i = 0; i < bodies.length; i++) {
            var body = bodies[i];

            if (body.ignoreGravity || body.isStatic || body.isSleeping)
                continue;

            // apply gravity
            body.force.y += body.mass * gravity.y * gravityScale;
            body.force.x += body.mass * gravity.x * gravityScale;
        }
    };

    /**
     * Applys `Body.update` to all given `bodies`.
     * @method _bodiesUpdate
     * @private
     * @param {body[]} bodies
     * @param {number} deltaTime
     * The amount of time elapsed between updates
     * @param {number} timeScale
     * @param {number} correction
     * The Verlet correction factor (deltaTime / lastDeltaTime)
     * @param {bounds} worldBounds
     */
    Engine._bodiesUpdate = function(bodies, deltaTime, timeScale, correction, worldBounds) {
        for (var i = 0; i < bodies.length; i++) {
            var body = bodies[i];

            if (body.isStatic || body.isSleeping)
                continue;

            Body.update(body, deltaTime, timeScale, correction);
        }
    };

    /**
     * An alias for `Runner.run`, see `Matter.Runner` for more information.
     * @method run
     * @param {engine} engine
     */

    /**
    * Fired just before an update
    *
    * @event beforeUpdate
    * @param {} event An event object
    * @param {number} event.timestamp The engine.timing.timestamp of the event
    * @param {} event.source The source object of the event
    * @param {} event.name The name of the event
    */

    /**
    * Fired after engine update and all collision events
    *
    * @event afterUpdate
    * @param {} event An event object
    * @param {number} event.timestamp The engine.timing.timestamp of the event
    * @param {} event.source The source object of the event
    * @param {} event.name The name of the event
    */

    /**
    * Fired after engine update, provides a list of all pairs that have started to collide in the current tick (if any)
    *
    * @event collisionStart
    * @param {} event An event object
    * @param {} event.pairs List of affected pairs
    * @param {number} event.timestamp The engine.timing.timestamp of the event
    * @param {} event.source The source object of the event
    * @param {} event.name The name of the event
    */

    /**
    * Fired after engine update, provides a list of all pairs that are colliding in the current tick (if any)
    *
    * @event collisionActive
    * @param {} event An event object
    * @param {} event.pairs List of affected pairs
    * @param {number} event.timestamp The engine.timing.timestamp of the event
    * @param {} event.source The source object of the event
    * @param {} event.name The name of the event
    */

    /**
    * Fired after engine update, provides a list of all pairs that have ended collision in the current tick (if any)
    *
    * @event collisionEnd
    * @param {} event An event object
    * @param {} event.pairs List of affected pairs
    * @param {number} event.timestamp The engine.timing.timestamp of the event
    * @param {} event.source The source object of the event
    * @param {} event.name The name of the event
    */

    /*
    *
    *  Properties Documentation
    *
    */

    /**
     * An integer `Number` that specifies the number of position iterations to perform each update.
     * The higher the value, the higher quality the simulation will be at the expense of performance.
     *
     * @property positionIterations
     * @type number
     * @default 6
     */

    /**
     * An integer `Number` that specifies the number of velocity iterations to perform each update.
     * The higher the value, the higher quality the simulation will be at the expense of performance.
     *
     * @property velocityIterations
     * @type number
     * @default 4
     */

    /**
     * An integer `Number` that specifies the number of constraint iterations to perform each update.
     * The higher the value, the higher quality the simulation will be at the expense of performance.
     * The default value of `2` is usually very adequate.
     *
     * @property constraintIterations
     * @type number
     * @default 2
     */

    /**
     * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module.
     * Sleeping can improve stability and performance, but often at the expense of accuracy.
     *
     * @property enableSleeping
     * @type boolean
     * @default false
     */

    /**
     * An `Object` containing properties regarding the timing systems of the engine.
     *
     * @property timing
     * @type object
     */

    /**
     * A `Number` that specifies the global scaling factor of time for all bodies.
     * A value of `0` freezes the simulation.
     * A value of `0.1` gives a slow-motion effect.
     * A value of `1.2` gives a speed-up effect.
     *
     * @property timing.timeScale
     * @type number
     * @default 1
     */

    /**
     * A `Number` that specifies the current simulation-time in milliseconds starting from `0`.
     * It is incremented on every `Engine.update` by the given `delta` argument.
     *
     * @property timing.timestamp
     * @type number
     * @default 0
     */

    /**
     * An instance of a `Render` controller. The default value is a `Matter.Render` instance created by `Engine.create`.
     * One may also develop a custom renderer module based on `Matter.Render` and pass an instance of it to `Engine.create` via `options.render`.
     *
     * A minimal custom renderer object must define at least three functions: `create`, `clear` and `world` (see `Matter.Render`).
     * It is also possible to instead pass the _module_ reference via `options.render.controller` and `Engine.create` will instantiate one for you.
     *
     * @property render
     * @type render
     * @deprecated see Demo.js for an example of creating a renderer
     * @default a Matter.Render instance
     */

    /**
     * An instance of a broadphase controller. The default value is a `Matter.Grid` instance created by `Engine.create`.
     *
     * @property broadphase
     * @type grid
     * @default a Matter.Grid instance
     */

    /**
     * A `World` composite object that will contain all simulated bodies and constraints.
     *
     * @property world
     * @type world
     * @default a Matter.World instance
     */

    /**
     * An object reserved for storing plugin-specific properties.
     *
     * @property plugin
     * @type {}
     */

})();


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

/**
 * Exponential ease-in.
 *
 * @function Phaser.Math.Easing.Expo.In
 * @since 3.0.0
 *
 * @param {number} v - The value to be tweened.
 *
 * @return {number} The tweened value.
 */
var In = function (v)
{
    return Math.pow(2, 10 * (v - 1)) - 0.001;
};

module.exports = In;


/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2018 Photon Storm Ltd.
 * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
 */

var Color = require('./Color');
var HueToComponent = require('./HueToComponent');

/**
 * Converts HSL (hue, saturation and lightness) values to a Phaser Color object.
 *
 * @function Phaser.Display.Color.HSLToColor
 * @since 3.0.0
 *
 * @param {number} h - The hue value in the range 0 to 1.
 * @param {number} s - The saturation value in the range 0 to 1.
 * @param {number} l - The lightness value in the range 0 to 1.
 *
 * @return {Phaser.Display.Color} A Color object created from the results of the h, s and l values.
 */
var HSLToColor = function (h, s, l)
{
    // achromatic by default
    var r = l;
    var g = l;
    var b = l;

    if (s !== 0)
    {
        var q = (l < 0.5) ? l * (1 + s) : l + s - l * s;
        var p = 2 * l - q;

        r = HueToComponent(p, q, h + 1 / 3);
        g = HueToComponent(p, q, h);
        b = HueToComponent(p, q, h - 1 / 3);
    }

    var color = new Color();

    return color.setGLTo(r, g, b, 1);
};

module.exports = HSLToColor;


keep keep keep add keep keep keep keep keep

'--rule': 'inspect a specific module rule',

'--plugin': 'inspect a specific plugin',

let patched = false
function patchWebpackChain () {
  if (patched) return

  const Config = require('webpack-chain')

  const toConfig = Config.prototype.toConfig
  Config.prototype.toConfig = function () {
    const config = toConfig.call(this)

    // inject plugin metadata
    const { entries: plugins, order: pluginNames } = this.plugins.order()
    config.plugins.forEach((p, i) => {
      Object.defineProperties(p, {
        __pluginName: {
          value: pluginNames[i]
        },
        __pluginArgs: {
          value: plugins[pluginNames[i]].get('args')
        }
      })
    })

    // inject rule metadata
    const { entries: rules, order: ruleNames } = this.module.rules.order()
    config.module.rules.forEach((rawRule, i) => {
      const ruleName = ruleNames[i]
      const rule = rules[ruleName]
      Object.defineProperties(rawRule, {
        __ruleName: {
          value: ruleName
        }
      })

      if (rawRule.oneOf) {
        const { entries: oneOfs, order: oneOfNames } = rule.oneOfs.order()
        rawRule.oneOf.forEach((o, i) => {
          const oneOfName = oneOfNames[i]
          const oneOf = oneOfs[oneOfName]
          Object.defineProperties(o, {
            __ruleName: {
              value: ruleName
            },
            __oneOfName: {
              value: oneOfName
            }
          })
          patchUse(oneOf, ruleName, oneOfName, o)
        })
      }

      patchUse(rule, ruleName, null, rawRule)
    })

    return config
  }

  patched = true
}

function patchUse (rule, ruleName, oneOfName, rawRule) {
  if (Array.isArray(rawRule.use)) {
    const { order: useNames } = rule.uses.order()
    rawRule.use.forEach((use, i) => {
      Object.defineProperties(use, {
        __ruleName: {
          value: ruleName
        },
        __oneOfName: {
          value: oneOfName
        },
        __useName: {
          value: useNames[i]
        }
      })
    })
  }
}

module.exports = (api, options) => {
  api.registerCommand('inspect', {
    description: 'inspect internal webpack config',
    usage: 'vue-cli-service inspect [options] [...paths]',
    options: {
      '--mode': 'specify env mode (default: development)',
      '--verbose': 'show full function definitions in output'
    }
  }, args => {
    patchWebpackChain()

    const get = require('get-value')
    const stringify = require('javascript-stringify')
    const config = api.resolveWebpackConfig()
    const paths = args._

    let res
    if (paths.length > 1) {
      res = {}
      paths.forEach(path => {
        res[path] = get(config, path)
      })
    } else if (paths.length === 1) {
      res = get(config, paths[0])
    } else {
      res = config
    }

    const pluginRE = /(?:function|class) (\w+Plugin)/
    console.log(stringify(res, (value, indent, stringify) => {
      // shorten long functions
      if (
        !args.verbose &&
        typeof value === 'function' &&
        value.toString().length > 100
      ) {
        return `function () { /* omitted long function */ }`
      }

      // improve plugin output
      if (value && value.__pluginName) {
        let match = (
          value.constructor &&
          value.constructor.toString().match(pluginRE)
        )
        // copy-webpack-plugin
        if (value.__pluginName === 'copy') {
          match = [null, `CopyWebpackPlugin`]
        }
        const name = match[1]
        const prefix = `/* config.plugin('${value.__pluginName}') */\n`

        if (name) {
          return prefix + `new ${name}(${
            value.__pluginArgs.map(arg => stringify(arg)).join(',\n')
          })`
        } else {
          return prefix + stringify({
            args: value.__pluginArgs || []
          })
        }
      }

      // improve rule output
      if (value && value.__ruleName) {
        const prefix = `/* config.module.rule('${value.__ruleName}')${
          value.__oneOfName ? `.oneOf('${value.__oneOfName}')` : ``
        }${
          value.__useName ? `.use('${value.__useName}')` : ``
        } */\n`
        return prefix + stringify(value)
      }

      return stringify(value)
    }, 2))
  })
}

module.exports.defaultModes = {
  inspect: 'development'
}


module.exports = class PromptModuleAPI {
  constructor (creator) {
    this.creator = creator
  }

  injectFeature (feature) {
    this.creator.featurePrompt.choices.push(feature)
  }

  injectPrompt (prompt) {
    this.creator.injectedPrompts.push(prompt)
  }

  injectOptionForPrompt (name, option) {
    this.creator.injectedPrompts.find(f => {
      return f.name === name
    }).choices.push(option)
  }

  onPromptComplete (cb) {
    this.creator.promptCompleteCbs.push(cb)
  }
}


module.exports = function fetchRemotePreset (name, clone) {
  // github shorthand fastpath
  if (!clone && /^[\w_-]+\/[\w_-]+$/.test(name)) {
    const { get } = require('./request')
    return get(`https://raw.githubusercontent.com/${name}/master/preset.json`)
      .then(res => res.body)
  }

  // fallback to full download
  const os = require('os')
  const path = require('path')
  const download = require('download-git-repo')
  const tmpdir = path.join(os.tmpdir(), 'vue-cli')

  return new Promise((resolve, reject) => {
    download(name, tmpdir, { clone }, err => {
      if (err) return reject(err)
      let preset
      try {
        preset = require(path.join(tmpdir, 'preset.json'))
      } catch (e) {
        return reject(e)
      }
      resolve(preset)
    })
  })
}


const defaults = {
  target: 'app',
  entry: 'src/App.vue'
}

const buildModes = {
  lib: 'library (commonjs + umd)',
  wc: 'web component',
  'wc-async': 'web component (async)'
}

module.exports = (api, options) => {
  api.registerCommand('build', {
    description: 'build for production',
    usage: 'vue-cli-service build [options] [entry|pattern]',
    options: {
      '--mode': `specify env mode (default: production)`,
      '--dest': `specify output directory (default: ${options.outputDir})`,
      '--target': `app | lib | wc | wc-async (default: ${defaults.target})`,
      '--name': `name for lib or web-component mode (default: "name" in package.json or entry filename)`
    }
  }, async function build (args) {
    args.entry = args.entry || args._[0]
    for (const key in defaults) {
      if (args[key] == null) {
        args[key] = defaults[key]
      }
    }

    const fs = require('fs-extra')
    const path = require('path')
    const chalk = require('chalk')
    const webpack = require('webpack')
    const formatStats = require('./formatStats')
    const {
      log,
      done,
      info,
      logWithSpinner,
      stopSpinner
    } = require('@vue/cli-shared-utils')

    log()
    const mode = api.service.mode
    if (args.target === 'app') {
      logWithSpinner(`Building for ${mode}...`)
    } else {
      const buildMode = buildModes[args.target]
      if (buildMode) {
        logWithSpinner(`Building for ${mode} as ${buildMode}...`)
      } else {
        throw new Error(`Unknown build target: ${args.target}`)
      }
    }

    const targetDir = api.resolve(args.dest || options.outputDir)

    // respect inline build destination in copy plugin
    if (args.dest) {
      api.chainWebpack(config => {
        if (args.target === 'app') {
          config.plugin('copy').tap(args => {
            args[0][0].to = targetDir
            return args
          })
        }
      })
    }

    // resolve raw webpack config
    let webpackConfig
    if (args.target === 'lib') {
      webpackConfig = require('./resolveLibConfig')(api, args, options)
    } else if (
      args.target === 'wc' ||
      args.target === 'wc-async'
    ) {
      webpackConfig = require('./resolveWcConfig')(api, args, options)
    } else {
      webpackConfig = api.resolveWebpackConfig()
    }

    // apply inline dest path after user configureWebpack hooks
    // so it takes higher priority
    if (args.dest) {
      const applyDest = config => {
        config.output.path = targetDir
      }
      if (Array.isArray(webpackConfig)) {
        webpackConfig.forEach(applyDest)
      } else {
        applyDest(webpackConfig)
      }
    }

    // grab the actual output path and check for common mis-configuration
    const actualTargetDir = (
      Array.isArray(webpackConfig)
        ? webpackConfig[0]
        : webpackConfig
    ).output.path

    if (!args.dest && actualTargetDir !== api.resolve(options.outputDir)) {
      // user directly modifys output.path in configureWebpack or chainWebpack.
      // this is not supported because there's no way for us to give copy
      // plugin the correct value this way.
      console.error(chalk.red(
        `\n\nConfiguration Error: ` +
        `Avoid modifying webpack output.path directly. ` +
        `Use the "outputDir" option instead.\n`
      ))
      process.exit(1)
    }

    if (actualTargetDir === api.service.context) {
      console.error(chalk.red(
        `\n\nConfiguration Error: ` +
        `Do not set output directory to project root.\n`
      ))
      process.exit(1)
    }

    await fs.remove(targetDir)

    return new Promise((resolve, reject) => {
      webpack(webpackConfig, (err, stats) => {
        stopSpinner(false)
        if (err) {
          return reject(err)
        }

        if (stats.hasErrors()) {
          return reject(`Build failed with errors.`)
        }

        if (!args.silent) {
          const targetDirShort = path.relative(
            api.service.context,
            targetDir
          )
          log(formatStats(stats, targetDirShort, api))
          if (args.target === 'app') {
            done(`Build complete. The ${chalk.cyan(targetDirShort)} directory is ready to be deployed.\n`)
            if (
              options.baseUrl === '/' &&
              // only log the tips if this is the first build
              !fs.existsSync(api.resolve('node_modules/.cache'))
            ) {
              info(`The app is built assuming that it will be deployed at the root of a domain.`)
              info(`If you intend to deploy it under a subpath, update the ${chalk.green('baseUrl')} option`)
              info(`in your project config (${chalk.cyan(`vue.config.js`)} or ${chalk.green('"vue"')} field in ${chalk.cyan(`package.json`)}).\n`)
            }
          }
        }

        // test-only signal
        if (process.env.VUE_CLI_TEST) {
          console.log('Build complete.')
        }

        resolve()
      })
    })
  })
}

module.exports.defaultModes = {
  build: 'production'
}


const config = api.resolveWebpackConfig()

keep keep keep keep replace keep keep keep keep keep

res = config.module.rules.find(r => r.__ruleName === args.rule)

res = config.plugins.find(p => p.__pluginName === args.plugin)

#!/usr/bin/env node

const fs = require('fs')
const path = require('path')
const slash = require('slash')
const chalk = require('chalk')
const semver = require('semver')
const minimist = require('minimist')
const requiredVersion = require('../package.json').engines.node

if (!semver.satisfies(process.version, requiredVersion)) {
  console.log(chalk.red(
    `You are using Node ${process.version}, but this version of vue-cli ` +
    `requires Node ${requiredVersion}.\nPlease upgrade your Node version.`
  ))
  process.exit(1)
}

// enter debug mode when creating test repo
if (
  slash(process.cwd()).indexOf('/packages/test') > 0 && (
    fs.existsSync(path.resolve(process.cwd(), '../@vue')) ||
    fs.existsSync(path.resolve(process.cwd(), '../../@vue'))
  )
) {
  process.env.VUE_CLI_DEBUG = true
}

const program = require('commander')
const loadCommand = require('../lib/util/loadCommand')

program
  .version(require('../package').version)
  .usage('<command> [options]')

program
  .command('create <app-name>')
  .description('create a new project powered by vue-cli-service')
  .option('-p, --preset <presetName>', 'Skip prompts and use saved or remote preset')
  .option('-d, --default', 'Skip prompts and use default preset')
  .option('-i, --inlinePreset <json>', 'Skip prompts and use inline JSON string as preset')
  .option('-m, --packageManager <command>', 'Use specified npm client when installing dependencies')
  .option('-r, --registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
  .option('-g, --git [message]', 'Force / skip git intialization, optionally specify initial commit message')
  .option('-f, --force', 'Overwrite target directory if it exists')
  .option('-c, --clone', 'Use git clone when fetching remote preset')
  .option('-x, --proxy', 'Use specified proxy when creating project')
  .action((name, cmd) => {
    require('../lib/create')(name, cleanArgs(cmd))
  })

program
  .command('add <plugin> [pluginOptions]')
  .allowUnknownOption()
  .description('install a plugin and invoke its generator in an already created project')
  .action((plugin) => {
    require('../lib/add')(plugin, minimist(process.argv.slice(3)))
  })

program
  .command('invoke <plugin> [pluginOptions]')
  .allowUnknownOption()
  .description('invoke the generator of a plugin in an already created project')
  .action((plugin) => {
    require('../lib/invoke')(plugin, minimist(process.argv.slice(3)))
  })

program
  .command('inspect [paths...]')
  .option('--mode <mode>')
  .option('-v --verbose', 'Show full function definitions in output')
  .description('inspect the webpack config in a project with vue-cli-service')
  .action((paths, cmd) => {
    require('../lib/inspect')(paths, cleanArgs(cmd))
  })

program
  .command('serve [entry]')
  .description('serve a .js or .vue file in development mode with zero config')
  .option('-o, --open', 'Open browser')
  .action((entry, cmd) => {
    loadCommand('serve', '@vue/cli-service-global').serve(entry, cleanArgs(cmd))
  })

program
  .command('build [entry]')
  .option('-t, --target <target>', 'Build target (app | lib | wc | wc-async, default: app)')
  .option('-n, --name <name>', 'name for lib or web-component mode (default: entry filename)')
  .option('-d, --dest <dir>', 'output directory (default: dist)')
  .description('build a .js or .vue file in production mode with zero config')
  .action((entry, cmd) => {
    loadCommand('build', '@vue/cli-service-global').build(entry, cleanArgs(cmd))
  })

program
  .command('init <template> <app-name>')
  .description('generate a project from a remote template (legacy API, requires @vue/cli-init)')
  .option('-c, --clone', 'Use git clone when fetching remote template')
  .action(() => {
    loadCommand('init', '@vue/cli-init')
  })

// output help information on unknown commands
program
  .arguments('<command>')
  .action((cmd) => {
    program.outputHelp()
    console.log(`  ` + chalk.red(`Unknown command ${chalk.yellow(cmd)}.`))
    console.log()
  })

// add some useful info on help
program.on('--help', () => {
  console.log()
  console.log(`  Run ${chalk.cyan(`vue <command> --help`)} for detailed usage of given command.`)
  console.log()
})

program.commands.forEach(c => c.on('--help', () => console.log()))

// enhance common error messages
const enhanceErrorMessages = (methodName, log) => {
  program.Command.prototype[methodName] = function (...args) {
    if (methodName === 'unknownOption' && this._allowUnknownOption) {
      return
    }
    this.outputHelp()
    console.log(`  ` + chalk.red(log(...args)))
    console.log()
    process.exit(1)
  }
}

enhanceErrorMessages('missingArgument', argName => {
  return `Missing required argument ${chalk.yellow(`<${argName}>`)}.`
})

enhanceErrorMessages('unknownOption', optionName => {
  return `Unknown option ${chalk.yellow(optionName)}.`
})

enhanceErrorMessages('optionMissingArgument', (option, flag) => {
  return `Missing required argument for option ${chalk.yellow(option.flags)}` + (
    flag ? `, got ${chalk.yellow(flag)}` : ``
  )
})

program.parse(process.argv)

if (!process.argv.slice(2).length) {
  program.outputHelp()
}

// commander passes the Command object itself as options,
// extract only actual options into a fresh object.
function cleanArgs (cmd) {
  const args = {}
  cmd.options.forEach(o => {
    const key = o.long.replace(/^--/, '')
    // if an option is not present and Command has a method with the same name
    // it should not be copied
    if (typeof cmd[key] !== 'function') {
      args[key] = cmd[key]
    }
  })
  return args
}


jest.setTimeout(20000)

const create = require('@vue/cli-test-utils/createTestProject')

test('should work', async () => {
  const project = await create('unit-jest', {
    plugins: {
      '@vue/cli-plugin-babel': {},
      '@vue/cli-plugin-unit-jest': {}
    }
  })
  await project.run(`vue-cli-service test:unit`)
})

test('should respect jest testMatch config', async () => {
  const project = await create('unit-jest-package.json', {
    plugins: {
      '@vue/cli-plugin-babel': {},
      '@vue/cli-plugin-unit-jest': {}
    }
  })
  const config = JSON.parse(await project.read('package.json'))
  config.jest.testMatch = ['custom-test-directory/my.spec.js']

  await project.write('package.json', JSON.stringify(config))

  let result
  try {
    await project.run(`vue-cli-service test:unit`)
  } catch (e) {
    result = e
  }
  expect(result.stdout).toMatch('testMatch: custom-test-directory/my.spec.js')
  expect(result.stdout).toMatch('No tests found')
})

test('should respect jest.config.js testMatch config', async () => {
  const project = await create('unit-jest-jest.config.js', {
    plugins: {
      '@vue/cli-plugin-babel': {},
      '@vue/cli-plugin-unit-jest': {}
    },
    useConfigFiles: true
  })
  await project.write('jest.config.js', `
  module.exports = ${JSON.stringify({
    testMatch: ['custom-test-directory/my.spec.js']
  })}
  `)

  let result
  try {
    await project.run(`vue-cli-service test:unit`)
  } catch (e) {
    result = e
  }
  expect(result.stdout).toMatch('testMatch: custom-test-directory/my.spec.js')
  expect(result.stdout).toMatch('No tests found')
})


<%_ if (!rootOptions.router) { _%>
<template>

    <HelloWorld msg="Welcome to Your Vue.js App"/>

</template>

<%_ } else { _%>
<template>

      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>

    <router-view/>

</template>
<%_ } _%>

<%_ if (rootOptions.cssPreprocessor !== 'stylus') { _%>

<%_ } else { _%>

<%_ } _%>


function removeArg (rawArgs, arg) {
  const matchRE = new RegExp(`^--${arg}`)
  const equalRE = new RegExp(`^--${arg}=`)
  const i = rawArgs.findIndex(arg => matchRE.test(arg))
  if (i > -1) {
    rawArgs.splice(i, equalRE.test(rawArgs[i]) ? 1 : 2)
  }
}

module.exports = (api, options) => {
  api.registerCommand('test:e2e', {
    description: 'run e2e tests with nightwatch',
    usage: 'vue-cli-service test:e2e [options]',
    options: {
      '--url': 'run e2e tests against given url instead of auto-starting dev server',
      '--config': 'use custom nightwatch config file (overrides internals)',
      '-e, --env': 'specify comma-delimited browser envs to run in (default: chrome)',
      '-t, --test': 'sepcify a test to run by name',
      '-f, --filter': 'glob to filter tests by filename'
    },
    details:
      `All Nightwatch CLI options are also supported.\n` +
      `https://github.com/nightwatchjs/nightwatch/blob/master/lib/runner/cli/cli.js`
  }, (args, rawArgs) => {
    removeArg(rawArgs, 'url')
    removeArg(rawArgs, 'mode')

    const serverPromise = args.url
      ? Promise.resolve({ url: args.url })
      : api.service.run('serve')

    return serverPromise.then(({ server, url }) => {
      // expose dev server url to tests
      process.env.VUE_DEV_SERVER_URL = url
      if (rawArgs.indexOf('--config') === -1) {
        // expose user options to config file
        const fs = require('fs')
        let userOptionsPath, userOptions
        if (fs.existsSync(userOptionsPath = api.resolve('nightwatch.config.js'))) {
          userOptions = require(userOptionsPath)
        } else if (fs.existsSync(userOptionsPath = api.resolve('nightwatch.json'))) {
          userOptions = require(userOptionsPath)
        }
        process.env.VUE_NIGHTWATCH_USER_OPTIONS = JSON.stringify(userOptions || {})

        rawArgs.push('--config', require.resolve('./nightwatch.config.js'))
      }

      if (rawArgs.indexOf('--env') === -1) {
        rawArgs.push('--env', 'chrome')
      }

      const execa = require('execa')
      const nightWatchBinPath = require.resolve('nightwatch/bin/nightwatch')
      const runner = execa(nightWatchBinPath, rawArgs, { stdio: 'inherit' })
      if (server) {
        runner.on('exit', () => server.close())
        runner.on('error', () => server.close())
      }

      if (process.env.VUE_CLI_TEST) {
        runner.on('exit', code => {
          process.exit(code)
        })
      }

      return runner
    })
  })

  // TODO remove in RC
  api.registerCommand('e2e', (args, rawArgv) => {
    const { warn } = require('@vue/cli-shared-utils')
    warn(`Deprecation Warning: "vue-cli-service e2e" has been renamed to "vue-cli-service test:e2e".`)
    return api.service.run('test:e2e', args, rawArgv)
  })
}

module.exports.defaultModes = {
  'test:e2e': 'production'
}


const pluginRE = /(?:function|class) (\w+Plugin)/

console.log(stringify(res, (value, indent, stringify) => {

keep keep keep keep keep replace keep keep keep keep keep

const output = stringify(res, (value, indent, stringify) => {


jest.setTimeout(20000)

const fs = require('fs-extra')
const path = require('path')
const portfinder = require('portfinder')
const { createServer } = require('http-server')
const execa = require('execa')
const launchPuppeteer = require('@vue/cli-test-utils/launchPuppeteer')

const cwd = path.resolve(__dirname, 'temp')
const binPath = require.resolve('@vue/cli/bin/vue')
const write = (file, content) => fs.writeFile(path.join(cwd, file), content)

const entryVue = fs.readFileSync(path.resolve(__dirname, 'entry.vue'), 'utf-8')

beforeAll(async () => {
  await fs.ensureDir(cwd)
  await write('my-wc.vue', entryVue)
})

let server, browser, page
test('global build --target wc', async () => {
  const { stdout } = await execa(binPath, ['build', 'my-wc.vue', '--target', 'wc'], { cwd })

  expect(stdout).toMatch('Build complete.')

  const distDir = path.join(cwd, 'dist')
  const hasFile = file => fs.existsSync(path.join(distDir, file))
  expect(hasFile('demo.html')).toBe(true)
  expect(hasFile('my-wc.js')).toBe(true)
  expect(hasFile('my-wc.min.js')).toBe(true)

  const port = await portfinder.getPortPromise()
  server = createServer({ root: distDir })

  await new Promise((resolve, reject) => {
    server.listen(port, err => {
      if (err) return reject(err)
      resolve()
    })
  })

  const launched = await launchPuppeteer(`http://localhost:${port}/demo.html`)
  browser = launched.browser
  page = launched.page

  const h1Text = await page.evaluate(() => {
    return document.querySelector('my-wc').shadowRoot.querySelector('h1').textContent
  })

  expect(h1Text).toMatch('hi')
})

afterAll(async () => {
  await browser.close()
  server.close()
})


# What is This?

The npm registry does not expose `/latest` endpoints for scoped packages. Getting the full metadata for a scoped package is typically `~300ms` slower than simply getting the latest version from an unscoped package.

This package serves as an unscoped marker to expose the latest version currently published for `@vue/cli`.


module.exports = api => {
  api.render('./template', {
    hasTS: api.hasPlugin('typescript')
  })

  api.extendPackage({
    scripts: {
      'test:e2e': 'vue-cli-service test:e2e'
    }
  })
}


}
return stringify(value)
}, 2))
})
}
module.exports.defaultModes = {
inspect: 'development'

keep keep keep replace keep keep keep keep keep

const fs = require('fs')
const path = require('path')
const execa = require('execa')
const resolve = require('resolve')

module.exports = function inspect (paths, args) {
  const cwd = process.cwd()
  let servicePath
  try {
    servicePath = resolve.sync('@vue/cli-service', { basedir: cwd })
  } catch (e) {
    const { error } = require('@vue/cli-shared-utils')
    error(`Failed to locate @vue/cli-service. Make sure you are in the right directory.`)
    process.exit(1)
  }
  const binPath = path.resolve(servicePath, '../../bin/vue-cli-service.js')
  if (fs.existsSync(binPath)) {
    execa('node', [
      binPath,
      'inspect',
      ...(args.mode ? ['--mode', args.mode] : []),
      ...(args.verbose ? ['--verbose'] : []),
      ...paths
    ], { cwd, stdio: 'inherit' })
  }
}


module.exports = function lint (args = {}, api, silent) {
  const cwd = api.resolve('.')
  const fs = require('fs')
  const path = require('path')
  const globby = require('globby')
  const tslint = require('tslint')
  const vueCompiler = require('vue-template-compiler')

  const options = {
    fix: args['fix'] !== false,
    formatter: args.format || 'codeFrame',
    formattersDirectory: args['formatters-dir'],
    rulesDirectory: args['rules-dir']
  }
  const linter = new tslint.Linter(options)

  const config = tslint.Configuration.findConfiguration(api.resolve('tslint.json')).results
  // create a patched config that disables the blank lines rule,
  // so that we get correct line numbers in error reports for *.vue files.
  const vueConfig = Object.assign(config)
  const rules = vueConfig.rules = new Map(vueConfig.rules)
  const rule = rules.get('no-consecutive-blank-lines')
  rules.set('no-consecutive-blank-lines', Object.assign({}, rule, {
    ruleSeverity: 'off'
  }))

  // hack to make tslint --fix work for *.vue files
  // this works because (luckily) tslint lints synchronously
  const vueFileCache = new Map()
  const writeFileSync = fs.writeFileSync
  const patchWriteFile = () => {
    fs.writeFileSync = (file, content, options) => {
      if (/\.vue(\.ts)?$/.test(file)) {
        file = file.replace(/\.ts$/, '')
        const { before, after } = vueFileCache.get(path.normalize(file))
        content = `${before}\n${content.trim()}\n${after}`
      }
      return writeFileSync(file, content, options)
    }
  }
  const restoreWriteFile = () => {
    fs.writeFileSync = writeFileSync
  }

  const lint = file => new Promise((resolve, reject) => {
    const filePath = api.resolve(file)
    fs.readFile(filePath, 'utf-8', (err, content) => {
      if (err) return reject(err)
      const isVue = /\.vue(\.ts)?$/.test(file)
      if (isVue) {
        const { script } = vueCompiler.parseComponent(content, { pad: 'line' })
        if (script) {
          vueFileCache.set(filePath, {
            before: content.slice(0, script.start),
            after: content.slice(script.end)
          })
        }
        content = script && script.content
      }
      if (content) {
        patchWriteFile()
        linter.lint(
          // append .ts so that tslint apply TS rules
          `${filePath}${isVue ? `.ts` : ``}`,
          content,
          // use Vue config to ignore blank lines
          isVue ? vueConfig : config
        )
        restoreWriteFile()
      }
      resolve()
    })
  })

  const files = args._ && args._.length
    ? args._
    : ['src/**/*.ts', 'src/**/*.vue', 'tests/**/*.ts']

  const stripTsExtension = str => str.replace(/\.vue\.ts\b/g, '.vue')

  return globby(files, { cwd }).then(files => {
    return Promise.all(files.map(lint))
  }).then(() => {
    if (silent) return

    const result = linter.getResult()
    if (result.output.trim()) {
      process.stdout.write(stripTsExtension(result.output))
    } else if (result.fixes.length) {
      // some formatters do not report fixes.
      const f = new tslint.Formatters.ProseFormatter()
      process.stdout.write(stripTsExtension(f.format(result.failures, result.fixes)))
    } else if (!result.failures.length) {
      console.log(`No lint errors found.\n`)
    }

    if (result.failures.length && !args.force) {
      process.exitCode = 1
    }
  })
}


const generateWithPlugin = require('@vue/cli-test-utils/generateWithPlugin')

test('base', async () => {
  const { pkg, files } = await generateWithPlugin([
    {
      id: 'unit-mocha',
      apply: require('../generator'),
      options: {}
    },
    // mock presence of the eslint plugin
    {
      id: 'eslint',
      apply: () => {},
      options: {}
    }
  ])

  expect(pkg.scripts['test:unit']).toBe('vue-cli-service test:unit')
  expect(pkg.devDependencies).toHaveProperty('@vue/test-utils')
  expect(files['tests/unit/.eslintrc.js']).toMatch('mocha: true')

  const spec = files['tests/unit/HelloWorld.spec.js']
  expect(spec).toMatch(`import { expect } from 'chai'`)
  expect(spec).toMatch(`expect(wrapper.text()).to.include(msg)`)
})