/* eslint-disable no-console */

import fs from 'fs'
import path from 'path'

let rootPath = undefined

const defaultOptions = {
    destination: null,
    flatten: false
}

export default function transformFiles(
    sourcePath = '',
    options = defaultOptions,
    fileTransformer = function() {}
) {
    validateArgs()

    if (!rootPath) rootPath = sourcePath

    const dirContents = fs.readdirSync(sourcePath)

    dirContents.forEach(fileOrDirName => {
        const fileOrDirPath = path.resolve(sourcePath, fileOrDirName)
        const destinationPath = setDestinationPath(sourcePath, options)

        if (isDir(fileOrDirPath)) {
            transformFiles(fileOrDirPath, options, fileTransformer)
        } else {
            transformThisFile(fileOrDirName, sourcePath, destinationPath, fileTransformer)
        }
    })

    function validateArgs() {
        if (!path.isAbsolute(sourcePath)) {
            throw new Error('sourcePath argument must be an absolute path.\n')
        }
        if (options.destination && !path.isAbsolute(options.destination)) {
            throw new Error('options.desintation must be an absolute path.\n')
        }
        if (options.flatten && typeof options.flatten !== 'boolean') {
            throw new TypeError('options.flatten must be a boolean value.\n')
        }
        for (let optionName in options) {
            if (optionName in defaultOptions === false) {
                throw new Error(`'${optionName}' is not a valid option.\n`)
            }
        }
    }

    function transformThisFile(filename, sourcePath, destinationPath, fileTransformer) {
        createDirsInPath(destinationPath)

        fileTransformer({
            filename,
            sourcePath,
            destinationPath
        })
    }

    function isDir(pathToFileOrDir) {
        return fs.statSync(pathToFileOrDir).isDirectory()
    }

    function setDestinationPath(source, {destination, flatten}) {
        let destPath = source
        if (destination) {
            if (flatten) {
                destPath = options.destination
            } else {
                const relativePathFromRootPath = source.replace(rootPath, '').slice(1)
                destPath = path.resolve(options.destination, relativePathFromRootPath)
            }
        }
        return destPath
    }
}

export function createDirsInPath(dirPath) {
    forEachDirInPath(createDirIfDoesntExist)

    function forEachDirInPath(pathReducer) {
        dirPath
            .split(path.sep)
            .reduce(pathReducer, path.sep)
    }

    function createDirIfDoesntExist(dirPath, nextDir) {
        if (!fs.existsSync(path.resolve(dirPath, nextDir))) {
            fs.mkdirSync(path.resolve(dirPath, nextDir))
        }
        return path.resolve(dirPath, nextDir)
    }
}

@@ -171,23 +171,8 @@
 %0A%7D%0A%0A
-export default 
 func
@@ -191,21 +191,16 @@
 rmFiles(
-%0A    
 sourcePa
@@ -205,18 +205,9 @@
 Path
- = '',%0A   
+,
  opt
@@ -228,20 +228,16 @@
 Options,
-%0A   
  fileTra
@@ -248,25 +248,8 @@
 rmer
- = function() %7B%7D%0A
 ) %7B%0A
@@ -317,28 +317,8 @@
 %0A   
- const dirContents =
  fs.
@@ -344,25 +344,8 @@
 ath)
-%0A%0A    dirContents
 .for
@@ -645,36 +645,35 @@
        transform
-This
+One
 File(fileOrDirNa
@@ -1429,24 +1429,28 @@
     %7D%0A    %7D%0A
+    
 %0A    functio
@@ -1455,109 +1455,105 @@
 ion 
-transformThisFile(filename, sourcePath, destinationPath, fileTransformer) %7B%0A        createDirsInPath(
+setDestinationPath(source, options) %7B%0A        let destPath = source%0A        %0A        if (options.
 dest
@@ -1559,22 +1559,19 @@
 tination
-Path)%0A
+) %7B
 %0A       
@@ -1575,117 +1575,365 @@
     
-fileTransformer(%7B%0A            filename,%0A            sourcePath,%0A            destinationPath%0A        %7D)
+    if (options.flatten) %7B%0A                destPath = options.destination%0A            %7D else %7B%0A                const relativePathFromRootPath = source.replace(rootPath, '').slice(1) // first char is '/'%0A                destPath = path.resolve(options.destination, relativePathFromRootPath)%0A            %7D%0A        %7D%0A        %0A        return destPath
 %0A    %7D%0A
+    
 %0A   
@@ -2049,36 +2049,47 @@
 ion 
-setDestinationPath(
+transformOneFile(filename, 
 source
+Path
 , 
-%7B
 dest
@@ -2099,63 +2099,57 @@
 tion
-, flatten%7D) %7B%0A        let destPath = source%0A        if 
+Path, fileTransformer) %7B%0A        createDirsInPath
 (des
@@ -2148,35 +2148,38 @@
 Path(destination
-) %7B
+Path)%0A
 %0A            if 
@@ -2175,316 +2175,110 @@
     
-    if (flatten) %7B%0A                destPath = options.destination%0A            %7D else %7B%0A                const relativePathFromRootPath = source.replace(rootPath, '').slice(1)%0A                destPath = path.resolve(options.destination, relativePathFromRootPath)%0A            %7D%0A        %7D%0A        return destPath
+fileTransformer(%7B%0A            filename,%0A            sourcePath,%0A            destinationPath%0A        %7D)
 %0A   
@@ -2744,16 +2744,47 @@
 extDir)%0A    %7D%0A%7D%0A
+%0Aexport default transformFiles%0A

Clean up the code.