/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.hslf.usermodel;

import static org.apache.poi.hslf.record.RecordTypes.OEPlaceholderAtom;
import static org.apache.poi.hslf.record.RecordTypes.RoundTripHFPlaceholder12;

import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.model.HSLFMetroShape;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTextShape;
import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;

/**
 * A common superclass of all shapes that can hold text.
 */
public abstract class HSLFTextShape extends HSLFSimpleShape
implements TextShape<HSLFShape,HSLFTextParagraph> {
    private static final POILogger LOG = POILogFactory.getLogger(HSLFTextShape.class);

    /**
     * How to anchor the text
     */
    private enum HSLFTextAnchor {
        TOP                   (0, VerticalAlignment.TOP,    false, false),
        MIDDLE                (1, VerticalAlignment.MIDDLE, false, false),
        BOTTOM                (2, VerticalAlignment.BOTTOM, false, false),
        TOP_CENTER            (3, VerticalAlignment.TOP,    true,  false),
        MIDDLE_CENTER         (4, VerticalAlignment.MIDDLE, true,  false),
        BOTTOM_CENTER         (5, VerticalAlignment.BOTTOM, true,  false),
        TOP_BASELINE          (6, VerticalAlignment.TOP,    false, true),
        BOTTOM_BASELINE       (7, VerticalAlignment.BOTTOM, false, true),
        TOP_CENTER_BASELINE   (8, VerticalAlignment.TOP,    true,  true),
        BOTTOM_CENTER_BASELINE(9, VerticalAlignment.BOTTOM, true,  true);
        
        public final int nativeId;
        public final VerticalAlignment vAlign;
        public final boolean centered;
        public final Boolean baseline;
        
        HSLFTextAnchor(int nativeId, VerticalAlignment vAlign, boolean centered, Boolean baseline) {
            this.nativeId = nativeId;
            this.vAlign = vAlign;
            this.centered = centered;
            this.baseline = baseline;
        }

        static HSLFTextAnchor fromNativeId(int nativeId) {
            for (HSLFTextAnchor ta : values()) {
                if (ta.nativeId == nativeId) return ta;
            }
            return null;
        }
    }

    /**
     * Specifies that a line of text will continue on subsequent lines instead
     * of extending into or beyond a margin.
     * Office Excel 2007, Excel 2010, PowerPoint 97, and PowerPoint 2010 read
     * and use this value properly but do not write it.
     */
    public static final int WrapSquare = 0;
    /**
     * Specifies a wrapping rule that is equivalent to that of WrapSquare
     * Excel 97, Excel 2000, Excel 2002, and Office Excel 2003 use this value.
     * All other product versions listed at the beginning of this appendix ignore this value.
     */
    public static final int WrapByPoints = 1;
    /**
     * Specifies that a line of text will extend into or beyond a margin instead
     * of continuing on subsequent lines.
     * Excel 97, Word 97, Excel 2000, Word 2000, Excel 2002,
     * and Office Excel 2003 do not use this value.
     */
    public static final int WrapNone = 2;
    /**
     * Specifies a wrapping rule that is undefined and MUST be ignored.
     */
    public static final int WrapTopBottom = 3;
    /**
     * Specifies a wrapping rule that is undefined and MUST be ignored.
     */
    public static final int WrapThrough = 4;


    /**
     * TextRun object which holds actual text and format data
     */
    protected List<HSLFTextParagraph> _paragraphs = new ArrayList<HSLFTextParagraph>();

    /**
     * Escher container which holds text attributes such as
     * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
     */
    protected EscherTextboxWrapper _txtbox;

    /**
     * This setting is used for supporting a deprecated alignment
     *
     * @see <a href=""></a>
     */
//    boolean alignToBaseline = false;

    /**
     * Used to calculate text bounds
     */
    protected static final FontRenderContext _frc = new FontRenderContext(null, true, true);

    /**
     * Create a TextBox object and initialize it from the supplied Record container.
     *
     * @param escherRecord       <code>EscherSpContainer</code> container which holds information about this shape
     * @param parent    the parent of the shape
     */
    protected HSLFTextShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
        super(escherRecord, parent);
    }

    /**
     * Create a new TextBox. This constructor is used when a new shape is created.
     *
     * @param parent    the parent of this Shape. For example, if this text box is a cell
     * in a table then the parent is Table.
     */
    public HSLFTextShape(ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
        super(null, parent);
        createSpContainer(parent instanceof HSLFGroupShape);
    }

    /**
     * Create a new TextBox. This constructor is used when a new shape is created.
     *
     */
    public HSLFTextShape(){
        this(null);
    }

    /**
     * Set default properties for the  TextRun.
     * Depending on the text and shape type the defaults are different:
     *   TextBox: align=left, valign=top
     *   AutoShape: align=center, valign=middle
     *
     */
    protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){

    }

    /**
     * When a textbox is added to  a sheet we need to tell upper-level
     * <code>PPDrawing</code> about it.
     *
     * @param sh the sheet we are adding to
     */
    @Override
    protected void afterInsert(HSLFSheet sh){
        super.afterInsert(sh);

        storeText();

        EscherTextboxWrapper thisTxtbox = getEscherTextboxWrapper();
        if(thisTxtbox != null){
            getSpContainer().addChildRecord(thisTxtbox.getEscherRecord());

            PPDrawing ppdrawing = sh.getPPDrawing();
            ppdrawing.addTextboxWrapper(thisTxtbox);
            // Ensure the escher layer knows about the added records
            try {
                thisTxtbox.writeOut(null);
            } catch (IOException e){
                throw new HSLFException(e);
            }
            boolean isInitialAnchor = getAnchor().equals(new Rectangle2D.Double());
            boolean isFilledTxt = !"".equals(getText());
            if (isInitialAnchor && isFilledTxt) {
                resizeToFitText();
            }
        }
        for (HSLFTextParagraph htp : _paragraphs) {
            htp.setShapeId(getShapeId());
        }
        sh.onAddTextShape(this);
    }

    protected EscherTextboxWrapper getEscherTextboxWrapper(){
        if(_txtbox != null) return _txtbox;

        EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID);
        if (textRecord == null) return null;

        HSLFSheet sheet = getSheet();
        if (sheet != null) {
            PPDrawing drawing = sheet.getPPDrawing();
            if (drawing != null) {
                EscherTextboxWrapper wrappers[] = drawing.getTextboxWrappers();
                if (wrappers != null) {
                    for (EscherTextboxWrapper w : wrappers) {
                        // check for object identity
                        if (textRecord == w.getEscherRecord()) {
                            _txtbox = w;
                            return _txtbox;
                        }
                    }
                }
            }
        }

        _txtbox = new EscherTextboxWrapper(textRecord);
        return _txtbox;
    }

    /**
     * Adjust the size of the shape so it encompasses the text inside it.
     *
     * @return a <code>Rectangle2D</code> that is the bounds of this shape.
     */
    public Rectangle2D resizeToFitText(){
        Rectangle2D anchor = getAnchor();
        if(anchor.getWidth() == 0.) {
            LOG.log(POILogger.WARN, "Width of shape wasn't set. Defaulting to 200px");
            anchor.setRect(anchor.getX(), anchor.getY(), 200., anchor.getHeight());
            setAnchor(anchor);
        }
        double height = getTextHeight();
        height += 1; // add a pixel to compensate rounding errors

        anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height);
        setAnchor(anchor);

        return anchor;
    }

    /**
    * Returns the type of the text, from the TextHeaderAtom.
    * Possible values can be seen from TextHeaderAtom
    * @see org.apache.poi.hslf.record.TextHeaderAtom
    */
    public int getRunType() {
        getEscherTextboxWrapper();
        if (_txtbox == null) return -1;
        List<HSLFTextParagraph> paras = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
        return (paras.isEmpty()) ? -1 : paras.get(0).getRunType();
    }

    /**
    * Changes the type of the text. Values should be taken
    *  from TextHeaderAtom. No checking is done to ensure you
    *  set this to a valid value!
    * @see org.apache.poi.hslf.record.TextHeaderAtom
    */
    public void setRunType(int type) {
        getEscherTextboxWrapper();
        if (_txtbox == null) return;
        List<HSLFTextParagraph> paras = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
        if (!paras.isEmpty()) {
            paras.get(0).setRunType(type);
        }
    }

    /**
     * Returns the type of vertical alignment for the text.
     * One of the <code>Anchor*</code> constants defined in this class.
     *
     * @return the type of alignment
     */
    /* package */ HSLFTextAnchor getAlignment(){
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
        HSLFTextAnchor align = HSLFTextAnchor.TOP;
        if (prop == null){
            /**
             * If vertical alignment was not found in the shape properties then try to
             * fetch the master shape and search for the align property there.
             */
            int type = getRunType();
            HSLFSheet sh = getSheet();
            HSLFMasterSheet master = (sh != null) ? sh.getMasterSheet() : null;
            HSLFTextShape masterShape = (master != null) ? master.getPlaceholderByTextType(type) : null;
            if (masterShape != null && type != TextHeaderAtom.OTHER_TYPE) {
                align = masterShape.getAlignment();
            } else {
                //not found in the master sheet. Use the hardcoded defaults.
                switch (type){
                     case TextHeaderAtom.TITLE_TYPE:
                     case TextHeaderAtom.CENTER_TITLE_TYPE:
                         align = HSLFTextAnchor.MIDDLE;
                         break;
                     default:
                         align = HSLFTextAnchor.TOP;
                         break;
                 }
            }
        } else {
            align = HSLFTextAnchor.fromNativeId(prop.getPropertyValue());
        }

        if (align == null) {
            align = HSLFTextAnchor.TOP;
        }

        return align;
    }

    /**
     * Sets the type of alignment for the text.
     * One of the <code>Anchor*</code> constants defined in this class.
     *
     * @param isCentered horizontal centered?
     * @param vAlign vertical alignment
     * @param baseline aligned to baseline?
     */
    /* package */ void setAlignment(Boolean isCentered, VerticalAlignment vAlign, boolean baseline) {
        for (HSLFTextAnchor hta : HSLFTextAnchor.values()) {
            if (
                (hta.centered == (isCentered != null && isCentered)) &&
                (hta.vAlign == vAlign) &&
                (hta.baseline == null || hta.baseline == baseline)
            ) {
                setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, hta.nativeId);
                break;
            }
        }
    }

    /**
     * @return true, if vertical alignment is relative to baseline
     * this is only used for older versions less equals Office 2003
     */
    public boolean isAlignToBaseline() {
        return getAlignment().baseline;
    }

    /**
     * Sets the vertical alignment relative to the baseline
     *
     * @param alignToBaseline if true, vertical alignment is relative to baseline
     */
    public void setAlignToBaseline(boolean alignToBaseline) {
        setAlignment(isHorizontalCentered(), getVerticalAlignment(), alignToBaseline);
    }

    @Override
    public boolean isHorizontalCentered() {
        return getAlignment().centered;
    }

    @Override
    public void setHorizontalCentered(Boolean isCentered) {
        setAlignment(isCentered, getVerticalAlignment(), getAlignment().baseline);
    }

    @Override
    public VerticalAlignment getVerticalAlignment() {
        return getAlignment().vAlign;
    }

    @Override
    public void setVerticalAlignment(VerticalAlignment vAlign) {
        setAlignment(isHorizontalCentered(), vAlign, getAlignment().baseline);
    }

    /**
     * Returns the distance (in points) between the bottom of the text frame
     * and the bottom of the inscribed rectangle of the shape that contains the text.
     * Default value is 1/20 inch.
     *
     * @return the botom margin
     */
    public double getBottomInset(){
        return getInset(EscherProperties.TEXT__TEXTBOTTOM, .05);
    }

    /**
     * Sets the botom margin.
     * @see #getBottomInset()
     *
     * @param margin    the bottom margin
     */
    public void setBottomInset(double margin){
        setInset(EscherProperties.TEXT__TEXTBOTTOM, margin);
    }

    /**
     *  Returns the distance (in points) between the left edge of the text frame
     *  and the left edge of the inscribed rectangle of the shape that contains
     *  the text.
     *  Default value is 1/10 inch.
     *
     * @return the left margin
     */
    public double getLeftInset(){
        return getInset(EscherProperties.TEXT__TEXTLEFT, .1);
    }

    /**
     * Sets the left margin.
     * @see #getLeftInset()
     *
     * @param margin    the left margin
     */
    public void setLeftInset(double margin){
        setInset(EscherProperties.TEXT__TEXTLEFT, margin);
    }

    /**
     *  Returns the distance (in points) between the right edge of the
     *  text frame and the right edge of the inscribed rectangle of the shape
     *  that contains the text.
     *  Default value is 1/10 inch.
     *
     * @return the right margin
     */
    public double getRightInset(){
        return getInset(EscherProperties.TEXT__TEXTRIGHT, .1);
    }

    /**
     * Sets the right margin.
     * @see #getRightInset()
     *
     * @param margin    the right margin
     */
    public void setRightInset(double margin){
        setInset(EscherProperties.TEXT__TEXTRIGHT, margin);
    }

     /**
     *  Returns the distance (in points) between the top of the text frame
     *  and the top of the inscribed rectangle of the shape that contains the text.
     *  Default value is 1/20 inch.
     *
     * @return the top margin
     */
    public double getTopInset(){
        return getInset(EscherProperties.TEXT__TEXTTOP, .05);
    }

   /**
     * Sets the top margin.
     * @see #getTopInset()
     *
     * @param margin    the top margin
     */
    public void setTopInset(double margin){
        setInset(EscherProperties.TEXT__TEXTTOP, margin);
    }

    /**
     * Returns the distance (in points) between the edge of the text frame
     * and the edge of the inscribed rectangle of the shape that contains the text.
     * Default value is 1/20 inch.
     *
     * @param propId the id of the inset edge
     * @return the inset in points
     */
    private double getInset(short propId, double defaultInch) {
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, propId);
        int val = prop == null ? (int)(Units.toEMU(Units.POINT_DPI)*defaultInch) : prop.getPropertyValue();
        return Units.toPoints(val);
    }

    /**
     * @param propId the id of the inset edge
     * @param margin the inset in points
     */
    private void setInset(short propId, double margin){
        setEscherProperty(propId, Units.toEMU(margin));
    }

    /**
     * Returns the value indicating word wrap.
     *
     * @return the value indicating word wrap.
     *  Must be one of the <code>Wrap*</code> constants defined in this class.
     *
     * @see <a href="https://msdn.microsoft.com/en-us/library/dd948168(v=office.12).aspx">MSOWRAPMODE</a>
     */
    public int getWordWrapEx() {
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT);
        return prop == null ? WrapSquare : prop.getPropertyValue();
    }

    /**
     *  Specifies how the text should be wrapped
     *
     * @param wrap  the value indicating how the text should be wrapped.
     *  Must be one of the <code>Wrap*</code> constants defined in this class.
     */
    public void setWordWrapEx(int wrap){
        setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap);
    }

    @Override
    public boolean getWordWrap(){
        int ww = getWordWrapEx();
        return (ww != WrapNone);
    }

    @Override
    public void setWordWrap(boolean wrap) {
        setWordWrapEx(wrap ? WrapSquare : WrapNone);
    }

    /**
     * @return id for the text.
     */
    public int getTextId(){
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTID);
        return prop == null ? 0 : prop.getPropertyValue();
    }

    /**
     * Sets text ID
     *
     * @param id of the text
     */
    public void setTextId(int id){
        setEscherProperty(EscherProperties.TEXT__TEXTID, id);
    }

    @Override
    public List<HSLFTextParagraph> getTextParagraphs(){
        if (!_paragraphs.isEmpty()) return _paragraphs;

        _txtbox = getEscherTextboxWrapper();
        if (_txtbox == null) {
            _paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph());
            _txtbox = _paragraphs.get(0).getTextboxWrapper();
        } else {
            _paragraphs = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
            if (_paragraphs == null) {
                // there are actually TextBoxRecords without extra data - see #54722
                _paragraphs = HSLFTextParagraph.createEmptyParagraph(_txtbox);
            }

            if (_paragraphs.isEmpty()) {
                LOG.log(POILogger.WARN, "TextRecord didn't contained any text lines");
            }
        }

        for (HSLFTextParagraph p : _paragraphs) {
            p.setParentShape(this);
        }

        return _paragraphs;
    }

    @Override
    public void setSheet(HSLFSheet sheet) {
        super.setSheet(sheet);

        // Initialize _txtrun object.
        // (We can't do it in the constructor because the sheet
        //  is not assigned then, it's only built once we have
        //  all the records)
        List<HSLFTextParagraph> ltp = getTextParagraphs();
        HSLFTextParagraph.supplySheet(ltp, sheet);
    }

    /**
     * Return {@link OEPlaceholderAtom}, the atom that describes a placeholder.
     *
     * @return {@link OEPlaceholderAtom} or {@code null} if not found
     */
    public OEPlaceholderAtom getPlaceholderAtom(){
        return getClientDataRecord(OEPlaceholderAtom.typeID);
    }

    /**
     * Return {@link RoundTripHFPlaceholder12}, the atom that describes a header/footer placeholder.
     * Compare the {@link RoundTripHFPlaceholder12#getPlaceholderId()} with
     * {@link OEPlaceholderAtom#MasterHeader} or {@link OEPlaceholderAtom#MasterFooter}, to find out
     * what kind of placeholder this is.
     *
     * @return {@link RoundTripHFPlaceholder12} or {@code null} if not found
     * 
     * @since POI 3.14-Beta2
     */
    public RoundTripHFPlaceholder12 getHFPlaceholderAtom() {
        // special case for files saved in Office 2007
        return getClientDataRecord(RoundTripHFPlaceholder12.typeID);
    }
    
    @Override
    public boolean isPlaceholder() {
        OEPlaceholderAtom oep = getPlaceholderAtom();
        if (oep != null) return true;

        //special case for files saved in Office 2007
        RoundTripHFPlaceholder12 hldr = getHFPlaceholderAtom();
        if (hldr != null) return true;

        return false;
    }


    @Override
    public Iterator<HSLFTextParagraph> iterator() {
        return _paragraphs.iterator();
    }

    @Override
    public Insets2D getInsets() {
        Insets2D insets = new Insets2D(getTopInset(), getLeftInset(), getBottomInset(), getRightInset());
        return insets;
    }

    @Override
    public void setInsets(Insets2D insets) {
        setTopInset(insets.top);
        setLeftInset(insets.left);
        setBottomInset(insets.bottom);
        setRightInset(insets.right);
    }

    @Override
    public double getTextHeight(){
        DrawFactory drawFact = DrawFactory.getInstance(null);
        DrawTextShape dts = drawFact.getDrawable(this);
        return dts.getTextHeight();
    }

    @Override
    public TextDirection getTextDirection() {
        // see 2.4.5 MSOTXFL
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTFLOW);
        int msotxfl = (prop == null) ? 0 : prop.getPropertyValue();
        switch (msotxfl) {
            default:
            case 0: // msotxflHorzN
            case 4: // msotxflHorzA
                return TextDirection.HORIZONTAL;
            case 1: // msotxflTtoBA
            case 3: // msotxflTtoBN
            case 5: // msotxflVertN
                return TextDirection.VERTICAL;
            case 2: // msotxflBtoT
                return TextDirection.VERTICAL_270;
            // TextDirection.STACKED is not supported
        }
    }

    @Override
    public void setTextDirection(TextDirection orientation) {
        AbstractEscherOptRecord opt = getEscherOptRecord();
        int msotxfl;
        if (orientation == null) {
            msotxfl = -1;
        } else {
            switch (orientation) {
                default:
                case STACKED:
                    // not supported -> remove
                    msotxfl = -1;
                    break;
                case HORIZONTAL:
                    msotxfl = 0;
                    break;
                case VERTICAL:
                    msotxfl = 1;
                    break;
                case VERTICAL_270:
                    // always interpreted as horizontal
                    msotxfl = 2;
                    break;
            }
        }
        setEscherProperty(opt, EscherProperties.TEXT__TEXTFLOW, msotxfl);
    }
    
    @Override
    public Double getTextRotation() {
        // see 2.4.6 MSOCDIR
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__FONTROTATION);
        return (prop == null) ? null : (90. * prop.getPropertyValue());
    }
    
    @Override
    public void setTextRotation(Double rotation) {
        AbstractEscherOptRecord opt = getEscherOptRecord();
        if (rotation == null) {
            opt.removeEscherProperty(EscherProperties.TEXT__FONTROTATION);
        } else {
            int rot = (int)(Math.round(rotation / 90.) % 4L);
            setEscherProperty(EscherProperties.TEXT__FONTROTATION, rot);
        }
    }
    
    /**
     * Returns the raw text content of the shape. This hasn't had any
     * changes applied to it, and so is probably unlikely to print
     * out nicely.
     */
    public String getRawText() {
        return HSLFTextParagraph.getRawText(getTextParagraphs());
    }

    @Override
    public String getText() {
        String rawText = getRawText();
        return HSLFTextParagraph.toExternalString(rawText, getRunType());
    }

    @Override
    public HSLFTextRun appendText(String text, boolean newParagraph) {
        // init paragraphs
        List<HSLFTextParagraph> paras = getTextParagraphs();
        HSLFTextRun htr = HSLFTextParagraph.appendText(paras, text, newParagraph);
        setTextId(getRawText().hashCode());
        return htr; 
    }

    @Override
    public HSLFTextRun setText(String text) {
        // init paragraphs
        List<HSLFTextParagraph> paras = getTextParagraphs();
        HSLFTextRun htr = HSLFTextParagraph.setText(paras, text);
        setTextId(getRawText().hashCode());
        return htr;
    }

    /**
     * Saves the modified paragraphs/textrun to the records.
     * Also updates the styles to the correct text length.
     */
    protected void storeText() {
        List<HSLFTextParagraph> paras = getTextParagraphs();
        HSLFTextParagraph.storeText(paras);
    }

    /**
     * Returns the array of all hyperlinks in this text run
     *
     * @return the array of all hyperlinks in this text run or <code>null</code>
     *         if not found.
     */
    public List<HSLFHyperlink> getHyperlinks() {
        return HSLFHyperlink.find(this);
    }

    @Override
    public void setTextPlaceholder(TextPlaceholder placeholder) {
        // TOOD: check for correct placeholder handling - see org.apache.poi.hslf.model.Placeholder
        Placeholder ph = null;
        int runType;
        switch (placeholder) {
            default:
            case BODY:
                runType = TextHeaderAtom.BODY_TYPE;
                ph = Placeholder.BODY;
                break;
            case TITLE:
                runType = TextHeaderAtom.TITLE_TYPE;
                ph = Placeholder.TITLE;
                break;
            case CENTER_BODY:
                runType = TextHeaderAtom.CENTRE_BODY_TYPE;
                ph = Placeholder.BODY;
                break;
            case CENTER_TITLE:
                runType = TextHeaderAtom.CENTER_TITLE_TYPE;
                ph = Placeholder.TITLE;
                break;
            case HALF_BODY:
                runType = TextHeaderAtom.HALF_BODY_TYPE;
                ph = Placeholder.BODY;
                break;
            case QUARTER_BODY:
                runType = TextHeaderAtom.QUARTER_BODY_TYPE;
                ph = Placeholder.BODY;
                break;
            case NOTES:
                runType = TextHeaderAtom.NOTES_TYPE;
                break;
            case OTHER:
                runType = TextHeaderAtom.OTHER_TYPE;
                break;
        }
        setRunType(runType);
        if (ph != null) {
            setPlaceholder(ph);
        }
    }

    @Override
    public TextPlaceholder getTextPlaceholder() {
        switch (getRunType()) {
            default:
            case TextHeaderAtom.BODY_TYPE: return TextPlaceholder.BODY;
            case TextHeaderAtom.TITLE_TYPE: return TextPlaceholder.TITLE;
            case TextHeaderAtom.NOTES_TYPE: return TextPlaceholder.NOTES;
            case TextHeaderAtom.OTHER_TYPE: return TextPlaceholder.OTHER;
            case TextHeaderAtom.CENTRE_BODY_TYPE: return TextPlaceholder.CENTER_BODY;
            case TextHeaderAtom.CENTER_TITLE_TYPE: return TextPlaceholder.CENTER_TITLE;
            case TextHeaderAtom.HALF_BODY_TYPE: return TextPlaceholder.HALF_BODY;
            case TextHeaderAtom.QUARTER_BODY_TYPE: return TextPlaceholder.QUARTER_BODY;
        }
    }


    /**
     * Get alternative representation of text shape stored as metro blob escher property.
     * The returned shape is the first shape in stored group shape of the metro blob
     *
     * @return null, if there's no alternative representation, otherwise the text shape
     */
    public TextShape<?,?> getMetroShape() {
        HSLFMetroShape<TextShape<?,?>> mbs = new HSLFMetroShape<TextShape<?,?>>(this);
        return mbs.getShape();
    }
}