// 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.



var Views = (function() {

  var map_results = []; // holds temporary emitted values during doc map

  function runReduce(reduceFuns, keys, values, rereduce) {
    var code_size = 0;
    for (var i in reduceFuns) {
      var fun_body =  reduceFuns[i];
      code_size += fun_body.length;
      reduceFuns[i] = Couch.compileFunction(fun_body);
    };
    var reductions = new Array(reduceFuns.length);
    for(var i = 0; i < reduceFuns.length; i++) {
      try {
        reductions[i] = reduceFuns[i](keys, values, rereduce);
      } catch (err) {
        handleViewError(err);
        // if the error is not fatal, ignore the results and continue
        reductions[i] = null;
      }
    };
    var reduce_line = JSON.stringify(reductions);
    var reduce_length = reduce_line.length;
    var input_length =  State.line_length - code_size
    // TODO make reduce_limit config into a number
    if (State.query_config && State.query_config.reduce_limit &&
          reduce_length > 4096 && ((reduce_length * 2) > input_length)) {
      var log_message = [
          "Reduce output must shrink more rapidly:",
          "input size:", input_length,
          "output size:", reduce_length
      ].join(" ");
      if (State.query_config.reduce_limit === "log") {
          log("reduce_overflow_error: " + log_message);
          print("[true," + reduce_line + "]");
      } else {
          throw(["error", "reduce_overflow_error", log_message]);
      };
    } else {
      print("[true," + reduce_line + "]");
    }
  };

  function handleViewError(err, doc) {
    if (err == "fatal_error") {
      // Only if it's a "fatal_error" do we exit. What's a fatal error?
      // That's for the query to decide.
      //
      // This will make it possible for queries to completely error out,
      // by catching their own local exception and rethrowing a
      // fatal_error. But by default if they don't do error handling we
      // just eat the exception and carry on.
      //
      // In this case we abort map processing but don't destroy the 
      // JavaScript process. If you need to destroy the JavaScript 
      // process, throw the error form matched by the block below.
      throw(["error", "map_runtime_error", "function raised 'fatal_error'"]);
    } else if (err[0] == "fatal") {
      // Throwing errors of the form ["fatal","error_key","reason"]
      // will kill the OS process. This is not normally what you want.
      throw(err);
    }
    var message = "function raised exception " +
                  (err.toSource ? err.toSource() : err.stack);
    if (doc) message += " with doc._id " + doc._id;
    log(message);
  };

  return {
    // view helper functions
    emit : function(key, value) {
      map_results.push([key, value]);
    },
    sum : function(values) {
      var rv = 0;
      for (var i in values) {
        rv += values[i];
      }
      return rv;
    },
    reduce : function(reduceFuns, kvs) {
      var keys = new Array(kvs.length);
      var values = new Array(kvs.length);
      for(var i = 0; i < kvs.length; i++) {
          keys[i] = kvs[i][0];
          values[i] = kvs[i][1];
      }
      runReduce(reduceFuns, keys, values, false);
    },
    rereduce : function(reduceFuns, values) {
      runReduce(reduceFuns, null, values, true);
    },
    mapDoc : function(doc) {
      // Compute all the map functions against the document.
      //
      // Each function can output multiple key/value pairs for each document.
      //
      // Example output of map_doc after three functions set by add_fun cmds:
      // [
      //  [["Key","Value"]],                    <- fun 1 returned 1 key value
      //  [],                                   <- fun 2 returned 0 key values
      //  [["Key1","Value1"],["Key2","Value2"]] <- fun 3 returned 2 key values
      // ]
      //

      Couch.recursivelySeal(doc);

      var buf = [];
      for each (fun in State.funs) {
        map_results = [];
        try {
          fun(doc);
          buf.push(map_results);
        } catch (err) {
          handleViewError(err, doc);
          // If the error is not fatal, we treat the doc as if it
          // did not emit anything, by buffering an empty array.
          buf.push([]);
        }
      }
      print(JSON.stringify(buf));
    }
  };
})();
