/*
 * 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.xdoc;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JPanel;

import dvi.DviException;
import dvi.DviRect;
import dvi.DviSize;
import dvi.api.DviContext;
import dvi.api.DviContextSupport;
import dvi.gui.swing.ViewSpec;
import dvi.image.split.SplitImage;
import dvi.image.split.SplitImageUtils;
import dvi.util.DviUtils;
public class XDocumentCanvas extends JPanel implements DviContextSupport {
  private static final Logger LOGGER = Logger.getLogger(XDocumentCanvas.class
      .getName());
  private final XDocument xdoc;
  private final DviContextSupport dcs;
  private int pageNum;
  private ViewSpec viewSpec;
  private final DviSize unit;
  
  public XDocumentCanvas(DviContextSupport dcs, XDocument xdoc, DviSize unit) {
    if (dcs == null) throw new IllegalArgumentException("dcs can't be null.");
    this.dcs = dcs;
    this.xdoc = xdoc;
    this.unit = unit;
    this.setPageNumber(0);
    this.setViewSpec(new ViewSpec(getDviContext()));
    this.addComponentListener(new ComponentListener() {
      public void componentHidden(ComponentEvent e) {
      }
      public void componentMoved(ComponentEvent e) {
      }
      public void componentResized(ComponentEvent e) {
        determinedSize = false;
      }
      public void componentShown(ComponentEvent e) {
      }
    });
  }
  
  public DviContext getDviContext() { return dcs.getDviContext(); }

  public XDocument getXDocument() {
    return xdoc;
  }
  
  private boolean determinedSize = false;
  protected synchronized void determineSize()
  {
    if (determinedSize)
      return;
//    setPreferredSize(getVisibleRect().getSize());
    setPreferredSize(new Dimension(6400, 4800));
    revalidate();
    return;
//    
//    try {
//      final Rectangle rect = getBounds();
//      DviRect target = new DviRect(rect.x, rect.y, rect.width, rect.height);
//      SplitImage splitImage = xdoc.getPage(pageNum).getSplitImage(
//          viewSpec.getResolution(), target, unit);
//      DviRect r = splitImage.getRect();
////      DviRect shrunken = r.shrink(viewSpec.getResolution().shrinkFactor());
//      DviRect shrunken = r;
//      setPreferredSize(new Dimension(shrunken.width(), shrunken.height()));
//    } catch (DviException e) {
//      DviUtils.logStackTrace(LOGGER, Level.WARNING, e);
//    }
//    determinedSize = true;
//    revalidate();
  }
  
  protected void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    determineSize();
    try {
      XPage page = xdoc.getPage(pageNum);
      SplitImage splitImage = page.getSplitImage(viewSpec.getResolution(), null, unit);
      DviRect clientRect = DviRect.fromRectangle(getVisibleRect());
      double scale = (double) clientRect.height() / splitImage.getRect().height();
      SplitImageUtils.renderToGraphics(g, splitImage, 0, 0, scale);
    } catch (DviException e) {
      DviUtils.logStackTrace(LOGGER, Level.WARNING, e);
    }
  }

  public void setPageNumber(int pageNum) {
    this.pageNum = pageNum;
    determinedSize = false;
    repaint();
  }

  public int getPageNum() {
    return pageNum;
  }
  
  public int getMinPageNum() {
    return 0;
  }
  
  public int getMaxPageNum() {
    try {
      return xdoc.getTotalPages()-1;
    } catch (DviException e) {
      DviUtils.logStackTrace(LOGGER, Level.WARNING, e);
      return 0;
    }
  }

  public void setViewSpec(ViewSpec viewSpec) {
    this.viewSpec = viewSpec;
  }

  public ViewSpec getViewSpec() {
    return viewSpec;
  }

}
