package net.sf.jasperreports.engine.xml;

import java.io.IOException;
import net.sf.jasperreports.engine.JRConditionalStyle;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRPen;
import net.sf.jasperreports.engine.JRStyle;
import net.sf.jasperreports.engine.JRStyleContainer;
import net.sf.jasperreports.engine.util.JRXmlWriteHelper;

public abstract class JRXmlBaseWriter {
  protected JRXmlWriteHelper writer;
  
  protected void useWriter(JRXmlWriteHelper aWriter) {
    this.writer = aWriter;
  }
  
  protected void writeStyle(JRStyle style) throws IOException {
    this.writer.startElement("style");
    this.writer.addEncodedAttribute("name", style.getName());
    this.writer.addAttribute("isDefault", style.isDefault());
    writeStyleReferenceAttr((JRStyleContainer)style);
    this.writer.addAttribute("mode", style.getOwnMode(), JRXmlConstants.getModeMap());
    this.writer.addAttribute("forecolor", style.getOwnForecolor());
    this.writer.addAttribute("backcolor", style.getOwnBackcolor());
    this.writer.addAttribute("fill", style.getOwnFill(), JRXmlConstants.getFillMap());
    this.writer.addAttribute("radius", style.getOwnRadius());
    this.writer.addAttribute("scaleImage", style.getOwnScaleImage(), JRXmlConstants.getScaleImageMap());
    this.writer.addAttribute("hAlign", style.getOwnHorizontalAlignment(), JRXmlConstants.getHorizontalAlignMap());
    this.writer.addAttribute("vAlign", style.getOwnVerticalAlignment(), JRXmlConstants.getVerticalAlignMap());
    this.writer.addAttribute("rotation", style.getOwnRotation(), JRXmlConstants.getRotationMap());
    this.writer.addAttribute("lineSpacing", style.getOwnLineSpacing(), JRXmlConstants.getLineSpacingMap());
    this.writer.addAttribute("markup", style.getOwnMarkup());
    this.writer.addEncodedAttribute("pattern", style.getOwnPattern());
    this.writer.addAttribute("isBlankWhenNull", style.isOwnBlankWhenNull());
    this.writer.addEncodedAttribute("fontName", style.getOwnFontName());
    this.writer.addAttribute("fontSize", style.getOwnFontSize());
    this.writer.addAttribute("isBold", style.isOwnBold());
    this.writer.addAttribute("isItalic", style.isOwnItalic());
    this.writer.addAttribute("isUnderline", style.isOwnUnderline());
    this.writer.addAttribute("isStrikeThrough", style.isOwnStrikeThrough());
    this.writer.addEncodedAttribute("pdfFontName", style.getOwnPdfFontName());
    this.writer.addEncodedAttribute("pdfEncoding", style.getOwnPdfEncoding());
    this.writer.addAttribute("isPdfEmbedded", style.isOwnPdfEmbedded());
    writePen(style.getLinePen());
    writeBox(style.getLineBox());
    if (toWriteConditionalStyles()) {
      JRConditionalStyle[] conditionalStyles = style.getConditionalStyles();
      if (!(style instanceof JRConditionalStyle) && conditionalStyles != null)
        for (int i = 0; i < conditionalStyles.length; i++)
          writeConditionalStyle(conditionalStyles[i]);  
    } 
    this.writer.closeElement();
  }
  
  protected void writeStyleReferenceAttr(JRStyleContainer styleContainer) {
    if (styleContainer.getStyle() != null) {
      this.writer.addEncodedAttribute("style", styleContainer.getStyle().getName());
    } else if (styleContainer.getStyleNameReference() != null) {
      this.writer.addEncodedAttribute("style", styleContainer.getStyleNameReference());
    } 
  }
  
  protected abstract boolean toWriteConditionalStyles();
  
  protected void writeConditionalStyle(JRConditionalStyle style) throws IOException {
    this.writer.startElement("conditionalStyle");
    this.writer.writeExpression("conditionExpression", style.getConditionExpression(), false);
    writeStyle((JRStyle)style);
    this.writer.closeElement();
  }
  
  protected void writePen(JRPen pen) throws IOException {
    writePen("pen", pen);
  }
  
  private void writePen(String element, JRPen pen) throws IOException {
    this.writer.startElement(element);
    this.writer.addAttribute("lineWidth", pen.getOwnLineWidth());
    this.writer.addAttribute("lineStyle", pen.getOwnLineStyle(), JRXmlConstants.getLineStyleMap());
    this.writer.addAttribute("lineColor", pen.getOwnLineColor());
    this.writer.closeElement(true);
  }
  
  protected void writeBox(JRLineBox box) throws IOException {
    if (box != null) {
      this.writer.startElement("box");
      this.writer.addAttribute("padding", box.getOwnPadding());
      this.writer.addAttribute("topPadding", box.getOwnTopPadding());
      this.writer.addAttribute("leftPadding", box.getOwnLeftPadding());
      this.writer.addAttribute("bottomPadding", box.getOwnBottomPadding());
      this.writer.addAttribute("rightPadding", box.getOwnRightPadding());
      writePen("pen", (JRPen)box.getPen());
      writePen("topPen", (JRPen)box.getTopPen());
      writePen("leftPen", (JRPen)box.getLeftPen());
      writePen("bottomPen", (JRPen)box.getBottomPen());
      writePen("rightPen", (JRPen)box.getRightPen());
      this.writer.closeElement(true);
    } 
  }
}
