package net.sf.jasperreports.engine.design;

import java.awt.Color;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import net.sf.jasperreports.engine.JRAlignment;
import net.sf.jasperreports.engine.JRBox;
import net.sf.jasperreports.engine.JRBoxContainer;
import net.sf.jasperreports.engine.JRCommonElement;
import net.sf.jasperreports.engine.JRCommonImage;
import net.sf.jasperreports.engine.JRDefaultStyleProvider;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRExpressionCollector;
import net.sf.jasperreports.engine.JRGroup;
import net.sf.jasperreports.engine.JRHyperlink;
import net.sf.jasperreports.engine.JRHyperlinkHelper;
import net.sf.jasperreports.engine.JRHyperlinkParameter;
import net.sf.jasperreports.engine.JRImage;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRPen;
import net.sf.jasperreports.engine.JRVisitor;
import net.sf.jasperreports.engine.base.JRBaseLineBox;
import net.sf.jasperreports.engine.util.JRBoxUtil;
import net.sf.jasperreports.engine.util.JRPenUtil;
import net.sf.jasperreports.engine.util.JRStyleResolver;
import net.sf.jasperreports.engine.util.LineBoxWrapper;

public class JRDesignImage extends JRDesignGraphicElement implements JRImage {
  private static final long serialVersionUID = 10200L;
  
  public static final String PROPERTY_ANCHOR_NAME_EXPRESSION = "anchorNameExpression";
  
  public static final String PROPERTY_BOOKMARK_LEVEL = "bookmarkLevel";
  
  public static final String PROPERTY_EVALUATION_GROUP = "evaluationGroup";
  
  public static final String PROPERTY_EVALUATION_TIME = "evaluationTime";
  
  public static final String PROPERTY_EXPRESSION = "expression";
  
  protected Byte scaleImage;
  
  protected Byte horizontalAlignment;
  
  protected Byte verticalAlignment;
  
  protected Boolean isUsingCache = null;
  
  protected boolean isLazy = false;
  
  protected byte onErrorType = 1;
  
  protected byte evaluationTime = 1;
  
  protected byte hyperlinkType = 0;
  
  protected String linkType;
  
  protected byte hyperlinkTarget = 1;
  
  private List hyperlinkParameters;
  
  protected JRLineBox lineBox = null;
  
  protected JRGroup evaluationGroup = null;
  
  protected JRExpression expression = null;
  
  protected JRExpression anchorNameExpression = null;
  
  protected JRExpression hyperlinkReferenceExpression = null;
  
  protected JRExpression hyperlinkAnchorExpression = null;
  
  protected JRExpression hyperlinkPageExpression = null;
  
  private JRExpression hyperlinkTooltipExpression;
  
  protected int bookmarkLevel = 0;
  
  private Byte border;
  
  private Byte topBorder;
  
  private Byte leftBorder;
  
  private Byte bottomBorder;
  
  private Byte rightBorder;
  
  private Color borderColor;
  
  private Color topBorderColor;
  
  private Color leftBorderColor;
  
  private Color bottomBorderColor;
  
  private Color rightBorderColor;
  
  private Integer padding;
  
  private Integer topPadding;
  
  private Integer leftPadding;
  
  private Integer bottomPadding;
  
  private Integer rightPadding;
  
  public JRDesignImage(JRDefaultStyleProvider defaultStyleProvider) {
    super(defaultStyleProvider);
    this.border = null;
    this.topBorder = null;
    this.leftBorder = null;
    this.bottomBorder = null;
    this.rightBorder = null;
    this.borderColor = null;
    this.topBorderColor = null;
    this.leftBorderColor = null;
    this.bottomBorderColor = null;
    this.rightBorderColor = null;
    this.padding = null;
    this.topPadding = null;
    this.leftPadding = null;
    this.bottomPadding = null;
    this.rightPadding = null;
    this.hyperlinkParameters = new ArrayList();
    this.lineBox = (JRLineBox)new JRBaseLineBox((JRBoxContainer)this);
  }
  
