/**
*
* @author James Gosling
*/
import java.io.*;
import java.util.*;
import java.util.ArrayList;
import java.util.regex.*;

public class BibReorder {
 String[] parts;
 DocumentFragment[] documentBody, bibliography;
 static Pattern bibRefPattern = Pattern.compile("\\[([0-9]+)\\]");
 public static void main(String[] args) {
   try {
     BibReorder doc = new BibReorder();
     boolean byFirstOccurrance = false;
     boolean processed = false;
     for(String s:args)
       if("-f".equals(s)) byFirstOccurrance = true;
       else {
         processed = true;
         doc.load(new FileInputStream(s));
         doc.reorder(byFirstOccurrance);
         doc.dumpDocument();
       }
     if(!processed) {
       doc.load(BibReorder.class.getResource("sample. Data").openStream());
       doc.reorder(byFirstOccurrance);
       doc.dumpDocument();
     }
   } catch (IOException ex) {
     System.err.println("Error reading file: "+ex);
   }
 }
 void load(InputStream in) throws IOException {
   Reader inc = new BufferedReader(new InputStreamReader(new BufferedInputStream(in)));
   StringBuilder sb = new StringBuilder();
   int c;
   while((c=inc.read())>=0) sb.append((char)c);
   parts = sb.toString().split("@footnote:");
   if(parts.length!=2) throw new IOException("Must have exactly 2 parts");
   documentBody = parseDocumentPart(parts[0]);
   bibliography = parseDocumentPart(parts[1]);
   in.close();
 }
 void reorder(boolean byFirstOccurrance) {
   int slot = 0;
   if(byFirstOccurrance) {
     for(DocumentFragment p:documentBody)
       if(p.tag!=null && p.tag.sequenceNumber==0) p.tag.sequenceNumber = ++slot;
     Arrays.sort(bibliography, new Comparator<DocumentFragment>(){
       public int compare(DocumentFragment o1, DocumentFragment o2) {
         return (o1.tag==null ? 0 : o1.tag.sequenceNumber)-(o2.tag==null ? 0 : o2.tag.sequenceNumber);
       }
     });
   } else
     for(DocumentFragment p:bibliography)
       if(p.tag!=null) p.tag.sequenceNumber = ++slot;
 }
 void dumpDocument() {
   dumpDocumentPart(documentBody, parts[0]);
   System.out.append("@footnote:");
   dumpDocumentPart(bibliography, parts[1]);
 }
 DocumentFragment[] parseDocumentPart(String s) {
   Matcher m = bibRefPattern.matcher(s);
   DocumentFragment prev = new DocumentFragment(0,null);
   ArrayList<DocumentFragment> pieces = new ArrayList<DocumentFragment>();
   pieces.add(prev);
   while(m.find()) {
     prev.end = m.start(0);
     String tlabel = s.substring(m.start(1),m.end(1));
     BibliographyTag t = tags.get(tlabel);
     if(t==null) { t = new BibliographyTag();
            tags.put(tlabel, t); }
     prev = new DocumentFragment(m.end(0),t);
     pieces.add(prev);
   }
   prev.end = s.length();
   return pieces.toArray(new DocumentFragment[pieces.size()]);
 }
 void dumpDocumentPart(DocumentFragment[] pieces, String part) {
   for(DocumentFragment p:pieces) {
     if(p.tag!=null) System.out.print("["+p.tag.sequenceNumber+"]");
     System.out.append(part,p.start,p.end);
   }
 }
 class DocumentFragment {
   int start, end;
   BibliographyTag tag;
   DocumentFragment(int st, BibliographyTag t) { start = st; tag = t; }
 }
 class BibliographyTag { int sequenceNumber; }
 HashMap<String,BibliographyTag> tags = new HashMap<String, BibliographyTag>();
}