'use strict'

var atomify = require('atomify')
  , path = require('path')
  , fs = require('fs')
  , cwd = process.cwd()
  , internals = {}

internals.findFirstFile = function findFirstFile (dir, filenames) {
  var entryPath
    , i
    , l

  for (i = 0, l = filenames.length; i < l; i++){
    entryPath = path.join(dir, filenames[i])
    if (fs.existsSync(entryPath)){
      return entryPath
    }
  }
}

internals.findEntryJs = function findEntryJs (dir) {
  return internals.findFirstFile(dir, ['entry.js', 'entry.jsx', 'index.js', 'index.jsx'])
}

internals.findEntryCss = function findEntryCss (dir) {
  return internals.findFirstFile(dir, ['entry.css', 'index.css'])
}

internals.findEntryHTML = function findEntryHTML (dir) {
  return internals.findFirstFile(dir, ['entry.html', 'index.html'])
}

internals.findEntryData = function findEntryHTML (dir) {
  return internals.findFirstFile(dir, ['data.js', 'data.json', 'entry.json'])
}

internals.makeHTML = function makeHTML (paths, appContent, options) {
  // be sure to include the body tag so that the livereload snipped can
  // be inserted
  var html = '<body>'

  if (paths.css) html += '<link rel="stylesheet" href="' + paths.css + '" />'
  html += '<div id="app">' + appContent + '</div>'
  if (paths.js && options.enableClientJSX) html += '<script src="' + paths.js + '"></script>'
  html += '</body>'

  return html
}

module.exports = function ribcagePreview (options) {
  var config = {
      server: {
        lr: {
          port: 4001
        }
        , port: 4000
      }
    }
    , exampleDir = path.join(options.dir, 'example')
    , cssEntry = internals.findEntryCss(exampleDir)
    , jsEntry = internals.findEntryJs(exampleDir)
    , htmlEntry = internals.findEntryHTML(exampleDir)
    , jsComponent = internals.findEntryJs(options.dir)
    , dataEntry = internals.findEntryData(exampleDir)
    , enableReactRouter = options.enableReactRouter

  if (cssEntry) {
    config.css = {
      entry: cssEntry
      , alias: '/bundle.css'
      , debug: options.debug
      , autoprefixer: typeof options.autoprefix === 'undefined' ? true : options.autoprefix
    }
  }

  if (jsEntry) {
    config.js = {
      entry: jsEntry
      , alias: '/bundle.js'
      , debug: options.debug
      , extensions: ['.js', '.json', '.jsx']
    }
  }

  if (htmlEntry) {
    config.server.html = htmlEntry
  }

  if (jsEntry.indexOf('.jsx') > -1) {
    require('babel/register', {only: new RegExp(cwd), sourceMap: 'inline'})

    config.server.html = function defaultHtml (paths, callback) {
      // React's context is … weird, and ReactRouter relies on it heavily. We
      // need to make sure we're requring the modules that the component is
      // using. Otherwise, the context goes missing
      var React = require(path.join(cwd, 'node_modules', 'react'))
        , ReactRouter = enableReactRouter ? require(path.join(cwd, 'node_modules', 'react-router')) : null
        , getHTML = function getHTML (reactComponent, data) {
          var done = function done (calcedReactComponent) {
            callback(null, internals.makeHTML(
              paths
              , React.renderToString(React.createElement(calcedReactComponent, data))
              , options
              , callback
            ))
          }

          if (enableReactRouter) ReactRouter.run(reactComponent, paths.request, done)
          else done(reactComponent)
        }

      // dump the whole cache because we can't be sure what's going to be
      // required by the entry file
      require.cache = {}

      try {
        getHTML(require(jsComponent), dataEntry ? require(dataEntry) : null)
      }
      catch (err) {
        // TODO better handle babel's crazy errors
        // babel throws weird errors :( check the first line of this stacktrace
        callback(err._babel ? new Error(err) : err)
      }
    }
  }

  if (enableReactRouter){
    config.server.spaMode = true
  }

  atomify(config)
}

@@ -1914,16 +1914,461 @@
 ctRouter
+%0A    , enableJSX = jsEntry.indexOf('.jsx') %3E -1%0A    // React's context is %E2%80%A6 weird, and ReactRouter relies on it heavily. We%0A    // need to make sure we're requring the modules that the component is%0A    // using. Otherwise, the context goes missing%0A    , React = enableJSX ? require(path.join(cwd, 'node_modules', 'react')) : null%0A    , ReactRouter = enableJSX && enableReactRouter ? require(path.join(cwd, 'node_modules', 'react-router')) : null
 %0A%0A  if (
@@ -2819,36 +2819,17 @@
 if (
-jsEntry.indexOf('.jsx') %3E -1
+enableJSX
 ) %7B%0A
@@ -2981,391 +2981,11 @@
     
-// React's context is %E2%80%A6 weird, and ReactRouter relies on it heavily. We%0A      // need to make sure we're requring the modules that the component is%0A      // using. Otherwise, the context goes missing%0A      var React = require(path.join(cwd, 'node_modules', 'react'))%0A        , ReactRouter = enableReactRouter ? require(path.join(cwd, 'node_modules', 'react-router')) : null%0A        ,
+var
  get
@@ -3459,142 +3459,595 @@
   %7D%0A
-%0A      // dump the whole cache because we can't be sure what's going to be%0A      // required by the entry file%0A      require.cache = %7B
+      , cacheId%0A%0A      // remove the cached requires for anything in the cwd directory%0A      // we can't just remove the requires for the entries becuase they might%0A      // require something else, and we can't just look at options.dir because%0A      // it's nice to be able to change things outside of this component and%0A      // have the change picked up. It also more closely matches watchify%0A      // behavior%0A      for (cacheId in require.cache)%7B%0A        if (cacheId.indexOf(cwd) %3E -1 && cacheId.indexOf('node_modules') %3C 0) %7B%0A          delete require.cache%5BcacheId%5D%0A        %7D%0A      
 %7D%0A%0A 

Fix jsx mode not getting new data. Fixes #12