/*
 * 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.gui.swing;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.util.logging.Logger;

import javax.swing.BorderFactory;

import dvi.DviException;
import dvi.DviObject;
import dvi.DviPaperSize;
import dvi.DviRect;
import dvi.DviResolution;
import dvi.api.DviContextSupport;
import dvi.api.DviDocument;
import dvi.api.DviPage;
import dvi.ctx.DviToolkit;

public class DefaultDviLayoutManager
extends DviObject
implements DviLayoutManager
{
  private static final Logger LOGGER = Logger.getLogger(DefaultDviLayoutManager.class.getName());
  private int cols;
  private int horizontalSpacing;
  private int verticalSpacing;
  private int paddingSize;
  private DviPaperSize paperSize;
  private boolean crop;
  private boolean enableDelayedRendering = true;
  
  public DefaultDviLayoutManager(DviContextSupport dcs, int cols, int paddingSize)
  {
    super(dcs);
    setNumberOfColumns(cols);
    setPaddingSize(paddingSize);
  }

  public DefaultDviLayoutManager(DviContextSupport dcs, int cols)
  {
    this(dcs, cols, 0);
  }
  
  private int computeRows(DviDocument doc)
  throws DviException
  {
    int rows = (doc.getTotalPages() + cols - 1)/ cols;
    return rows;
  }
  
  public LayoutManager createLayout(DviDocument doc, DviResolution res)
      throws DviException
  {
    return new GridLayout(computeRows(doc), cols, horizontalSpacing, verticalSpacing);
//      return new FlowLayout();
  }
  
  public DviRect getPageBoundingBox(DviDocument doc, DviResolution res)
  throws DviException
  {
    DviToolkit utils = getDviContext().getDviToolkit();
    if (getEnableCrop()) {
      DviRect bbox = DviRect.union(utils.computeBoundingBoxes(doc, res));
      return bbox;
    } else {
      DviPaperSize ps = null;
      try {
        ps = getDviContext().getDefaultPaperSize();
      } catch (DviException e) {
        LOGGER.warning(e.toString());
      }
      return utils.computePageBoundingBox(ps, res);
    }
  }

  public DviRect getBoundingBox(DviDocument doc, DviResolution res)
      throws DviException
  {
    int rows = computeRows(doc);
    DviRect bbox = getPageBoundingBox(doc, res);
    DviRect ret = new DviRect
      (0, 0, bbox.width() * cols + horizontalSpacing * (cols -1) + paddingSize * (cols + 1) + 16 * (cols),
          bbox.height() * rows + verticalSpacing * (rows - 1) + paddingSize * (rows + 1) + 16 * (cols));
    return ret;
  }

  public int getNumberOfColumns() { return cols; }
  public void setNumberOfColumns(int cols) {
    this.cols = Math.max(0, cols);
  }

  public int getHorizontalSpacing()
  {
    return horizontalSpacing;
  }

  public void setHorizontalSpacing(int horizontalSpacing)
  {
    this.horizontalSpacing = horizontalSpacing;
  }

  public int getVerticalSpacing()
  {
    return verticalSpacing;
  }

  public void setVerticalSpacing(int verticalSpacing)
  {
    this.verticalSpacing = verticalSpacing;
  }
  
  public void decoratePage(TDviDocument tdd, TDviPage dp)
  throws DviException
  {
//    DviRect bbox = determinePageSize(dp);
//    dp.setBoundingBox(bbox);
    dp.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, new Color(190, 190, 190)));
  }

  public int getPaddingSize()
  {
    return paddingSize;
  }

  public void setPaddingSize(int paddingSize)
  {
    this.paddingSize = paddingSize;
  }

  public void setPaperSize(DviPaperSize paperSize)
  {
    this.paperSize = paperSize;
  }

  public DviPaperSize getPaperSize()
  {
    return paperSize;
  }

  public void setEnableCrop(boolean crop)
  {
    this.crop = crop;
  }

  public boolean getEnableCrop()
  {
    return crop;
  }

  public boolean getEnableDelayedRendering(TDviPage dp) throws DviException
  {
    return enableDelayedRendering;
  }

  public void setEnableDelayedRendering(boolean enableDelayedRendering)
  {
    this.enableDelayedRendering = enableDelayedRendering;
  }

  public DviRect determinePageSize(TDviPage dp) throws DviException
  {
    DviRect bbox = null;
    DviPage page = dp.getPage();
    ViewSpec viewSpec = dp.getViewSpec();
    DviResolution res = viewSpec.getResolution();
    if (page != null) {
      bbox = getPageBoundingBox(page.getDocument(), res);
    }
    if (bbox == null) {
      DviToolkit utils = getDviContext().getDviToolkit();
      bbox = utils.computePageBoundingBox(viewSpec.getPaperSize(), res);
    }
    return bbox.addPadding(paddingSize);
  }
}
