package com.googlecode.totallylazy.records.lucene;

import com.googlecode.totallylazy.LazyException;
import com.googlecode.totallylazy.Predicate;
import com.googlecode.totallylazy.Sequence;
import com.googlecode.totallylazy.records.AbstractRecords;
import com.googlecode.totallylazy.records.Keyword;
import com.googlecode.totallylazy.records.Record;
import com.googlecode.totallylazy.records.lucene.mappings.Mappings;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;

import java.io.IOException;
import java.util.Iterator;

import static com.googlecode.totallylazy.numbers.Numbers.increment;
import static com.googlecode.totallylazy.records.SelectCallable.select;
import static com.googlecode.totallylazy.records.lucene.Lucene.RECORD_KEY;

public class LuceneRecords extends AbstractRecords {
    private final Directory directory;
    private final IndexWriter writer;
    private final Mappings mappings;

    public LuceneRecords(final Directory directory, final IndexWriter writer, final Mappings mappings) throws IOException {
        this.directory = directory;
        this.writer = writer;
        this.mappings = mappings;
    }

    public Sequence<Record> get(final Keyword recordName) {
        return new Sequence<Record>() {
            public Iterator<Record> iterator() {
                return new DocumentIterator(directory, mappings, definitions(recordName));
            }
        };
    }

    public boolean exists(Keyword recordName) {
        throw new UnsupportedOperationException();
    }

    public Number add(Keyword recordName, Sequence<Keyword> fields, Sequence<Record> records) {
        try {
            Number count = 0;
            for (Document document : records.map(select(fields)).map(mappings.asDocument(recordName, definitions(recordName)))) {
                writer.addDocument(document);
                count = increment(count);
            }
            writer.commit();
            return count;
        } catch (IOException e) {
            throw new LazyException(e);
        }
    }

    public Number set(Keyword recordName, Predicate<? super Record> predicate, Sequence<Keyword> fields, Record record) {
        throw new UnsupportedOperationException();
    }

    public Number remove(Keyword recordName, Predicate<? super Record> predicate) {
        throw new UnsupportedOperationException();
    }

    public Number remove(Keyword recordName) {
        try {
            writer.deleteDocuments(new TermQuery(new Term(RECORD_KEY.toString())));
            return -1;
        } catch (IOException e) {
            throw new LazyException(e);
        }
    }
}

@@ -183,16 +183,139 @@
 quence;%0A
+import com.googlecode.totallylazy.predicates.EqualsPredicate;%0Aimport com.googlecode.totallylazy.predicates.WherePredicate;%0A
 import c
@@ -695,68 +695,9 @@
 rch.
-MatchAllDocsQuery;%0Aimport org.apache.lucene.search.TermQuery
+*
 ;%0Aim
@@ -2564,24 +2564,901 @@
 redicate) %7B%0A
+        return remove(and(record(recordName), query(predicate)));%0A    %7D%0A%0A    private Query and(Query... queries) %7B%0A        BooleanQuery booleanQuery = new BooleanQuery();%0A        for (Query query : queries) %7B%0A            booleanQuery.add(query, BooleanClause.Occur.MUST);%0A        %7D%0A        return booleanQuery;%0A    %7D%0A%0A    private Query query(Predicate%3C? super Record%3E predicate) %7B%0A        if(predicate instanceof WherePredicate)%7B%0A            return where((WherePredicate) predicate);%0A        %7D%0A        throw new UnsupportedOperationException();%0A    %7D%0A%0A    private Query where(WherePredicate where) %7B%0A        Keyword keyword = (Keyword) where.callable();%0A        Predicate predicate = where.predicate();%0A        if(predicate instanceof EqualsPredicate)%7B%0A            return new TermQuery(new Term(keyword.toString(), ((EqualsPredicate) predicate).value().toString()));%0A        %7D%0A
         thro
@@ -3562,95 +3562,289 @@
     
-try %7B
+return remove(record(recordName));
 %0A    
+%7D%0A%0A
     
-    writer.deleteDocuments(new TermQuery(new Term(RECORD_KEY.toString()))
+private TermQuery record(Keyword recordName) %7B%0A        return new TermQuery(new Term(RECORD_KEY.toString(), recordName.toString()));%0A    %7D%0A%0A    private Number remove(Query query) %7B%0A        try %7B%0A            writer.deleteDocuments(query
 );%0A 

Work in progress