/**
 * Extract-text webpack block.
 *
 * @see https://github.com/webpack/extract-text-webpack-plugin
 */

const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = extractText

/**
 * @param {string}    outputFilePattern
 * @param {string}  [fileType]          A MIME type used for file matching. Defaults to `text/css`.
 * @return {Function}
 */
function extractText (outputFilePattern, fileType) {
  outputFilePattern = outputFilePattern || 'css/[name].[contenthash:8].css'
  fileType = fileType || 'text/css'

  const plugin = new ExtractTextPlugin(outputFilePattern)

  return (context, webpackConfig) => {
    const loaderConfig = getLoaderConfigByType(context, webpackConfig, fileType)
    const nonStyleLoaders = getNonStyleLoaders(loaderConfig, fileType)

    return {
      module: {
        loaders: [
          {
            test: context.fileType(fileType),
            exclude: loaderConfig.exclude,
            loader: plugin.extract({
              fallbackLoader: 'style-loader',
              loader: nonStyleLoaders
            }),
            loaders: undefined
          }
        ]
      },
      plugins: [ plugin ]
    }
  }
}

/**
 * @param {object}  context
 * @param {object}  webpackConfig
 * @param {string}  fileType
 * @return {object}
 * @throws {Error}
 */
function getLoaderConfigByType (context, webpackConfig, fileType) {
  const loaderConfig = webpackConfig.module.loaders.find(
    // using string-based comparison here, since webpack-merge tends to deep-cloning things
    (loader) => String(loader.test) === String(context.fileType(fileType))
  )

  if (loaderConfig) {
    return loaderConfig
  } else {
    throw new Error(`${fileType} loader could not be found in webpack config.`)
  }
}

/**
 * Finds the loader config for the given `fileType` and returns all loaders
 * except the `style-loader` which is expected to be the first loader.
 *
 * @param {object}  context
 * @param {object}  webpackConfig
 * @param {string}  fileType
 * @return {string[]}
 * @throws {Error}
 */
function getNonStyleLoaders (loaderConfig, fileType) {
  if (!loaderConfig.loaders || loaderConfig.loaders.length === 0) {
    throw new Error(`No ${fileType} file loaders found.`)
  }
  if (!/^style(-loader)?$/.test(loaderConfig.loaders[0])) {
    throw new Error(`Expected "style-loader" to be first loader of .css files. Instead got: ${loaderConfig.loaders[0]}`)
  }

  // `loaderConfig.loaders` without the leading 'style-loader'
  const nonStyleLoaders = [].concat(loaderConfig.loaders)
  nonStyleLoaders.shift()

  return nonStyleLoaders
}

@@ -613,22 +613,30 @@
 xt, 
-webpack
+helpers) =%3E prev
 Config
-)
  =%3E 
@@ -685,39 +685,36 @@
 ByType(context, 
-webpack
+prev
 Config, fileType
@@ -795,70 +795,189 @@
     
-return %7B%0A      module: %7B%0A        loaders: %5B%0A          %7B%0A      
+// Partial application of %60addLoader%60, %60addPlugin%60 & %60removeLoaders%60%0A    // Bind them to their job, but don't apply them on a config yet%0A%0A    const _addLoader = helpers.addLoader(%7B%0A
     
@@ -1012,22 +1012,16 @@
 eType),%0A
-      
       ex
@@ -1051,30 +1051,24 @@
 lude,%0A      
- 
-     
 loader: plug
@@ -1080,22 +1080,16 @@
 tract(%7B%0A
-      
         
@@ -1124,30 +1124,24 @@
 r',%0A        
-    
-  
 loader: nonS
@@ -1162,111 +1162,329 @@
     
- 
+%7D)%0A
     
- 
 %7D)
-,
 %0A    
-        loaders: undefined%0A          %7D%0A        %5D%0A      %7D,%0A      plugins: %5B plugin %5D%0A    %7D
+const _addPlugin = helpers.addPlugin(plugin)%0A    const _removeLoaders = removeLoaders(context.fileType(fileType))%0A%0A    // Now apply them to the config: Remove the existing loaders for that%0A    // file type, add the new loader and add the plugin%0A%0A    return _addPlugin(_addLoader(_removeLoaders(prevConfig)))
 %0A  %7D
@@ -2903,8 +2903,431 @@
 aders%0A%7D%0A
+%0A/**%0A * @param %7BRegExp%7D loaderTest   Remove all loaders that match this %60.test%60 regex.%0A * @return %7BFunction%7D%0A */%0Afunction removeLoaders (loaderTest) %7B%0A  return prevConfig =%3E %7B%0A    const newLoaders = prevConfig.module.loaders.filter(loaderDef =%3E loaderDef.test !== loaderTest)%0A%0A    return Object.assign(%7B%7D, prevConfig, %7B%0A      module: Object.assign(%7B%7D, prevConfig.module, %7B%0A        loaders: newLoaders%0A      %7D)%0A    %7D)%0A  %7D%0A%7D%0A

Update extract-text block to use new API