  public byte getMode() {
    return JRStyleResolver.getMode((JRCommonElement)this, (byte)2);
  }
  
  public byte getScaleImage() {
    return JRStyleResolver.getScaleImage((JRCommonImage)this);
  }
  
  public Byte getOwnScaleImage() {
    return this.scaleImage;
  }
  
  public void setScaleImage(byte scaleImage) {
    setScaleImage(new Byte(scaleImage));
  }
  
  public void setScaleImage(Byte scaleImage) {
    Object old = this.scaleImage;
    this.scaleImage = scaleImage;
    getEventSupport().firePropertyChange("scaleImage", old, this.scaleImage);
  }
  
  public byte getHorizontalAlignment() {
    return JRStyleResolver.getHorizontalAlignment((JRAlignment)this);
  }
  
  public Byte getOwnHorizontalAlignment() {
    return this.horizontalAlignment;
  }
  
  public void setHorizontalAlignment(byte horizontalAlignment) {
    setHorizontalAlignment(new Byte(horizontalAlignment));
  }
  
  public void setHorizontalAlignment(Byte horizontalAlignment) {
    Object old = this.horizontalAlignment;
    this.horizontalAlignment = horizontalAlignment;
    getEventSupport().firePropertyChange("horizontalAlignment", old, this.horizontalAlignment);
  }
  
  public byte getVerticalAlignment() {
    return JRStyleResolver.getVerticalAlignment((JRAlignment)this);
  }
  
  public Byte getOwnVerticalAlignment() {
    return this.verticalAlignment;
  }
  
  public void setVerticalAlignment(byte verticalAlignment) {
    setVerticalAlignment(new Byte(verticalAlignment));
  }
  
  public void setVerticalAlignment(Byte verticalAlignment) {
    Object old = this.verticalAlignment;
    this.verticalAlignment = verticalAlignment;
    getEventSupport().firePropertyChange("verticalAlignment", old, this.verticalAlignment);
  }
  
  public boolean isUsingCache() {
    if (this.isUsingCache == null) {
      if (getExpression() != null)
        return String.class.getName().equals(getExpression().getValueClassName()); 
      return true;
    } 
    return this.isUsingCache.booleanValue();
  }
  
  public Boolean isOwnUsingCache() {
    return this.isUsingCache;
  }
  
  public byte getEvaluationTime() {
    return this.evaluationTime;
  }
  
  public JRBox getBox() {
    return (JRBox)new LineBoxWrapper(getLineBox());
  }
  
  public JRLineBox getLineBox() {
    return this.lineBox;
  }
  
  public void setBox(JRBox box) {
    JRBoxUtil.setBoxToLineBox(box, this.lineBox);
  }
  
  public byte getHyperlinkType() {
    return JRHyperlinkHelper.getHyperlinkType((JRHyperlink)this);
  }
  
  public byte getHyperlinkTarget() {
    return this.hyperlinkTarget;
  }
  
  public JRGroup getEvaluationGroup() {
    return this.evaluationGroup;
  }
  
  public JRExpression getExpression() {
    return this.expression;
  }
  
  public JRExpression getAnchorNameExpression() {
    return this.anchorNameExpression;
  }
  
  public JRExpression getHyperlinkReferenceExpression() {
    return this.hyperlinkReferenceExpression;
  }
  
  public JRExpression getHyperlinkAnchorExpression() {
    return this.hyperlinkAnchorExpression;
  }
  
  public JRExpression getHyperlinkPageExpression() {
    return this.hyperlinkPageExpression;
  }
  
  public void setUsingCache(boolean isUsingCache) {
    setUsingCache(isUsingCache ? Boolean.TRUE : Boolean.FALSE);
  }
  
  public void setUsingCache(Boolean isUsingCache) {
    Object old = this.isUsingCache;
    this.isUsingCache = isUsingCache;
    getEventSupport().firePropertyChange("usingCache", old, this.isUsingCache);
  }
  
