import path from "path";

export class Config {
  constructor() {
    const context = process.cwd();
    const env = process.env.NODE_ENV || "development";
    const debug = ["development", "test"].indexOf(env) !== -1;

    this.options = {
      alias: {},      // [package]: folder
      context,        // Folder
      env,            // String
      debug,          // Boolean
      dest: null,     // Folder
      loader: {},     // [ext]: [ {...loader} ] ],
      src: {},        // [name]: [files]
    };

    this
      .alias("react", "./node_modules/react")
      .loader("babel", ".js", {
        cacheDirectory: true,
        exclude: /node_modules/,
        query: {
          cacheDirectory: true,
        },
      })
      .loader("json", ".json")
      .loader("url", [".gif", ".jpg", ".jpeg", ".png"], {
        query: {
          limit: 8192,
        },
      })
      .loader("style", ".css")
      .loader("css", ".css", {
        query: {
          localIdentName: "[name]-[local]--[hash:base64:5]",
        },
      })
    ;
  }

  alias(pkg, folder) {
    this.options.alias[pkg] = path.resolve(this.options.context, folder);

    return this;
  }

  context(context) {
    this.options.context = context;

    return this;
  }

  create() {
    throw new Error("`Config.create` should be extended.");
  }

  debug(debug) {
    if (typeof debug === "undefined") {
      return this.options.debug;
    }

    this.options.debug = debug;

    return this;
  }

  dest(folder) {
    this.options.dest = folder;

    return this;
  }

  env(env) {
    if (!env) {
      return this.options.env;
    }

    this.options.env = env;

    return this;
  }

  loader(loader, extOrExts = ".js", settings = {}) {
    if (Array.isArray(extOrExts)) {
      extOrExts.forEach((ext) => this.loader(loader, ext, settings));

      return this;
    }

    const ext = extOrExts;

    if (!loader.match(/-loader$/)) {
      loader = `${loader}-loader`;
    }

    if (!this.options.loader[ext]) {
      this.options.loader[ext] = [];
    }

    if (typeof loader === "function") {
      this.options.loader[ext] = loader(this.options.loader[ext]);
    } else {
      const test = new RegExp(ext.replace(".", "\\."));

      this.options.loader[ext].push({
        loader,
        test,
        ...settings,
      });
    }

    return this;
  }

  src(src) {
    // Convert "./src/client.js" into { client: ["/.../src/client.js"] }
    if (typeof src === "string") {
      const parsed = path.parse(src);
      const basename = path.basename(parsed.base, parsed.ext).toLowerCase();

      // Arrays are best to avoid cyclical dependency issues
      src = {
        [basename]: [path.resolve(this.options.context, src)],
      };
    }

    this.options.src = src;

    return this;
  }
}

@@ -505,16 +505,465 @@
 %0A    %7D;%0A
+  %7D%0A%0A  alias(pkg, folder) %7B%0A    this.options.alias%5Bpkg%5D = path.resolve(this.options.context, folder);%0A%0A    return this;%0A  %7D%0A%0A  context(context) %7B%0A    this.options.context = context;%0A%0A    return this;%0A  %7D%0A%0A  create() %7B%0A    throw new Error(%22%60Config.create%60 should be extended.%22);%0A  %7D%0A%0A  debug(debug) %7B%0A    if (typeof debug === %22undefined%22) %7B%0A      return this.options.debug;%0A    %7D%0A%0A    this.options.debug = debug;%0A%0A    return this;%0A  %7D%0A%0A  defaults() %7B
 %0A    thi
@@ -1046,38 +1046,8 @@
 , %7B%0A
-        cacheDirectory: true,%0A
     
@@ -1468,438 +1468,8 @@
  %7D%0A%0A
-  alias(pkg, folder) %7B%0A    this.options.alias%5Bpkg%5D = path.resolve(this.options.context, folder);%0A%0A    return this;%0A  %7D%0A%0A  context(context) %7B%0A    this.options.context = context;%0A%0A    return this;%0A  %7D%0A%0A  create() %7B%0A    throw new Error(%22%60Config.create%60 should be extended.%22);%0A  %7D%0A%0A  debug(debug) %7B%0A    if (typeof debug === %22undefined%22) %7B%0A      return this.options.debug;%0A    %7D%0A%0A    this.options.debug = debug;%0A%0A    return this;%0A  %7D%0A%0A
   de

Move default options into .defaults