// Generated by CoffeeScript 2.3.2
(function() {
  module.exports = function(settings) {
    var Express, P, Path, Promise, SearchRequestBuilder, augment, call, cheerio, console, errorHandler, es, handler, host, https, i, j, jsonP, k, len, len1, len2, mP, mod, morgan, mountPoint, opts, plugin, preserveHostHdr, proxy, ref, ref1, ref2, ref3, ref4, sendResponse, service, spec, stderr, stdout;
    Promise = require("bluebird");
    Path = require("path");
    Express = require("express");
    SearchRequestBuilder = require("./config-types/search-request-builder");
    morgan = require("morgan");
    proxy = require("express-http-proxy");
    errorHandler = require("errorhandler");
    cheerio = require("cheerio");
    call = require("./call");
    es = settings.elasticSearch;
    ({stdout, stderr, console} = settings.io);
    P = function(handler) {
      return function(req, res) {
        return Promise.resolve(handler(req)).then(function(data) {
          return res.send(data);
        }).catch(function(err) {
          console.error("error", err.stack || err);
          return res.status(err.status).send(err);
        });
      };
    };
    jsonP = function(f) {
      return function(req, res, next) {
        var err, failure, success;
        success = function(obj) {
          return res.json(obj);
        };
        failure = function(err) {
          var ref, ref1;
          console.error("error", err.stack || err);
          console.error("error", err);
          return res.status((ref = (ref1 = err.status) != null ? ref1 : err.statusCode) != null ? ref : 500).send(err);
        };
        try {
          return Promise.resolve(f(req, res, next)).done(success, failure);
        } catch (error1) {
          err = error1;
          console.error("error", err.stack || err);
          return res.status(500).send(err);
        }
      };
    };
    service = Express();
    service.set('port', settings.port);
    if (settings.pretty) {
      service.set('json spaces', 2);
    }
    if (settings.plugins != null) {
      ref = settings.plugins;
      for (i = 0, len = ref.length; i < len; i++) {
        plugin = ref[i];
        if (typeof plugin.install === 'function') {
          plugin.install(service, settings, es);
        } else {
          console.error('function install missing in plugin');
        }
      }
    }
    ref1 = settings.static;
    for (mountPoint in ref1) {
      spec = ref1[mountPoint];
      if (typeof spec === "string") {
        console.log(`mounting ${spec} at ${mountPoint}`);
        service.use(mountPoint, Express.static(spec));
      }
      if (typeof spec === "object") {
        for (j = 0, len1 = spec.length; j < len1; j++) {
          mP = spec[j];
          console.log(`mounting ${mP} at ${mountPoint}`);
          service.use(mountPoint, Express.static(mP));
        }
      }
    }
    ref2 = settings.proxy;
    for (mountPoint in ref2) {
      ({host, augment, https, preserveHostHdr} = ref2[mountPoint]);
      console.log(`forwarding ${mountPoint} to ${host}`);
      opts = {
        forwardPath: function(req, res) {
          var path;
          path = req.originalUrl;
          return path;
        }
      };
      if (https != null) {
        opts.https = https;
      }
      if (preserveHostHdr != null) {
        opts.preserveHostHdr = preserveHostHdr;
      }
      if (augment != null) {
        opts.intercept = function(rsp, data0, req, res, callback) {
          var $, data, href, k, l, len2, len3, ref3, ref4, ref5, ref6, ref7, src;
          if ((ref3 = rsp.headers["content-type"]) != null ? ref3.startsWith("text/html") : void 0) {
            console.log("augmenting");
            $ = cheerio.load(data0.toString());
            ref5 = (ref4 = augment.js) != null ? ref4 : [];
            for (k = 0, len2 = ref5.length; k < len2; k++) {
              src = ref5[k];
              $("body").last().append($("<script>").attr("src", src));
            }
            ref7 = (ref6 = augment.css) != null ? ref6 : [];
            for (l = 0, len3 = ref7.length; l < len3; l++) {
              href = ref7[l];
              $("head").last().append($("<link>").attr("type", "text/css").attr("rel", "stylesheet").attr("href", href));
            }
            data = $.html();
          } else {
            data = data0;
          }
          return callback(null, data);
        };
      }
      service.use(mountPoint, proxy(host, opts));
    }
    ref3 = settings.dynamic;
    for (mountPoint in ref3) {
      mod = ref3[mountPoint];
      service.get(mountPoint, require(mod));
    }
    service.use('/_irma', Express.static(Path.join(__dirname, '..', 'static')));
    service.use(morgan('dev', {
      stream: settings.io.stdout
    }));
    service.use(errorHandler({
      log: function(err, str, req) {
        return settings.io.console.error(str);
      }
    }));
    service.get('/_irma', function(req, res) {
      return res.json({
        apiVersion: require("../package.json").version
      });
    });
    service.get('/_irma/analyze', jsonP(function(req) {
      return es.analyze(req, settings)({
        field: req.query.field,
        text: req.query.q
      });
    }));
    service.get('/:type/search', function(req, res) {
      var identity, ref4, ref5, ref6, ref7, ref8, requestFilter, responseFilter, searchRequest, type, typeName, viewName;
      viewName = req.query.view;
      typeName = req.params.type;
      searchRequest = {
        query: req.query,
        type: typeName
      };
      type = (ref4 = settings.types[typeName]) != null ? ref4 : {};
      identity = function() {
        return function(x) {
          return x;
        };
      };
      requestFilter = (ref5 = (ref6 = type.searchRequestFilter) != null ? ref6 : settings.searchRequestFilter) != null ? ref5 : identity;
      responseFilter = (ref7 = (ref8 = type.searchResponseFilter) != null ? ref8 : settings.searchResponseFilter) != null ? ref7 : identity;
      //.then es.search
      return Promise.resolve(searchRequest).then(call(requestFilter)(searchRequest, settings)).then(es.search(searchRequest, settings)).then(call(responseFilter)(searchRequest, settings)).then(sendResponse(res)).catch(function(err) {
        var ref10, ref9;
        console.error((ref9 = err.stack) != null ? ref9 : err);
        return res.status((ref10 = err.status) != null ? ref10 : 500).send(err);
      });
    });
    sendResponse = function(res) {
      return function({data, mimeType, headers = {}}) {
        var encoder, header, ref4, value;
        for (header in headers) {
          value = headers[header];
          res.set(header, value);
        }
        if (mimeType != null) {
          res.set('Content-Type', mimeType);
          encoder = (ref4 = settings.bodyEncoders) != null ? ref4[mimeType] : void 0;
          if (encoder == null) {
            throw new Error(`no encoder configured for ${mimeType}`);
          }
          return encoder.encode(data).then(function(encodedData) {
            return res.send(encodedData);
          });
        } else {
          return res.send(data);
        }
      };
    };
    service.get('/:type/random', jsonP(function(req) {
      var options, ref4;
      options = {
        seed: (ref4 = req.query.seed) != null ? ref4 : Date.now(),
        query: req.query,
        type: req.params.type
      };
      return es.random(req, settings)(options);
    }));
    service.get('/:type/:id', jsonP(function(req, res, next) {
      var ref4, tf;
      tf = (ref4 = settings.types[req.params.type]) != null ? ref4.documentTransform : void 0;
      return es.get(req, settings)({
        id: req.params.id,
        typeName: req.params.type
      }).then(function(body) {
        if ((tf != null) && (tf.transform != null)) {
          return tf.transform(body._source);
        } else {
          return body._source;
        }
      }).catch(function(error) {
        if ((settings.postPlugins != null) && error.status === 404) {
          return next();
        } else {
          console.error(error);
          throw error;
        }
      });
    }));
    if (settings.postPlugins != null) {
      ref4 = settings.postPlugins;
      for (k = 0, len2 = ref4.length; k < len2; k++) {
        handler = ref4[k];
        if (typeof handler.install === 'function') {
          handler.install(service, settings, es);
        } else {
          console.error('function install missing in post plugin');
        }
      }
    }
    return service;
  };

}).call(this);