  public boolean isLazy() {
    return this.isLazy;
  }
  
  public void setLazy(boolean isLazy) {
    boolean old = this.isLazy;
    this.isLazy = isLazy;
    getEventSupport().firePropertyChange("lazy", old, this.isLazy);
  }
  
  public byte getOnErrorType() {
    return this.onErrorType;
  }
  
  public void setOnErrorType(byte onErrorType) {
    byte old = this.onErrorType;
    this.onErrorType = onErrorType;
    getEventSupport().firePropertyChange("onErrorType", old, this.onErrorType);
  }
  
  public void setEvaluationTime(byte evaluationTime) {
    byte old = this.evaluationTime;
    this.evaluationTime = evaluationTime;
    getEventSupport().firePropertyChange("evaluationTime", old, this.evaluationTime);
  }
  
  public void setHyperlinkType(byte hyperlinkType) {
    setLinkType(JRHyperlinkHelper.getLinkType(hyperlinkType));
  }
  
  public void setHyperlinkTarget(byte hyperlinkTarget) {
    byte old = this.hyperlinkTarget;
    this.hyperlinkTarget = hyperlinkTarget;
    getEventSupport().firePropertyChange("hyperlinkTarget", old, this.hyperlinkTarget);
  }
  
  public void setEvaluationGroup(JRGroup evaluationGroup) {
    Object old = this.evaluationGroup;
    this.evaluationGroup = evaluationGroup;
    getEventSupport().firePropertyChange("evaluationGroup", old, this.evaluationGroup);
  }
  
  public void setExpression(JRExpression expression) {
    Object old = this.expression;
    this.expression = expression;
    getEventSupport().firePropertyChange("expression", old, this.expression);
  }
  
  public void setAnchorNameExpression(JRExpression anchorNameExpression) {
    Object old = this.anchorNameExpression;
    this.anchorNameExpression = anchorNameExpression;
    getEventSupport().firePropertyChange("anchorNameExpression", old, this.anchorNameExpression);
  }
  
  public void setHyperlinkReferenceExpression(JRExpression hyperlinkReferenceExpression) {
    Object old = this.hyperlinkReferenceExpression;
    this.hyperlinkReferenceExpression = hyperlinkReferenceExpression;
    getEventSupport().firePropertyChange("hyperlinkReferenceExpression", old, this.hyperlinkReferenceExpression);
  }
  
  public void setHyperlinkAnchorExpression(JRExpression hyperlinkAnchorExpression) {
    Object old = this.hyperlinkAnchorExpression;
    this.hyperlinkAnchorExpression = hyperlinkAnchorExpression;
    getEventSupport().firePropertyChange("hyperlinkAnchorExpression", old, this.hyperlinkAnchorExpression);
  }
  
  public void setHyperlinkPageExpression(JRExpression hyperlinkPageExpression) {
    Object old = this.hyperlinkPageExpression;
    this.hyperlinkPageExpression = hyperlinkPageExpression;
    getEventSupport().firePropertyChange("hyperlinkPageExpression", old, this.hyperlinkPageExpression);
  }
  
  public void visit(JRVisitor visitor) {
    visitor.visitImage(this);
  }
  
  public void collectExpressions(JRExpressionCollector collector) {
    collector.collect(this);
  }
  
  public int getBookmarkLevel() {
    return this.bookmarkLevel;
  }
  
  public void setBookmarkLevel(int bookmarkLevel) {
    int old = this.bookmarkLevel;
    this.bookmarkLevel = bookmarkLevel;
    getEventSupport().firePropertyChange("bookmarkLevel", old, this.bookmarkLevel);
  }
  
  public Float getDefaultLineWidth() {
    return JRPen.LINE_WIDTH_0;
  }
  
  public byte getBorder() {
    return JRPenUtil.getPenFromLinePen((JRPen)this.lineBox.getPen());
  }
  
  public Byte getOwnBorder() {
    return JRPenUtil.getOwnPenFromLinePen((JRPen)this.lineBox.getPen());
  }
  
