package com.senseidb.clue.commands;

import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.DocsAndPositionsEnum;
import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;

import com.senseidb.clue.ClueContext;

public class ReconstructCommand extends ClueCommand {

  public ReconstructCommand(ClueContext ctx) {
    super(ctx);
  }

  @Override
  public String getName() {
    return "reconstruct";
  }

  @Override
  public String help() {
    return "reconstructs an indexed field for a document";
  }
  
  public String reconstructWithPositions(TermsEnum te, int docid, Bits liveDocs) throws IOException{
    TreeMap<Integer,List<String>> docTextMap = new TreeMap<Integer,List<String>>();
    BytesRef text;
    DocsAndPositionsEnum dpe = null;
    while ((text = te.next()) != null) {
      dpe = te.docsAndPositions(liveDocs, dpe);
      int iterDoc;
      while ((iterDoc = dpe.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
        if (iterDoc == docid) {
          int freq = dpe.freq();
          for (int i = 0; i < freq; ++i) {
            int pos = dpe.nextPosition();
            List<String> textList = docTextMap.get(pos);
            if (textList == null) {
              textList = new ArrayList<String>();
              docTextMap.put(pos, textList);
            }
            textList.add(text.utf8ToString());
          }
        }
      }
    }
    StringBuffer buf = new StringBuffer();
    for (Entry<Integer, List<String>> entry : docTextMap.entrySet()) {
      Integer pos = entry.getKey();
      List<String> terms = entry.getValue();
      for (String term : terms) {
        buf.append(term+"("+pos+") ");
      }
    }
    return buf.toString();
  }

  public String reconstructNoPositions(TermsEnum te, int docid, Bits liveDocs) throws IOException{
    List<String> textList = new ArrayList<String>();
    BytesRef text;
    DocsEnum dpe = null;
    while ((text = te.next()) != null) {
      dpe = te.docs(liveDocs, dpe);
      int iterDoc;
      while ((iterDoc = dpe.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
        if (iterDoc == docid) {
          textList.add(text.utf8ToString());
        }
      }
    }
    StringBuffer buf = new StringBuffer();
    for (String s : textList) {
      buf.append(s+" ");
    }
    return buf.toString();
  }

  
  @Override
  public void execute(String[] args, PrintStream out) throws Exception {
    if (args.length != 2) {
      out.println("usage: field doc");
      return;
    }
    
    String field = args[0];
    
    int doc = Integer.parseInt(args[1]);
    
    IndexReader reader = ctx.getIndexReader();
    List<AtomicReaderContext> leaves = reader.leaves();
    
    boolean found = false;
    
    
    for (AtomicReaderContext ctx : leaves) {
      AtomicReader atomicReader = ctx.reader();
      FieldInfo finfo = atomicReader.getFieldInfos().fieldInfo(field);
      if (finfo == null) continue;
      
      if (!finfo.isIndexed()) {
        out.println(field+" is not an indexed field");
        return;
      }
      int docID = doc - ctx.docBase;
      if (docID >= 0) {
        Terms terms = atomicReader.terms(field);
        boolean hasPositions  = terms.hasPositions();
        
        TermsEnum te = terms.iterator(null);
        if (hasPositions) {
          out.println(reconstructWithPositions(te, docID, atomicReader.getLiveDocs()));
        }
        else {
          out.println(reconstructNoPositions(te, docID, atomicReader.getLiveDocs()));
        }
        found = true;
        break;
      }
    }
    
    if (!found) {
      out.println(doc + " not found");
      return;
    }
    
    
  }

}

@@ -1363,93 +1363,37 @@
 rDoc
-;%0A      while ((iterDoc = dpe.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) %7B%0A 
+ = dpe.advance(docid);%0A
       
- 
 if (
@@ -1404,34 +1404,32 @@
 Doc == docid) %7B%0A
-  
         int freq
@@ -1447,26 +1447,24 @@
 ();%0A        
-  
 for (int i =
@@ -1490,26 +1490,24 @@
 %7B%0A          
- 
- 
 int pos = dp
@@ -1520,26 +1520,24 @@
 Position();%0A
-  
           Li
@@ -1585,26 +1585,24 @@
 ;%0A          
-  
 if (textList
@@ -1609,26 +1609,24 @@
  == null) %7B%0A
-  
             
@@ -1673,18 +1673,16 @@
         
-  
 docTextM
@@ -1710,30 +1710,26 @@
 ;%0A          
-  %7D%0A  
+%7D%0A
           te
@@ -1761,28 +1761,16 @@
 ing());%0A
-          %7D%0A
         
@@ -2393,87 +2393,31 @@
 rDoc
-;%0A      while ((iterDoc = dpe.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) %7B%0A  
+ = dpe.advance(docid);%0A
     
@@ -2438,26 +2438,24 @@
 == docid) %7B%0A
-  
         text
@@ -2481,34 +2481,24 @@
 oString());%0A
-        %7D%0A
       %7D%0A    

clean up