import http from "http";
import path from "path";
import fs from "fs";

import mime from "mime";
import { findKey } from "lodash";


function fileNotFound (res) {
  res.writeHead(404);
  res.end();
}

function respondStatic (res, basePath, relativePath) {
  const contentType = mime.lookup(relativePath);
  const realPath = path.join(basePath, relativePath);

  fs.readFile(realPath, (err, data) => {
    if (err) {
      res.writeHead(404);
    } else {
      res.writeHead(200, { "content-type": contentType });
      res.write(data);
    }
    res.end();
  });
}

function sendEvent (connections, id, eventName, data, retryTimeout) {
  const connection = connections[id];
  data = JSON.stringify(data);
  connection.write(`id: ${id}\n`);
  connection.write(`event: ${eventName}\n`);
  connection.write(`retry: ${retryTimeout}\n`);
  connection.write(`data: ${data}\n\n`);
}


export function createServer (opts = {}) {
  const eventsUrl = opts.eventsUrl || "/ilk/events";
  const connections = {};
  let nextConnectionID = 0;

  let dynamicResources = {};
  let shouldRespond = Promise.resolve();

  function pause () {
    let resume;
    shouldRespond = new Promise(_resolve => resume = _resolve);
    return resume;
  }

  function setDynamicAssets (assets) { dynamicResources = assets; }

  function notify (eventName, data) {
    Object.keys(connections).forEach(key => {
      if (!connections[key]) { return; }
      sendEvent(connections, key, eventName, data, opts.retryTimeout);
    });
  }

  const server = http.createServer((req, res) => {
    shouldRespond.then(() => { // eslint-disable-line max-statements
      const acceptType = req.headers.accept;
      const url = req.url.toLowerCase();

      if (url === eventsUrl && acceptType === "text/event-stream") {
        const id = ++nextConnectionID;
        connections[id] = res;
        res.writeHead(200, {
          "Content-Type": "text/event-stream",
          "Cache-Control": "no-cache",
          "Connection": "keep-alive"
        });

        res.on("close", function () {
          connections[id] = null;
        });

        return;
      } else if (url in dynamicResources) {
        const contentType = mime.lookup(url);
        res.writeHead(200, { "content-type": contentType });
        res.write(dynamicResources[url]);
        res.end();
        return;
      }
      const staticMatch = findKey(opts.staticResources, pattern => {
        return pattern.test(url);
      });

      if (!staticMatch) {
        fileNotFound(res);
        return;
      }

      const relPath = url.replace(opts.staticResources[staticMatch], "");
      respondStatic(res, staticMatch, relPath);
    });
  });

  server.listen(opts.port);

  return {
    server,
    setDynamicAssets,
    notify,
    pause
  };
}

@@ -63,16 +63,39 @@
 om %22fs%22;
+%0Aimport url from %22url%22;
 %0A%0Aimport
@@ -1702,49 +1702,202 @@
 nst 
-url = req.url.toLowerCase();%0A%0A      if (u
+requestUrl = url.parse(req.url).pathname.toLowerCase();%0A%0A      const requestedResource = dynamicResources%5BrequestUrl%5D %7C%7C%0A        dynamicResources%5B%60$%7BrequestUrl%7D/index.html%60%5D;%0A%0A      if (requestU
 rl =
@@ -2307,30 +2307,25 @@
 if (
-url in dynamic
+requested
 Resource
 s) %7B
@@ -2320,17 +2320,16 @@
 Resource
-s
 ) %7B%0A    
@@ -2364,17 +2364,24 @@
 .lookup(
-u
+requestU
 rl);%0A   
@@ -2456,31 +2456,33 @@
 s.write(
-dynamic
+requested
 Resource
 s%5Burl%5D);
@@ -2477,14 +2477,8 @@
 urce
-s%5Burl%5D
 );%0A 
@@ -2616,17 +2616,24 @@
 rn.test(
-u
+requestU
 rl);%0A   
@@ -2740,17 +2740,24 @@
 lPath = 
-u
+requestU
 rl.repla

Add server support for URLs with query-strings and `index.html` resolution.