/*
 * Copyright (c) 2009, Takeyuki Nagao
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the
 * following conditions are met:
 * 
 *  * Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */

package dvi.v2.cli.tools;
import java.io.File;
import java.io.PrintStream;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;

import dvi.DviException;
import dvi.api.DviContext;
import dvi.api.DviDocument;
import dvi.api.DviPage;
import dvi.ctx.DefaultDviContext;
import dvi.render.EmptyDviExecutorHandler;
import dvi.util.Benchmark;
public class ScanGlyphs {
  public static final class GlyphInfo
  implements Comparable<GlyphInfo>
  {
    private final int fn;
    private final int code;

    public GlyphInfo(int fn, int code)
    {
      this.fn = fn;
      this.code = code;
    }

    public int getFontNumber() {
      return fn;
    }

    public int getCode() {
      return code;
    }
    
    public String toString() {
      return getClass().getName() + "[fontNumber=" + fn + ",code=" + code + "]";
    }
    
    public int hashCode()
    {
      return fn + 33 * code;
    }
    
    public boolean equals(Object o)
    {
      if (o == null || !(o instanceof GlyphInfo)) return false;
      GlyphInfo oo = (GlyphInfo) o;
      return oo.fn == fn && oo.code == code;
    }

    public int compareTo(GlyphInfo o) {
      if (fn < o.fn) {
        return -1;
      } else if (fn > o.fn) {
        return 1;
      } else {
        return code - o.code;
      }
    }
  }
  
  public static final class EmptyDviExecutorHandlerExtension extends
      EmptyDviExecutorHandler {
    private final Set<GlyphInfo> glyphSet = new TreeSet<GlyphInfo>();
    private int fn = -1;

    public void doSet(int code) throws DviException {
      glyphSet.add(new GlyphInfo(fn, code));
    }

    public void doPut(int code) throws DviException {
      doSet(code);
    }

    public void doSelectFont(int fn) throws DviException {
      this.fn = fn;
    }

    public Set<GlyphInfo> getGlyphSet() {
      return Collections.unmodifiableSet(glyphSet);
    }
  }

  public static void printUsage(PrintStream out)
  {
    out.println(ScanGlyphs.class.getName() + " - Counts number of glyphs in the specified files.");
    out.println("Command line arguments: <input-files>");
  }
  
  public static void main(String[] args)
  throws Exception
  {
    if (args.length <= 0) {
      printUsage(System.out);
      System.out.println("error: No inputs");
    } else {
      final DviContext ctx = new DefaultDviContext();
      for (String filename : args) {
        File file = new File(filename);
        DviDocument doc = ctx.openDviDocument(file.toURL());
        Benchmark bm = new Benchmark();
        bm.begin("Glyphs scan in " + file);
        for (DviPage page : doc.getPages()) {
          FontExecutor exe = new FontExecutor(ctx);
          EmptyDviExecutorHandlerExtension handler = new EmptyDviExecutorHandlerExtension();
          exe.execute(page, handler);
//          System.out.println(handler.glyphSet);
          System.out.println("page=" + page.getPageNumber() + " count=" + handler.glyphSet.size());
          //bm.addSamples(handler.glyphSet.size());
          bm.addSample();
        }
        bm.end();
        System.err.println(bm.format());
      }
    }
  }
}
