import { Readable } from 'stream'
import File from 'vinyl'
import nodepath from 'path'
import opts from '../opts'
import cache from '../cache'
import bridge from '../bridge'
import { _, log, readFile, handleError } from '../lib/fns'

const LOG = 'stream'

let basePath, flintPath
let stream = new Readable({ objectMode: true })
stream._read = function(n) {}

let internalTimeout
let fileLoading = {}
let scriptWaiting = {}

function fileSend({ path, contents }) {
  log(LOG, '--- STREAM --- fileSend', path)

  // check if file actually in flint project
  if (!path || path.indexOf(basePath) !== 0 || path.indexOf(flintPath) === 0) {
    log(LOG, 'file not in path, or in flint dir', basePath, flintPath, path)
    return
  }

  // write to stream
  const rPath = nodepath.relative(basePath, path)
  const file = new File(vinyl(path, new Buffer(contents)))

  log(LOG, 'rpath', rPath)

  function pushStream() {
    log(LOG, 'pushStream()', path, rPath)
    stream.push(file)
  }

  let attempts = 0

  // waits for file load before pushing next
  function checkPushStream(loop = false) {
    if (!loop) {
      // ensures it only runs once after loaded
      if (scriptWaiting[rPath]) return
      scriptWaiting[rPath] = true
    }

    log(LOG, 'checkPushStream', 'rPath', rPath, 'fileLoading', fileLoading[rPath])
    // loop waiting for browser to finish loading
    if (fileLoading[rPath]) {
      log(LOG, 'checkPushStream', 'fileLoading = true', rPath)

      if (++attempts > 50) {
        // ceil attempts to avoid locks
        log(LOG, 'ATTEMPTS > 50!!')
        fileLoading[rPath] = false
        scriptWaiting[rPath] = false
      }
      else {
        // loop
        setTimeout(() => checkPushStream(true), 20)
        return
      }
    }

    // fileLoading[rPath] = true
    scriptWaiting[rPath] = false
    pushStream()
  }

  // internals debounce
  if (cache.isExported(path)) {
    log(LOG, 'is exported')
    clearTimeout(internalTimeout)
    internalTimeout = setTimeout(pushStream, 1000)
  }
  else {
    checkPushStream()
  }
}

// ignore stream when loading file in browser
function initScriptWait() {
  // bridge.on('script:load', ({ path }) => {
  //   log(LOG, 'script:load', path)
  //   // fileLoading[path] = true
  // })

  bridge.on('script:done', ({ path }) => {
    log(LOG, 'script:done', path)
    fileLoading[path] = false
  })
}

function init() {
  basePath = opts.get('appDir')
  flintPath = opts.get('flintDir')

  initScriptWait()

  // throttle the stream a bit
  let fileSender = _.throttle(fileSend, 22, { leading: true })

  bridge.on('live:save', fileSender)
}

function vinyl(path, contents) {
  const cwd = '/'
  const base = basePath + '/'
  return { cwd, base, path, contents }
}

export default { init, stream }

@@ -178,16 +178,22 @@
 ort %7B _,
+ path,
  log, re
@@ -232,16 +232,16 @@
 ib/fns'%0A
-
 %0Aconst L
@@ -423,16 +423,95 @@
 g = %7B%7D%0A%0A
+function isFileType(_path, ext) %7B%0A  return path.extname(_path) == %60.$%7Bext%7D%60%0A%7D%0A%0A
 function
@@ -708,16 +708,43 @@
 h) === 0
+ %7C%7C !isFileType(path, 'js')
 ) %7B%0A    
@@ -757,16 +757,23 @@
 G, 'file
+ no JS,
  not in 
@@ -781,19 +781,23 @@
 ath, or 
+is 
 in 
+.
 flint di

verify file path