/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const Compiler = require("./Compiler");
const MultiCompiler = require("./MultiCompiler");
const NodeEnvironmentPlugin = require("./node/NodeEnvironmentPlugin");
const WebpackOptionsApply = require("./WebpackOptionsApply");
const WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter");
const validateSchema = require("./validateSchema");
const WebpackOptionsValidationError = require("./WebpackOptionsValidationError");
const webpackOptionsSchema = require("../schemas/WebpackOptions.json");

const webpack = (options, callback) => {
	const webpackOptionsValidationErrors = validateSchema(webpackOptionsSchema, options);
	if(webpackOptionsValidationErrors.length) {
		throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
	}
	let compiler;
	if(Array.isArray(options)) {
		compiler = new MultiCompiler(options.map(options => webpack(options)));
	} else if(typeof options === "object") {
		options = new WebpackOptionsDefaulter().process(options);

		compiler = new Compiler(options.context);
		compiler.options = options;
		new NodeEnvironmentPlugin().apply(compiler);
		if(options.plugins && Array.isArray(options.plugins)) {
			for(const plugin of options.plugins) {
				plugin.apply(compiler);
			}
		}
		compiler.hooks.environment.call();
		compiler.hooks.afterEnvironment.call();
		compiler.options = new WebpackOptionsApply().process(options, compiler);
	} else {
		throw new Error("Invalid argument: options");
	}
	if(callback) {
		if(typeof callback !== "function") throw new Error("Invalid argument: callback");
		if(options.watch === true || (Array.isArray(options) && options.some(o => o.watch))) {
			const watchOptions = Array.isArray(options) ? options.map(o => o.watchOptions || {}) : (options.watchOptions || {});
			return compiler.watch(watchOptions, callback);
		}
		compiler.run(callback);
	}
	return compiler;
};

exports = module.exports = webpack;

webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter;
webpack.WebpackOptionsApply = WebpackOptionsApply;
webpack.Compiler = Compiler;
webpack.MultiCompiler = MultiCompiler;
webpack.NodeEnvironmentPlugin = NodeEnvironmentPlugin;
webpack.validate = validateSchema.bind(this, webpackOptionsSchema);
webpack.validateSchema = validateSchema;
webpack.WebpackOptionsValidationError = WebpackOptionsValidationError;

const exportPlugins = (obj, mappings) => {
	for(const name of Object.keys(mappings)) {
		Object.defineProperty(obj, name, {
			configurable: false,
			enumerable: true,
			get: mappings[name]
		});
	}
};

