package com.github.rnewson.couchdb.lucene;

/**
 * Copyright 2009 Robert Newson
 * 
 * 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.
 */

import java.io.IOException;
import java.util.Scanner;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.NIOFSDirectory;

/**
 * Search entry point.
 */
public final class Search {

	public static void main(final String[] args) {
		try {
			IndexReader reader = null;
			IndexSearcher searcher = null;

			final Scanner scanner = new Scanner(System.in);
			while (scanner.hasNextLine()) {
				if (reader == null) {
					// Open a reader and searcher if index exists.
					if (IndexReader.indexExists(Config.INDEX_DIR)) {
						reader = IndexReader.open(NIOFSDirectory.getDirectory(Config.INDEX_DIR), true);
						searcher = new IndexSearcher(reader);
					}
				}

				final String line = scanner.nextLine();

				// Process search request if index exists.
				if (searcher == null) {
					System.out.println(Utils.error(503, "couchdb-lucene not available."));
					continue;
				}

				final JSONObject obj;
				try {
					obj = JSONObject.fromObject(line);
				} catch (final JSONException e) {
					System.out.println(Utils.error(400, "invalid JSON."));
					continue;
				}

				if (!obj.has("query")) {
					System.out.println(Utils.error(400, "No query found in request."));
					continue;
				}

				final JSONObject query = obj.getJSONObject("query");

				final boolean reopen = !"ok".equals(query.optString("stale", "not-ok"));

				// Refresh reader and searcher if necessary.
				if (reader != null && reopen) {
					final IndexReader newReader = reader.reopen();
					if (reader != newReader) {
						Log.outlog("Lucene index was updated, reopening searcher.");
						final IndexReader oldReader = reader;
						reader = newReader;
						searcher = new IndexSearcher(reader);
						oldReader.close();
					}
				}

				try {
					// A query.
					if (query.has("q")) {
						final SearchRequest request = new SearchRequest(obj);
						final String result = request.execute(searcher);
						System.out.println(result);
						continue;
					}
					// info.
					if (query.keySet().isEmpty()) {
						final JSONObject json = new JSONObject();
						json.put("doc_count", reader.numDocs());
						json.put("doc_del_count", reader.numDeletedDocs());
						json.put("last_modified", IndexReader.lastModified(Config.INDEX_DIR));
						json.put("current", reader.isCurrent());
						json.put("optimized", reader.isOptimized());
						json.put("disk_size", size(reader.directory()));
						reader.directory();

						final JSONObject info = new JSONObject();
						info.put("code", 200);
						info.put("json", json);
						final JSONObject headers = new JSONObject();
						headers.put("Content-Type", "text/plain");
						info.put("headers", headers);

						System.out.println(info);
					}
				} catch (final Exception e) {
					System.out.println(Utils.error(400, e));
				}

				System.out.println(Utils.error(400, "Bad request."));
			}
			if (reader != null) {
				reader.close();
			}
		} catch (final Exception e) {
			System.out.println(Utils.error(500, e.getMessage()));
		}
	}

	private static long size(final Directory dir) throws IOException {
		long result = 0;
		for (final String name : dir.list()) {
			result += dir.fileLength(name);
		}
		return result;
	}

}

@@ -691,16 +691,46 @@
 anner;%0A%0A
+import net.sf.json.JSONArray;%0A
 import n
@@ -827,24 +827,80 @@
 ndexReader;%0A
+import org.apache.lucene.index.IndexReader.FieldOption;%0A
 import org.a
@@ -2975,221 +2975,421 @@
 ut(%22
-doc_count%22, reader.numDocs());%0A%09%09%09%09%09%09json.put(%22doc_del_count%22, reader.numDeletedDocs());%0A%09%09%09%09%09%09json.put(%22last_modified%22, IndexReader.lastModified(Config.INDEX_DIR));%0A%09%09%09%09%09%09json.put(%22current%22, reader.isCurrent()
+current%22, reader.isCurrent());%0A%09%09%09%09%09%09json.put(%22disk_size%22, size(reader.directory()));%0A%09%09%09%09%09%09json.put(%22doc_count%22, reader.numDocs());%0A%09%09%09%09%09%09json.put(%22doc_del_count%22, reader.numDeletedDocs());%0A%09%09%09%09%09%09final JSONArray fields = new JSONArray();%0A%09%09%09%09%09%09for (final Object field : reader.getFieldNames(FieldOption.INDEXED)) %7B%0A%09%09%09%09%09%09%09if (((String) field).startsWith(%22_%22))%0A%09%09%09%09%09%09%09%09continue;%0A%09%09%09%09%09%09%09fields.add(field
 );%0A
+%09%09%09%09%09%09%7D%0A
 %09%09%09%09
@@ -3404,121 +3404,151 @@
 ut(%22
-optimized%22, reader.isOptimized());%0A%09%09%09%09%09%09json.put(%22disk_size%22, size(reader.directory()));%0A%09%09%09%09%09%09reader.directory(
+fields%22, fields);%0A%09%09%09%09%09%09json.put(%22last_modified%22, IndexReader.lastModified(Config.INDEX_DIR));%0A%09%09%09%09%09%09json.put(%22optimized%22, reader.isOptimized()
 );%0A%0A

include searchable/sortable fields in info.