// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

module.exports = function (grunt) {
  var log = grunt.log;

  grunt.registerTask("couchserver", 'Run a couch dev proxy server', function () {
    var fs = require("fs"),
        path = require("path"),
        http = require("http"),
        httpProxy = require('http-proxy'),
        send = require('send'),
        urlLib = require('url'),
        options = grunt.config('couchserver'),
        _ = grunt.util._,
        helper = require('./helper.js');

    if (process.env.FAUXTON_PORT) {
      options.port = process.env.FAUXTON_PORT;
    }

    // Options
    var dist_dir = './dist/debug/',
        app_dir = './app',
        port = options.port,
        setContentSecurityPolicy = _.isUndefined(options.contentSecurityPolicy) ? true : options.contentSecurityPolicy;

    // Proxy options with default localhost
    var proxy_settings = options.proxy || {
      target: helper.couch
    };

    // inform grunt that this task is async
    var done = this.async();

    // create proxy to couch for all couch requests
    var proxy = httpProxy.createServer(proxy_settings);

    http.createServer(function (req, res) {
      var url = req.url.replace('app/', ''),
          accept = req.headers.accept && req.headers.accept.split(','),
          filePath;

      if (setContentSecurityPolicy) {
        var headerValue = "default-src 'self'; img-src 'self' data:; font-src 'self'; " +
                          "script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline';";

        if (options.contentSecurityPolicyHeader) {
          headerValue = options.contentSecurityPolicyHeader;
        }

        res.setHeader('Content-Security-Policy', headerValue);
      }

      if (!!url.match(/^\/addons\/.*\/assets\/js/)) {
        filePath = path.join(app_dir, url.replace('/_utils/fauxton/', ''));
      } else if (!!url.match(/dashboard\.assets/)) {
        url = url.replace(/\?.*/, '');
        filePath = path.join(dist_dir, url);
      } else if (!!url.match(/assets/)) {
        // serve any javascript or css files from here assets dir
        url = url.replace(/\?.*/, '');
        filePath = path.join('./', url);
      } else if (!!url.match(/mocha|\/test\/core\/|test\.config/)) {
        filePath = path.join('./test', url.replace('/test/', ''));
      } else if (!!url.match(/fonts/)) {
        url = url.replace(/\?.*/, ''); // IE
        filePath = path.join(dist_dir, url.split('?v=')[0]);
      } else if (!!url.match(/\.css|img/)) {
        url = url.replace(/\?.*/, '');
        filePath = path.join(dist_dir, url);
      } else if (!!url.match(/\.js(\?_.*)?$|\.html(\?_.*)?$/)) {
        // server js from app directory
        url = url.replace(/\?_.*/, '');
        filePath = path.join(app_dir, url.replace('/_utils/fauxton/', ''));
      // handles local references to any addon dependencies (e.g. ZeroClipboard.swf)
      } else if (!!url.match(/addons\/[^\/]+\/dependencies\/.+/)) {
        var urlNoQueryStr = url.replace(/\?.*$/, '');
        filePath = './app' + urlNoQueryStr;
      } else if (!!url.match(/testrunner/)) {
        var testSetup = grunt.util.spawn({cmd: 'grunt', grunt: true, args: ['test_inline']}, function (error, result, code) {/* log.writeln(String(result));*/ });
        testSetup.stdout.pipe(process.stdout);
        testSetup.stderr.pipe(process.stderr);
        filePath = path.join('./test/runner.html');
      } else if (url === '/' && accept && accept[0] !== 'application/json') {
        // serve main index file from here
        filePath = path.join(dist_dir, 'index.html');
      }

      if (/_utils\/docs/.test(filePath)) {
        filePath = false;
      }

      if (filePath) {
        return send(req, filePath)
          .on('error', function (err) {
            if (err.status === 404) {
              log.writeln('Could not locate', filePath);
            } else {
              log.writeln('ERROR', filePath, err);
            }

            res.setHeader("Content-Type", "text/javascript");
            res.statusCode = 404;
            res.end(JSON.stringify({error: err.message}));
          })
          .pipe(res);
      }

      // This sets the Host header in the proxy so that one can use external
      // CouchDB instances and not have the Host set to 'localhost'
      var urlObj = urlLib.parse(req.url);
      req.headers.host = urlObj.host;


      proxy.web(req, res);
    }).listen(port);

    proxy.on('error', function (e) {
      // don't explode on cancelled requests
    });

    //Remove Secure on the cookie if the proxy is communicating to a CouchDB instance
    // via https.
    proxy.on('proxyRes', function (proxyRes, req, res) {
      if (proxyRes.headers['set-cookie']) {
        proxyRes.headers['set-cookie'][0] = proxyRes.headers["set-cookie"][0].replace('Secure', '');
      }
    });

    // Fail this task if any errors have been logged
    if (grunt.errors) {
      return false;
    }

    var watch = grunt.util.spawn({cmd: 'grunt', grunt: true, args: ['watch']}, function (error, result, code) {/* log.writeln(String(result));*/ });

    watch.stdout.pipe(process.stdout);
    watch.stderr.pipe(process.stderr);

    var logo = [
      [""],
      [" ______                        _                   "],
      ["|  ____|                      | |                  "],
      ["| |__    __ _   _   _  __  __ | |_    ___    _ __  "],
      ["|  __|  / _` | | | | | \\ \\/ / | __|  / _ \\  | '_ \\ "],
      ["| |    | (_| | | |_| |  >  <  | |_  | (_) | | | | |"],
      ["|_|     \\__,_|  \\__,_| /_/\\_\\  \\__|  \\___/  |_| |_|"],
      [""]
   ];

    _.each(logo, function (line) {
      console.log(line.toString());
    });

    log.writeln('Listening on ' + port);
  });

};