exportPlugins(exports, {
	"AutomaticPrefetchPlugin": () => require("./AutomaticPrefetchPlugin"),
	"BannerPlugin": () => require("./BannerPlugin"),
	"CachePlugin": () => require("./CachePlugin"),
	"ContextExclusionPlugin": () => require("./ContextExclusionPlugin"),
	"ContextReplacementPlugin": () => require("./ContextReplacementPlugin"),
	"DefinePlugin": () => require("./DefinePlugin"),
	"DllPlugin": () => require("./DllPlugin"),
	"DllReferencePlugin": () => require("./DllReferencePlugin"),
	"EnvironmentPlugin": () => require("./EnvironmentPlugin"),
	"EvalDevToolModulePlugin": () => require("./EvalDevToolModulePlugin"),
	"EvalSourceMapDevToolPlugin": () => require("./EvalSourceMapDevToolPlugin"),
	"ExtendedAPIPlugin": () => require("./ExtendedAPIPlugin"),
	"ExternalsPlugin": () => require("./ExternalsPlugin"),
	"HashedModuleIdsPlugin": () => require("./HashedModuleIdsPlugin"),
	"HotModuleReplacementPlugin": () => require("./HotModuleReplacementPlugin"),
	"IgnorePlugin": () => require("./IgnorePlugin"),
	"LibraryTemplatePlugin": () => require("./LibraryTemplatePlugin"),
	"LoaderOptionsPlugin": () => require("./LoaderOptionsPlugin"),
	"LoaderTargetPlugin": () => require("./LoaderTargetPlugin"),
	"MemoryOutputFileSystem": () => require("./MemoryOutputFileSystem"),
	"ModuleFilenameHelpers": () => require("./ModuleFilenameHelpers"),
	"NamedChunksPlugin": () => require("./NamedChunksPlugin"),
	"NamedModulesPlugin": () => require("./NamedModulesPlugin"),
	"NoEmitOnErrorsPlugin": () => require("./NoEmitOnErrorsPlugin"),
	"NormalModuleReplacementPlugin": () => require("./NormalModuleReplacementPlugin"),
	"PrefetchPlugin": () => require("./PrefetchPlugin"),
	"ProgressPlugin": () => require("./ProgressPlugin"),
	"ProvidePlugin": () => require("./ProvidePlugin"),
	"SetVarMainTemplatePlugin": () => require("./SetVarMainTemplatePlugin"),
	"SingleEntryPlugin": () => require("./SingleEntryPlugin"),
	"SourceMapDevToolPlugin": () => require("./SourceMapDevToolPlugin"),
	"Stats": () => require("./Stats"),
	"UmdMainTemplatePlugin": () => require("./UmdMainTemplatePlugin"),
	"WatchIgnorePlugin": () => require("./WatchIgnorePlugin"),
});
exportPlugins(exports.optimize = {}, {
	"AggressiveMergingPlugin": () => require("./optimize/AggressiveMergingPlugin"),
	"AggressiveSplittingPlugin": () => require("./optimize/AggressiveSplittingPlugin"),
	"ChunkModuleIdRangePlugin": () => require("./optimize/ChunkModuleIdRangePlugin"),
	"LimitChunkCountPlugin": () => require("./optimize/LimitChunkCountPlugin"),
	"MinChunkSizePlugin": () => require("./optimize/MinChunkSizePlugin"),
	"ModuleConcatenationPlugin": () => require("./optimize/ModuleConcatenationPlugin"),
	"OccurrenceOrderPlugin": () => require("./optimize/OccurrenceOrderPlugin"),
	"RuntimeChunkPlugin": () => require("./optimize/RuntimeChunkPlugin"),
	"SideEffectsFlagPlugin": () => require("./optimize/SideEffectsFlagPlugin"),
	"SplitChunksPlugin": () => require("./optimize/SplitChunksPlugin"),
});
exportPlugins(exports.web = {}, {
	"FetchCompileWasmTemplatePlugin": () => require("./web/FetchCompileWasmTemplatePlugin"),
	"JsonpTemplatePlugin": () => require("./web/JsonpTemplatePlugin"),
});
exportPlugins(exports.webworker = {}, {
	"WebWorkerTemplatePlugin": () => require("./webworker/WebWorkerTemplatePlugin"),
});
exportPlugins(exports.node = {}, {
	"NodeTemplatePlugin": () => require("./node/NodeTemplatePlugin"),
	"ReadFileCompileWasmTemplatePlugin": () => require("./node/ReadFileCompileWasmTemplatePlugin"),
});
exportPlugins(exports.debug = {}, {
	"ProfilingPlugin": () => require("./debug/ProfilingPlugin"),
});

const defineMissingPluginError = (pluginName, errorMessage) => {
	Reflect.defineProperty(exports.optimize, pluginName, {
		configurable: false,
		enumerable: true,
		get() {
			throw new Error(errorMessage);
		}
	});
};

defineMissingPluginError(
	"UglifyJsPlugin",
	"webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead."
);

defineMissingPluginError(
	"CommonsChunkPlugin",
	"webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead."
);

@@ -6417,16 +6417,39 @@
 w Error(
+%60RemovedPluginError: $%7B
 errorMes
@@ -6452,16 +6452,18 @@
 rMessage
+%7D%60
 );%0A%09%09%7D%0A%09

improve error message