  public void setBorder(byte border) {
    JRPenUtil.setLinePenFromPen(border, (JRPen)this.lineBox.getPen());
  }
  
  public void setBorder(Byte border) {
    JRPenUtil.setLinePenFromPen(border, (JRPen)this.lineBox.getPen());
  }
  
  public Color getBorderColor() {
    return this.lineBox.getPen().getLineColor();
  }
  
  public Color getOwnBorderColor() {
    return this.lineBox.getPen().getOwnLineColor();
  }
  
  public void setBorderColor(Color borderColor) {
    this.lineBox.getPen().setLineColor(borderColor);
  }
  
  public int getPadding() {
    return this.lineBox.getPadding().intValue();
  }
  
  public Integer getOwnPadding() {
    return this.lineBox.getOwnPadding();
  }
  
  public void setPadding(int padding) {
    this.lineBox.setPadding(padding);
  }
  
  public void setPadding(Integer padding) {
    this.lineBox.setPadding(padding);
  }
  
  public byte getTopBorder() {
    return JRPenUtil.getPenFromLinePen((JRPen)this.lineBox.getTopPen());
  }
  
  public Byte getOwnTopBorder() {
    return JRPenUtil.getOwnPenFromLinePen((JRPen)this.lineBox.getTopPen());
  }
  
  public void setTopBorder(byte topBorder) {
    JRPenUtil.setLinePenFromPen(topBorder, (JRPen)this.lineBox.getTopPen());
  }
  
  public void setTopBorder(Byte topBorder) {
    JRPenUtil.setLinePenFromPen(topBorder, (JRPen)this.lineBox.getTopPen());
  }
  
  public Color getTopBorderColor() {
    return this.lineBox.getTopPen().getLineColor();
  }
  
  public Color getOwnTopBorderColor() {
    return this.lineBox.getTopPen().getOwnLineColor();
  }
  
  public void setTopBorderColor(Color topBorderColor) {
    this.lineBox.getTopPen().setLineColor(topBorderColor);
  }
  
  public int getTopPadding() {
    return this.lineBox.getTopPadding().intValue();
  }
  
  public Integer getOwnTopPadding() {
    return this.lineBox.getOwnTopPadding();
  }
  
  public void setTopPadding(int topPadding) {
    this.lineBox.setTopPadding(topPadding);
  }
  
  public void setTopPadding(Integer topPadding) {
    this.lineBox.setTopPadding(topPadding);
  }
  
  public byte getLeftBorder() {
    return JRPenUtil.getPenFromLinePen((JRPen)this.lineBox.getLeftPen());
  }
  
  public Byte getOwnLeftBorder() {
    return JRPenUtil.getOwnPenFromLinePen((JRPen)this.lineBox.getLeftPen());
  }
  
  public void setLeftBorder(byte leftBorder) {
    JRPenUtil.setLinePenFromPen(leftBorder, (JRPen)this.lineBox.getLeftPen());
  }
  
  public void setLeftBorder(Byte leftBorder) {
    JRPenUtil.setLinePenFromPen(leftBorder, (JRPen)this.lineBox.getLeftPen());
  }
  
  public Color getLeftBorderColor() {
    return this.lineBox.getLeftPen().getLineColor();
  }
  
  public Color getOwnLeftBorderColor() {
    return this.lineBox.getLeftPen().getOwnLineColor();
  }
  
  public void setLeftBorderColor(Color leftBorderColor) {
    this.lineBox.getLeftPen().setLineColor(leftBorderColor);
  }
  
  public int getLeftPadding() {
    return this.lineBox.getLeftPadding().intValue();
  }
  
  public Integer getOwnLeftPadding() {
    return this.lineBox.getOwnLeftPadding();
  }
  
  public void setLeftPadding(int leftPadding) {
    this.lineBox.setLeftPadding(leftPadding);
  }
  
  public void setLeftPadding(Integer leftPadding) {
    this.lineBox.setLeftPadding(leftPadding);
  }
  
