import Route from 'route-parser'
import { createHistory } from 'history'
import internal from '../internal'

let Internal
let history, render
let activeID = 1
let routes = {}
let routesList = []
let params = {}
let location = window.location.pathname
let listeners = []

function runListeners(location) {
  listeners.forEach(listener => {
    listener(location)
  })
}

const router = {
  init(appName, { onChange }) {
    Internal = internal.get(appName)
    render = onChange
    history = createHistory()

    // router updates
    history.listen(location => {
      if (Internal.firstRender) return
      router.go(location.pathname, { dontPush: true })
      runListeners(location)
    })
  },

  onChange(cb) {
    if (typeof cb !== 'function')
      throw new Error('Must provide function to Flint.router.onChange')

    listeners.push(cb)
  },

  link(...args) {
    return () => router.go(...args)
  },

  back() { history.goBack() },
  forward() {history.goForward() },

  go(path, opts = {}) {
    // wait for after first render
    if (Internal.firstRender) return setTimeout(() => router.go(path, opts))
    if (!render) return

    // query changes
    if (path[0] === '?')
      path = location + path

    // ensure prefixed with /
    if (path[0] !== '/')
      path = '/' + path

    location = path

    if (!opts.dontPush) history.push(path)
    router.next()
    router.recognize()
    if (!opts.dontRender) render()
  },

  isActive(path) {
    return (
      routes[path] == activeID // /article/:id
      || window.location.pathname == path // /article/123
    )
  },

  next() {
    activeID += 1 // on change route, reset matchers
  },

  recognize() {
    routesList.forEach(({ route, path }) => {
      let routeParams = route.match(location)
      if (routeParams) {
        delete routeParams._
        routes[path] = activeID
        params[path] = routeParams
        router.params = routeParams
      }
    })
  },

  add(path) {
    // this is ridiculous (at the moment, but it works)
    // matches all sub routes, so we can show the whole tree
    let lazy = '(/*_)(/*_)(/*_)(/*_)(/*_)(/*_)(/*_)(/*_)'

    if (typeof path == 'object') {
      let opts = path
      path = opts.path

      if (opts.strict)
        lazy = '/'

    }
    else {
      // TODO: babel needs to add unique key to routematch
      if (routes[path]) return
    }

    const _path = path + lazy
    const route = new Route(_path)

    routesList.push({ route, path })
    routes[path] = activeID

    router.next()
    router.recognize()
  },

  getParams(path) {
    return { params: params[path] }
  }
}

export default router
@@ -1668,24 +1668,45 @@
 cognize() %7B%0A
+    let matches = 0%0A%0A
     routesLi
@@ -1822,33 +1822,230 @@
     
-delete routeParams._%0A    
+matches++%0A        router.setActive(path, routeParams)%0A      %7D%0A    %7D)%0A%0A    // 404%0A    if (!matches && routes%5B404%5D) %7B%0A      router.setActive(404)%0A    %7D%0A  %7D,%0A%0A  setActive(path, params) %7B%0A    if (params) delete params._ // ??%0A
     
@@ -2068,20 +2068,16 @@
 ctiveID%0A
-    
     para
@@ -2087,32 +2087,23 @@
 path%5D = 
-routeP
+p
 arams%0A
-    
     rout
@@ -2118,34 +2118,14 @@
 s = 
-routeParams%0A      %7D%0A    %7D)
+params
 %0A  %7D

add 404 basic support