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

couchTests.etags_views = function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"true"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;

  var designDoc = {
    _id: "_design/etags",
    language: "javascript",
    views : {
      fooView: {
        map: stringFun(function(doc) {
          if (doc.foo) {
            emit("bar", 1);
          }
        }),
      },
      basicView : {
        map : stringFun(function(doc) {
          if(doc.integer && doc.string) {
            emit(doc.integer, doc.string);
          }
        })
      },
      withReduce : {
        map : stringFun(function(doc) {
          if(doc.integer && doc.string) {
            emit(doc.integer, doc.string);
          }
        }),
        reduce : stringFun(function(keys, values, rereduce) {
          if (rereduce) {
            return sum(values);
          } else {
            return values.length;
          }
        })
      }
    }
  };
  T(db.save(designDoc).ok);
  db.bulkSave(makeDocs(0, 10));

  var xhr;

  // verify get w/Etag on map view
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView");
  T(xhr.status == 200);
  var etag = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView", {
    headers: {"if-none-match": etag}
  });
  T(xhr.status == 304);

  // verify ETag doesn't change when an update
  // doesn't change the view group's index
  T(db.save({"_id":"doc1", "foo":"bar"}).ok);
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView");
  var etag1 = xhr.getResponseHeader("etag");
  T(etag1 == etag);

  // verify ETag always changes for include_docs=true on update
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView?include_docs=true");
  var etag1 = xhr.getResponseHeader("etag");
  T(db.save({"_id":"doc2", "foo":"bar"}).ok);
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView?include_docs=true");
  var etag2 = xhr.getResponseHeader("etag");
  T(etag1 != etag2);
 
  // Verify that purges affect etags
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/fooView");
  var foo_etag = xhr.getResponseHeader("etag");
  var doc1 = db.open("doc1");
  xhr = CouchDB.request("POST", "/test_suite_db/_purge", {
    body: JSON.stringify({"doc1":[doc1._rev]})
  });
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/fooView");
  var etag1 = xhr.getResponseHeader("etag");
  T(etag1 != foo_etag);

  // Test that _purge didn't affect the other view etags.
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView");
  var etag1 = xhr.getResponseHeader("etag");
  T(etag1 == etag);

  // verify different views in the same view group may have different ETags
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/fooView");
  var etag1 = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView");
  var etag2 = xhr.getResponseHeader("etag");
  T(etag1 != etag2);

  // verify ETag changes when an update changes the view group's index.
  db.bulkSave(makeDocs(10, 20));
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView");
  var etag1 = xhr.getResponseHeader("etag");
  T(etag1 != etag);

  // verify ETag is the same after a restart
  restartServer();
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView");
  var etag2 = xhr.getResponseHeader("etag");
  T(etag1 == etag2);

  // reduce view
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce");
  T(xhr.status == 200);
  var etag = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce",{
    headers: {"if-none-match": etag}
  });
  T(xhr.status == 304);

  // verify ETag doesn't change when an update
  // doesn't change the view group's index
  T(db.save({"_id":"doc3", "foo":"bar"}).ok);
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce");
  var etag1 = xhr.getResponseHeader("etag");
  T(etag1 == etag);
  // purge
  var doc3 = db.open("doc3");
  xhr = CouchDB.request("POST", "/test_suite_db/_purge", {
    body: JSON.stringify({"doc3":[doc3._rev]})
  });
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce");
  var etag1 = xhr.getResponseHeader("etag");
  T(etag1 == etag);

  // verify different views in the same view group may have different ETags
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/fooView");
  var etag1 = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce");
  var etag2 = xhr.getResponseHeader("etag");
  T(etag1 != etag2);

  // verify ETag changes when an update changes the view group's index
  db.bulkSave(makeDocs(20, 30));
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce");
  var etag1 = xhr.getResponseHeader("etag");
  T(etag1 != etag);

  // verify ETag is the same after a restart
  restartServer();
  xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce");
  var etag2 = xhr.getResponseHeader("etag");
  T(etag1 == etag2);

  // confirm ETag changes with different POST bodies
  xhr = CouchDB.request("POST", "/test_suite_db/_design/etags/_view/basicView",
    {body: JSON.stringify({keys:[1]})}
  );
  var etag1 = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("POST", "/test_suite_db/_design/etags/_view/basicView",
    {body: JSON.stringify({keys:[2]})}
  );
  var etag2 = xhr.getResponseHeader("etag");
  T(etag1 != etag2, "POST to map view generates key-depdendent ETags");

  xhr = CouchDB.request("POST",
    "/test_suite_db/_design/etags/_view/withReduce?group=true",
    {body: JSON.stringify({keys:[1]})}
  );
  etag1 = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("POST",
    "/test_suite_db/_design/etags/_view/withReduce?group=true",
    {body: JSON.stringify({keys:[2]})}
  );
  etag2 = xhr.getResponseHeader("etag");
  T(etag1 != etag2, "POST to reduce view generates key-depdendent ETags");
  
  // all docs
  xhr = CouchDB.request("GET", "/test_suite_db/_all_docs");
  T(xhr.status == 200);
  var etag = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("GET", "/test_suite_db/_all_docs", {
    headers: {"if-none-match": etag}
  });
  T(xhr.status == 304);

  // _changes
  xhr = CouchDB.request("GET", "/test_suite_db/_changes");
  T(xhr.status == 200);
  var etag = xhr.getResponseHeader("etag");
  xhr = CouchDB.request("GET", "/test_suite_db/_changes", {
    headers: {"if-none-match": etag}
  });
  T(xhr.status == 304);

  // list etag
  // in the list test for now
  
  // A new database should have unique _all_docs etags. 
  db.deleteDb(); 
  db.createDb(); 
  db.save({a: 1}); 
  xhr = CouchDB.request("GET", "/test_suite_db/_all_docs"); 
  var etag = xhr.getResponseHeader("etag"); 
  db.deleteDb(); 
  db.createDb(); 
  db.save({a: 2}); 
  xhr = CouchDB.request("GET", "/test_suite_db/_all_docs"); 
  var new_etag = xhr.getResponseHeader("etag");
  T(etag != new_etag);
  // but still be cacheable
  xhr = CouchDB.request("GET", "/test_suite_db/_all_docs"); 
  T(new_etag == xhr.getResponseHeader("etag"));
  
};