  public byte getBottomBorder() {
    return JRPenUtil.getPenFromLinePen((JRPen)this.lineBox.getBottomPen());
  }
  
  public Byte getOwnBottomBorder() {
    return JRPenUtil.getOwnPenFromLinePen((JRPen)this.lineBox.getBottomPen());
  }
  
  public void setBottomBorder(byte bottomBorder) {
    JRPenUtil.setLinePenFromPen(bottomBorder, (JRPen)this.lineBox.getBottomPen());
  }
  
  public void setBottomBorder(Byte bottomBorder) {
    JRPenUtil.setLinePenFromPen(bottomBorder, (JRPen)this.lineBox.getBottomPen());
  }
  
  public Color getBottomBorderColor() {
    return this.lineBox.getBottomPen().getLineColor();
  }
  
  public Color getOwnBottomBorderColor() {
    return this.lineBox.getBottomPen().getOwnLineColor();
  }
  
  public void setBottomBorderColor(Color bottomBorderColor) {
    this.lineBox.getBottomPen().setLineColor(bottomBorderColor);
  }
  
  public int getBottomPadding() {
    return this.lineBox.getBottomPadding().intValue();
  }
  
  public Integer getOwnBottomPadding() {
    return this.lineBox.getOwnBottomPadding();
  }
  
  public void setBottomPadding(int bottomPadding) {
    this.lineBox.setBottomPadding(bottomPadding);
  }
  
  public void setBottomPadding(Integer bottomPadding) {
    this.lineBox.setBottomPadding(bottomPadding);
  }
  
  public byte getRightBorder() {
    return JRPenUtil.getPenFromLinePen((JRPen)this.lineBox.getRightPen());
  }
  
  public Byte getOwnRightBorder() {
    return JRPenUtil.getOwnPenFromLinePen((JRPen)this.lineBox.getRightPen());
  }
  
  public void setRightBorder(byte rightBorder) {
    JRPenUtil.setLinePenFromPen(rightBorder, (JRPen)this.lineBox.getRightPen());
  }
  
  public void setRightBorder(Byte rightBorder) {
    JRPenUtil.setLinePenFromPen(rightBorder, (JRPen)this.lineBox.getRightPen());
  }
  
  public Color getRightBorderColor() {
    return this.lineBox.getRightPen().getLineColor();
  }
  
  public Color getOwnRightBorderColor() {
    return this.lineBox.getRightPen().getOwnLineColor();
  }
  
  public void setRightBorderColor(Color rightBorderColor) {
    this.lineBox.getRightPen().setLineColor(rightBorderColor);
  }
  
  public int getRightPadding() {
    return this.lineBox.getRightPadding().intValue();
  }
  
  public Integer getOwnRightPadding() {
    return this.lineBox.getOwnRightPadding();
  }
  
  public void setRightPadding(int rightPadding) {
    this.lineBox.setRightPadding(rightPadding);
  }
  
  public void setRightPadding(Integer rightPadding) {
    this.lineBox.setRightPadding(rightPadding);
  }
  
  public String getLinkType() {
    return this.linkType;
  }
  
  public void setLinkType(String type) {
    Object old = this.linkType;
    this.linkType = type;
    getEventSupport().firePropertyChange("linkType", old, this.linkType);
  }
  
  public JRHyperlinkParameter[] getHyperlinkParameters() {
    JRHyperlinkParameter[] parameters;
    if (this.hyperlinkParameters.isEmpty()) {
      parameters = null;
    } else {
      parameters = new JRHyperlinkParameter[this.hyperlinkParameters.size()];
      this.hyperlinkParameters.toArray((Object[])parameters);
    } 
    return parameters;
  }
  
  public List getHyperlinkParametersList() {
    return this.hyperlinkParameters;
  }
  
  public void addHyperlinkParameter(JRHyperlinkParameter parameter) {
    this.hyperlinkParameters.add(parameter);
    getEventSupport().fireCollectionElementAddedEvent("hyperlinkParameters", parameter, this.hyperlinkParameters.size() - 1);
  }
  
