/*
 * 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 jp.sourceforge.dvibrowser.dvicore.gui.swing;

// mutable.
// TODO: make this class independent of Swing and move it to another package.
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;

import jp.sourceforge.dvibrowser.dvicore.DviColor;
import jp.sourceforge.dvibrowser.dvicore.DviException;
import jp.sourceforge.dvibrowser.dvicore.DviObject;
import jp.sourceforge.dvibrowser.dvicore.DviPaperSize;
import jp.sourceforge.dvibrowser.dvicore.DviResolution;
import jp.sourceforge.dvibrowser.dvicore.api.DviContextSupport;
import jp.sourceforge.dvibrowser.dvicore.api.GammaCorrector;
import jp.sourceforge.dvibrowser.dvicore.render.DefaultGammaCorrector;
import jp.sourceforge.dvibrowser.dvicore.util.DviUtils;


public class ViewSpec
extends DviObject
implements Cloneable
{
  private static final Logger LOGGER = Logger.getLogger(ViewSpec.class.getName());
  
  protected EventListenerList listenerList = new EventListenerList();
  
  public void addChangeListener(ChangeListener l)
  {
      listenerList.add(ChangeListener.class, l);
  }

  public void removeChangeListener(ChangeListener l)
  {
      listenerList.remove(ChangeListener.class, l);
  }

  protected void fireChangeEvent()
  {
    ChangeEvent event = null;
    
    Object[] listeners = listenerList.getListenerList();
    for (int i = listeners.length-2; i>=0; i-=2) {
      if (listeners[i] == ChangeListener.class) {
        if (event == null)
          event = new ChangeEvent(this);
        ((ChangeListener)listeners[i+1]).stateChanged(event);
      }
    }
  }
  
  // TODO: outsource configurations to a config file.
  private DviColor backgroundColor = new DviColor(255, 255, 255);
  private int epsResolutionDpi = 200;
  private String epsImageFileExtension = ".jpg";
  private String epsImageDeviceName = "jpeg"; // passed to Ghostscript
  
  private DviColor foregroundColor = new DviColor(0, 0, 0);
  private static final GammaCorrector defaultGammaCorrector = new DefaultGammaCorrector(1.4, 1.2);
  private GammaCorrector gammaCorrector = defaultGammaCorrector;

  private DviPaperSize paperSize;
  
  private boolean postScriptEnabled = true;
  
  private DviResolution res;
  
  public ViewSpec(DviContextSupport dcs) {
    super(dcs);
    try {
      res = getDviContext().getDefaultResolution();
    } catch (DviException e) {
      DviUtils.logStackTrace(LOGGER, Level.WARNING, e);
    }
    if (res == null) {
      res = new DviResolution(2400, 20);
    }
  }

  // Note that we don't copy the listeners.
  public Object clone()
 {
    try {
      ViewSpec vs = (ViewSpec) super.clone();
      vs.backgroundColor = this.backgroundColor;
      vs.epsResolutionDpi = this.epsResolutionDpi;
      vs.foregroundColor = this.foregroundColor;
      vs.gammaCorrector = this.gammaCorrector;
      vs.paperSize = this.paperSize;
      vs.postScriptEnabled = this.postScriptEnabled;
      vs.res = this.res;
      vs.epsImageDeviceName = this.epsImageDeviceName;
      vs.epsImageFileExtension = this.epsImageFileExtension;
      vs.epsResolutionDpi = this.epsResolutionDpi;
      return vs;
    } catch (CloneNotSupportedException e) {
      throw new InternalError();
    }
  }

  public DviColor getBackgroundColor()
  {
    return backgroundColor;
  }

  public int getEpsResolutionDpi()
  {
    return epsResolutionDpi;
  }
  
  public DviColor getForegroundColor()
  {
    return foregroundColor;
  }

  public GammaCorrector getGammaCorrector()
  {
    return gammaCorrector;
  }
  public DviPaperSize getPaperSize()
  {
    return paperSize;
  }
  public DviResolution getResolution()
  {
    return res;
  }

  public boolean isPostScriptEnabled()
  {
    return postScriptEnabled;
  }
  public void setPostScriptEnabled(boolean postScriptEnabled)
  {
    this.postScriptEnabled = postScriptEnabled;
    fireChangeEvent();
  }
  
  public void setBackgroundColor(DviColor c)
  {
    backgroundColor = c;
    fireChangeEvent();
  }
  
  public void setEpsResolutionDpi(int epsResolutionDpi)
  {
    this.epsResolutionDpi = epsResolutionDpi;
    fireChangeEvent();
  }
  
  public void setForegroundColor(DviColor c)
  {
    foregroundColor = c;
    fireChangeEvent();
  }

  public void setGammaCorrector(GammaCorrector gc)
  {
    this.gammaCorrector = gc;
    fireChangeEvent();
  }

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

  public void setResolution(DviResolution res)
  {
    this.res = res;
    LOGGER.finer("res=" + res);
    fireChangeEvent();
  }

  public void setEpsImageFileExtension(String epsImageFileExtension)
  {
    this.epsImageFileExtension = epsImageFileExtension;
    fireChangeEvent();
  }

  public String getEpsImageFileExtension()
  {
    return epsImageFileExtension;
  }

  public void setEpsImageDeviceName(String epsImageDevice)
  {
    this.epsImageDeviceName = epsImageDevice;
    fireChangeEvent();
  }

  public String getEpsImageDeviceName()
  {
    return epsImageDeviceName;
  }
  
  public String toString()
  {
    return getClass().getName()
      + "[backgroundColor=" + this.backgroundColor
      + ",epsResolutionDpi=" + this.epsResolutionDpi
      + ",foregroundColor=" + this.foregroundColor
      + ",gammaCorrector=" + this.gammaCorrector
      + ",paperSize=" + this.paperSize
      + ",postScriptEnabled=" + this.postScriptEnabled
      + ",resolution=" + this.res
      + "]"
      ;
  }

  public void setApproximateDpi(double dpi) {
    setResolution(res.approximate(dpi));
  }

  public static GammaCorrector getDefaultGammaCorrector() {
    return defaultGammaCorrector;
  }
}