  public void removeHyperlinkParameter(JRHyperlinkParameter parameter) {
    int idx = this.hyperlinkParameters.indexOf(parameter);
    if (idx >= 0) {
      this.hyperlinkParameters.remove(idx);
      getEventSupport().fireCollectionElementRemovedEvent("hyperlinkParameters", parameter, idx);
    } 
  }
  
  public void removeHyperlinkParameter(String parameterName) {
    for (ListIterator it = this.hyperlinkParameters.listIterator(); it.hasNext(); ) {
      JRHyperlinkParameter parameter = it.next();
      if (parameter.getName() != null && parameter.getName().equals(parameterName)) {
        it.remove();
        getEventSupport().fireCollectionElementRemovedEvent("hyperlinkParameters", parameter, it.nextIndex());
      } 
    } 
  }
  
  protected void normalizeLinkType() {
    if (this.linkType == null)
      this.linkType = JRHyperlinkHelper.getLinkType(this.hyperlinkType); 
    this.hyperlinkType = 0;
  }
  
  public JRExpression getHyperlinkTooltipExpression() {
    return this.hyperlinkTooltipExpression;
  }
  
  public void setHyperlinkTooltipExpression(JRExpression hyperlinkTooltipExpression) {
    Object old = this.hyperlinkTooltipExpression;
    this.hyperlinkTooltipExpression = hyperlinkTooltipExpression;
    getEventSupport().firePropertyChange("hyperlinkTooltipExpression", old, this.hyperlinkTooltipExpression);
  }
  
  public Object clone() {
    JRDesignImage clone = (JRDesignImage)super.clone();
    if (this.hyperlinkParameters != null) {
      clone.hyperlinkParameters = new ArrayList(this.hyperlinkParameters.size());
      for (int i = 0; i < this.hyperlinkParameters.size(); i++)
        clone.hyperlinkParameters.add(((JRHyperlinkParameter)this.hyperlinkParameters.get(i)).clone()); 
    } 
    if (this.expression != null)
      clone.expression = (JRExpression)this.expression.clone(); 
    if (this.anchorNameExpression != null)
      clone.anchorNameExpression = (JRExpression)this.anchorNameExpression.clone(); 
    if (this.hyperlinkReferenceExpression != null)
      clone.hyperlinkReferenceExpression = (JRExpression)this.hyperlinkReferenceExpression.clone(); 
    if (this.hyperlinkAnchorExpression != null)
      clone.hyperlinkAnchorExpression = (JRExpression)this.hyperlinkAnchorExpression.clone(); 
    if (this.hyperlinkPageExpression != null)
      clone.hyperlinkPageExpression = (JRExpression)this.hyperlinkPageExpression.clone(); 
    if (this.hyperlinkTooltipExpression != null)
      clone.hyperlinkTooltipExpression = (JRExpression)this.hyperlinkTooltipExpression.clone(); 
    return clone;
  }
  
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    in.defaultReadObject();
    if (this.lineBox == null) {
      this.lineBox = (JRLineBox)new JRBaseLineBox((JRBoxContainer)this);
      JRBoxUtil.setToBox(this.border, this.topBorder, this.leftBorder, this.bottomBorder, this.rightBorder, this.borderColor, this.topBorderColor, this.leftBorderColor, this.bottomBorderColor, this.rightBorderColor, this.padding, this.topPadding, this.leftPadding, this.bottomPadding, this.rightPadding, this.lineBox);
      this.border = null;
      this.topBorder = null;
      this.leftBorder = null;
      this.bottomBorder = null;
      this.rightBorder = null;
      this.borderColor = null;
      this.topBorderColor = null;
      this.leftBorderColor = null;
      this.bottomBorderColor = null;
      this.rightBorderColor = null;
      this.padding = null;
      this.topPadding = null;
      this.leftPadding = null;
      this.bottomPadding = null;
      this.rightPadding = null;
    } 
    normalizeLinkType();
  }
}
