/* ====================================================================
   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.xslf.usermodel;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.apache.poi.ooxml.util.POIXMLUnits;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.TabStop.TabStopType;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.util.Units;
import org.apache.poi.xslf.model.ParagraphPropertyFetcher;
import org.apache.poi.xslf.model.ParagraphPropertyFetcher.ParaPropFetcher;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;

/**
 * Represents a paragraph of text within the containing text body.
 * The paragraph is the highest level text separation mechanism.
 *
 * @since POI-3.8
 */
@Beta
public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagraph,XSLFTextRun> {
    private final CTTextParagraph _p;
    private final List<XSLFTextRun> _runs;
    private final XSLFTextShape _shape;

    @FunctionalInterface
    private interface Procedure {
        void accept();
    }

    XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape) {
        _p = p;
        _runs = new ArrayList<>();
        _shape = shape;

        try (XmlCursor c = _p.newCursor()) {
            if (c.toFirstChild()) {
                do {
                    XmlObject r = c.getObject();
                    if (r instanceof CTTextLineBreak) {
                        _runs.add(new XSLFLineBreak((CTTextLineBreak)r, this));
                    } else if (r instanceof CTRegularTextRun || r instanceof CTTextField) {
                        _runs.add(new XSLFTextRun(r, this));
                    }
                } while (c.toNextSibling());
            }
        }
    }

    public String getText() {
        StringBuilder out = new StringBuilder();
        for (XSLFTextRun r : _runs) {
            out.append(r.getRawText());
        }
        return out.toString();
    }

    @Internal
    public CTTextParagraph getXmlObject() {
        return _p;
    }

    @Override
    public XSLFTextShape getParentShape() {
        return _shape;

    }

    @Override
    public List<XSLFTextRun> getTextRuns() {
        return Collections.unmodifiableList(_runs);
    }

    @Override
    public Iterator<XSLFTextRun> iterator() {
        return getTextRuns().iterator();
    }

    /**
     * Add a new run of text
     *
     * @return a new run of text
     */
    public XSLFTextRun addNewTextRun() {
        CTRegularTextRun r = _p.addNewR();
        CTTextCharacterProperties rPr = r.addNewRPr();
        rPr.setLang("en-US");
        XSLFTextRun run = newTextRun(r);
        _runs.add(run);
        return run;
    }

    /**
     * Remove a text run
     *
     * @param  textRun a run of text
     * @return whether the run was removed
     * @since POI 5.2.2
     */
    public boolean removeTextRun(XSLFTextRun textRun) {
        if (_runs.remove(textRun)) {
            XmlObject xo = textRun.getXmlObject();
            if (xo instanceof CTRegularTextRun) {
                for (int i = 0; i < getXmlObject().sizeOfRArray(); i++) {
                    if (getXmlObject().getRArray(i).equals(xo)) {
                        getXmlObject().removeR(i);
                        return true;
                    }
                }
            } else if (xo instanceof CTTextField) {
                for (int i = 0; i < getXmlObject().sizeOfFldArray(); i++) {
                    if (getXmlObject().getFldArray(i).equals(xo)) {
                        getXmlObject().removeFld(i);
                        return true;
                    }
                }
            } else if (xo instanceof CTTextLineBreak) {
                for (int i = 0; i < getXmlObject().sizeOfBrArray(); i++) {
                    if (getXmlObject().getBrArray(i).equals(xo)) {
                        getXmlObject().removeBr(i);
                        return true;
                    }
                }
            }
            return false;
        }
        return false;
    }

    /**
     * Insert a line break
     *
     * @return text run representing this line break ('\n')
     */
    @SuppressWarnings("WeakerAccess")
    public XSLFTextRun addLineBreak() {
        XSLFLineBreak run = new XSLFLineBreak(_p.addNewBr(), this);
        CTTextCharacterProperties brProps = run.getRPr(true);
        if (!_runs.isEmpty()) {
            // by default line break has the font size of the last text run
            CTTextCharacterProperties prevRun = _runs.get(_runs.size() - 1).getRPr(true);
            brProps.set(prevRun);
            // don't copy hlink properties
            if (brProps.isSetHlinkClick()) {
                brProps.unsetHlinkClick();
            }
            if (brProps.isSetHlinkMouseOver()) {
                brProps.unsetHlinkMouseOver();
            }
        }
        _runs.add(run);
        return run;
    }

    @Override
    public TextAlign getTextAlign() {
        return fetchParagraphProperty((props,val) -> {
            if (props.isSetAlgn()) {
                val.accept(TextAlign.values()[props.getAlgn().intValue() - 1]);
            }
        });
    }

    @Override
    public void setTextAlign(TextAlign align) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if(align == null) {
            if(pr.isSetAlgn()) {
                pr.unsetAlgn();
            }
        } else {
            pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1));
        }
    }

    @Override
    public FontAlign getFontAlign() {
        return fetchParagraphProperty((props,val) -> {
            if (props.isSetFontAlgn()) {
                val.accept(FontAlign.values()[props.getFontAlgn().intValue() - 1]);
            }
        });
    }

    /**
     * Specifies the font alignment that is to be applied to the paragraph.
     * Possible values for this include auto, top, center, baseline and bottom.
     * see {@link org.apache.poi.sl.usermodel.TextParagraph.FontAlign}.
     *
     * @param align font align
     */
    @SuppressWarnings("unused")
    public void setFontAlign(FontAlign align) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if(align == null) {
            if(pr.isSetFontAlgn()) {
                pr.unsetFontAlgn();
            }
        } else {
            pr.setFontAlgn(STTextFontAlignType.Enum.forInt(align.ordinal() + 1));
        }
    }



    /**
     * @return the font to be used on bullet characters within a given paragraph
     */
    @SuppressWarnings("WeakerAccess")
    public String getBulletFont() {
        return fetchParagraphProperty((props, val) -> {
            if (props.isSetBuFont()) {
                val.accept(props.getBuFont().getTypeface());
            }
        });
    }

    @SuppressWarnings("WeakerAccess")
    public void setBulletFont(String typeface) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTTextFont font = pr.isSetBuFont() ? pr.getBuFont() : pr.addNewBuFont();
        font.setTypeface(typeface);
    }

    /**
     * @return the character to be used in place of the standard bullet point
     */
    @SuppressWarnings("WeakerAccess")
    public String getBulletCharacter() {
        return fetchParagraphProperty((props, val) -> {
            if (props.isSetBuChar()) {
                val.accept(props.getBuChar().getChar());
            }
        });
    }

    @SuppressWarnings("WeakerAccess")
    public void setBulletCharacter(String str) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTTextCharBullet c = pr.isSetBuChar() ? pr.getBuChar() : pr.addNewBuChar();
        c.setChar(str);
    }

    /**
     *
     * @return the color of bullet characters within a given paragraph.
     * A <code>null</code> value means to use the text font color.
     */
    @SuppressWarnings("WeakerAccess")
    public PaintStyle getBulletFontColor() {
        Color col = fetchParagraphProperty(this::fetchBulletFontColor);
        return (col == null) ? null : DrawPaint.createSolidPaint(col);
    }

    private void fetchBulletFontColor(CTTextParagraphProperties props, Consumer<Color> val) {
        final XSLFSheet sheet = getParentShape().getSheet();
        final XSLFTheme theme = sheet.getTheme();
        if(props.isSetBuClr()) {
            XSLFColor c = new XSLFColor(props.getBuClr(), theme, null, sheet);
            val.accept(c.getColor());
        }
    }

    @SuppressWarnings("WeakerAccess")
    public void setBulletFontColor(Color color) {
        setBulletFontColor(DrawPaint.createSolidPaint(color));
    }


    /**
     * Set the color to be used on bullet characters within a given paragraph.
     *
     * @param color the bullet color
     */
    @SuppressWarnings("WeakerAccess")
    public void setBulletFontColor(PaintStyle color) {
        if (!(color instanceof SolidPaint)) {
            throw new IllegalArgumentException("Currently XSLF only supports SolidPaint");
        }

        // TODO: implement setting bullet color to null
        SolidPaint sp = (SolidPaint)color;
        Color col = DrawPaint.applyColorTransform(sp.getSolidColor());

        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr();
        CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr();
        clr.setVal(new byte[]{(byte) col.getRed(), (byte) col.getGreen(), (byte) col.getBlue()});
    }

    /**
     * Returns the bullet size that is to be used within a paragraph.
     * This may be specified in two different ways, percentage spacing and font point spacing:
     * <p>
     * If bulletSize &gt;= 0, then bulletSize is a percentage of the font size.
     * If bulletSize &lt; 0, then it specifies the size in points
     * </p>
     *
     * @return the bullet size
     */
    @SuppressWarnings("WeakerAccess")
    public Double getBulletFontSize() {
        return fetchParagraphProperty(XSLFTextParagraph::fetchBulletFontSize);
    }

    private static void fetchBulletFontSize(CTTextParagraphProperties props, Consumer<Double> val) {
        if(props.isSetBuSzPct()) {
            val.accept(POIXMLUnits.parsePercent(props.getBuSzPct().xgetVal()) * 0.001);
        }
        if(props.isSetBuSzPts()) {
            val.accept( - props.getBuSzPts().getVal() * 0.01);
        }
    }


    /**
     * Sets the bullet size that is to be used within a paragraph.
     * This may be specified in two different ways, percentage spacing and font point spacing:
     * <p>
     * If bulletSize &gt;= 0, then bulletSize is a percentage of the font size.
     * If bulletSize &lt; 0, then it specifies the size in points
     * </p>
     */
    @SuppressWarnings("WeakerAccess")
    public void setBulletFontSize(double bulletSize) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();

        if(bulletSize >= 0) {
            CTTextBulletSizePercent pt = pr.isSetBuSzPct() ? pr.getBuSzPct() : pr.addNewBuSzPct();
            pt.setVal(Integer.toString((int)(bulletSize*1000)));
            if(pr.isSetBuSzPts()) {
                pr.unsetBuSzPts();
            }
        } else {
            CTTextBulletSizePoint pt = pr.isSetBuSzPts() ? pr.getBuSzPts() : pr.addNewBuSzPts();
            pt.setVal((int)(-bulletSize*100));
            if(pr.isSetBuSzPct()) {
                pr.unsetBuSzPct();
            }
        }
   }

    /**
     * @return the auto numbering scheme, or null if not defined
     */
    @SuppressWarnings("WeakerAccess")
    public AutoNumberingScheme getAutoNumberingScheme() {
        return fetchParagraphProperty(XSLFTextParagraph::fetchAutoNumberingScheme);
    }

    private static void fetchAutoNumberingScheme(CTTextParagraphProperties props, Consumer<AutoNumberingScheme> val) {
        if (props.isSetBuAutoNum()) {
            AutoNumberingScheme ans = AutoNumberingScheme.forOoxmlID(props.getBuAutoNum().getType().intValue());
            if (ans != null) {
                val.accept(ans);
            }
        }
    }


    /**
     * @return the auto numbering starting number, or null if not defined
     */
    @SuppressWarnings("WeakerAccess")
    public Integer getAutoNumberingStartAt() {
        return fetchParagraphProperty((props, val) -> {
            if (props.isSetBuAutoNum() && props.getBuAutoNum().isSetStartAt()) {
                val.accept(props.getBuAutoNum().getStartAt());
            }
        });
    }

    @Override
    public void setIndent(Double indent) {
        if ((indent == null) && !_p.isSetPPr()) {
            return;
        }
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if(indent == null) {
            if(pr.isSetIndent()) {
                pr.unsetIndent();
            }
        } else {
            pr.setIndent(Units.toEMU(indent));
        }
    }

    @Override
    public Double getIndent() {
        return fetchParagraphProperty((props, val) -> {
            if (props.isSetIndent()) {
                val.accept(Units.toPoints(props.getIndent()));
            }
        });
    }


    @Override
    public void setLeftMargin(Double leftMargin) {
        if (leftMargin == null && !_p.isSetPPr()) {
            return;
        }
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if (leftMargin == null) {
            if(pr.isSetMarL()) {
                pr.unsetMarL();
            }
        } else {
            pr.setMarL(Units.toEMU(leftMargin));
        }

    }

    /**
     * @return the left margin (in points) of the paragraph, null if unset
     */
    @Override
    public Double getLeftMargin() {
        return fetchParagraphProperty((props, val) -> {
            if (props.isSetMarL()) {
                val.accept(Units.toPoints(props.getMarL()));
            }
        });
    }

    @Override
    public void setRightMargin(Double rightMargin) {
        if (rightMargin == null && !_p.isSetPPr()) {
            return;
        }
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if(rightMargin == null) {
            if(pr.isSetMarR()) {
                pr.unsetMarR();
            }
        } else {
            pr.setMarR(Units.toEMU(rightMargin));
        }
    }

    /**
     *
     * @return the right margin of the paragraph, null if unset
     */
    @Override
    public Double getRightMargin() {
        return fetchParagraphProperty((props, val) -> {
            if (props.isSetMarR()) {
                val.accept(Units.toPoints(props.getMarR()));
            }
        });
    }

    @Override
    public Double getDefaultTabSize() {
        return fetchParagraphProperty((props, val) -> {
            if (props.isSetDefTabSz()) {
                val.accept(Units.toPoints(POIXMLUnits.parseLength(props.xgetDefTabSz())));
            }
        });
    }

    @SuppressWarnings("WeakerAccess")
    public double getTabStop(final int idx) {
        Double d = fetchParagraphProperty((props,val) -> fetchTabStop(idx,props,val));
        return (d == null) ? 0. : d;
    }

    private static void fetchTabStop(final int idx, CTTextParagraphProperties props, Consumer<Double> val) {
        if (props.isSetTabLst()) {
            CTTextTabStopList tabStops = props.getTabLst();
            if(idx < tabStops.sizeOfTabArray() ) {
                CTTextTabStop ts = tabStops.getTabArray(idx);
                val.accept(Units.toPoints(POIXMLUnits.parseLength(ts.xgetPos())));
            }
        }
    }


    @SuppressWarnings("WeakerAccess")
    public void addTabStop(double value) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTTextTabStopList tabStops = pr.isSetTabLst() ? pr.getTabLst() : pr.addNewTabLst();
        tabStops.addNewTab().setPos(Units.toEMU(value));
    }

    @Override
    public void setLineSpacing(Double lineSpacing) {
        setSpacing(lineSpacing, props -> props::getLnSpc, props -> props::addNewLnSpc, props -> props::unsetLnSpc);
    }

    @Override
    public Double getLineSpacing() {
        final Double lnSpc = getSpacing(props -> props::getLnSpc);
        if (lnSpc != null && lnSpc > 0) {
            // check if the percentage value is scaled
            final CTTextNormalAutofit normAutofit = getParentShape().getTextBodyPr().getNormAutofit();
            if (normAutofit != null) {
                final double scale = 1 - POIXMLUnits.parsePercent(normAutofit.xgetLnSpcReduction()) / 100_000.;
                return lnSpc * scale;
            }
        }

        return lnSpc;
    }

    @Override
    public void setSpaceBefore(Double spaceBefore) {
        setSpacing(spaceBefore, props -> props::getSpcBef, props -> props::addNewSpcBef, props -> props::unsetSpcBef);
    }

    @Override
    public Double getSpaceBefore() {
        return getSpacing(props -> props::getSpcBef);
    }

    @Override
    public void setSpaceAfter(Double spaceAfter) {
        setSpacing(spaceAfter, props -> props::getSpcAft, props -> props::addNewSpcAft, props -> props::unsetSpcAft);
    }

    @Override
    public Double getSpaceAfter() {
        return getSpacing(props -> props::getSpcAft);
    }

    private void setSpacing(final Double space,
        final Function<CTTextParagraphProperties,Supplier<CTTextSpacing>> getSpc,
        final Function<CTTextParagraphProperties,Supplier<CTTextSpacing>> addSpc,
        final Function<CTTextParagraphProperties,Procedure> unsetSpc
    ) {
        final CTTextParagraphProperties pPr = (space == null || _p.isSetPPr()) ?  _p.getPPr() : _p.addNewPPr();
        if (pPr == null) {
            return;
        }

        CTTextSpacing spc = getSpc.apply(pPr).get();

        if (space == null) {
            if (spc != null) {
                // unset the space before on null input
                unsetSpc.apply(pPr).accept();
            }
            return;
        }

        if (spc == null) {
            spc = addSpc.apply(pPr).get();
        }

        if (space >= 0) {
            if (spc.isSetSpcPts()) {
                spc.unsetSpcPts();
            }
            final CTTextSpacingPercent pct = spc.isSetSpcPct() ? spc.getSpcPct() : spc.addNewSpcPct();
            pct.setVal((int)(space*1000));
        } else {
            if (spc.isSetSpcPct()) {
                spc.unsetSpcPct();
            }
            final CTTextSpacingPoint pts = spc.isSetSpcPts() ? spc.getSpcPts() : spc.addNewSpcPts();
            pts.setVal((int)(-space*100));
        }
    }

    private Double getSpacing(final Function<CTTextParagraphProperties,Supplier<CTTextSpacing>> getSpc) {
        return fetchParagraphProperty((props,val) -> fetchSpacing(getSpc,props,val));
    }

    private static void fetchSpacing(final Function<CTTextParagraphProperties,Supplier<CTTextSpacing>> getSpc,
                                        CTTextParagraphProperties props, Consumer<Double> val) {
        final CTTextSpacing spc = getSpc.apply(props).get();
        if (spc != null) {
            if (spc.isSetSpcPct()) {
                val.accept( POIXMLUnits.parsePercent(spc.getSpcPct().xgetVal())*0.001 );
            } else if (spc.isSetSpcPts()) {
                val.accept( -spc.getSpcPts().getVal()*0.01 );
            }
        }
    }


    @Override
    public void setIndentLevel(int level) {
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        pr.setLvl(level);
    }

    @Override
    public int getIndentLevel() {
        CTTextParagraphProperties pr = _p.getPPr();
        return (pr == null || !pr.isSetLvl()) ? 0 : pr.getLvl();
    }

    /**
     * Returns whether this paragraph has bullets
     */
    public boolean isBullet() {
        Boolean b = fetchParagraphProperty(XSLFTextParagraph::fetchIsBullet);
        return b == null ? false : b;
    }

    private static void fetchIsBullet(CTTextParagraphProperties props, Consumer<Boolean> val) {
        if (props.isSetBuNone()) {
            val.accept(false);
        } else if(props.isSetBuFont() || props.isSetBuChar()) {
            val.accept(true);
        }
    }


    /**
     *
     * @param flag whether text in this paragraph has bullets
     */
    public void setBullet(boolean flag) {
        if(isBullet() == flag) {
            return;
        }

        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        if(flag) {
            pr.addNewBuFont().setTypeface("Arial");
            pr.addNewBuChar().setChar("\u2022");
        } else {
            if (pr.isSetBuFont()) {
                pr.unsetBuFont();
            }
            if (pr.isSetBuChar()) {
                pr.unsetBuChar();
            }
            if (pr.isSetBuAutoNum()) {
                pr.unsetBuAutoNum();
            }
            if (pr.isSetBuBlip()) {
                pr.unsetBuBlip();
            }
            if (pr.isSetBuClr()) {
                pr.unsetBuClr();
            }
            if (pr.isSetBuClrTx()) {
                pr.unsetBuClrTx();
            }
            if (pr.isSetBuFont()) {
                pr.unsetBuFont();
            }
            if (pr.isSetBuFontTx()) {
                pr.unsetBuFontTx();
            }
            if (pr.isSetBuSzPct()) {
                pr.unsetBuSzPct();
            }
            if (pr.isSetBuSzPts()) {
                pr.unsetBuSzPts();
            }
            if (pr.isSetBuSzTx()) {
                pr.unsetBuSzTx();
            }
            pr.addNewBuNone();
        }
    }

    /**
     * Specifies that automatic numbered bullet points should be applied to this paragraph
     *
     * @param scheme type of auto-numbering
     * @param startAt the number that will start number for a given sequence of automatically
    numbered bullets (1-based).
     */
    @SuppressWarnings("WeakerAccess")
    public void setBulletAutoNumber(AutoNumberingScheme scheme, int startAt) {
        if(startAt < 1) {
            throw new IllegalArgumentException("Start Number must be greater or equal that 1") ;
        }
        CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
        CTTextAutonumberBullet lst = pr.isSetBuAutoNum() ? pr.getBuAutoNum() : pr.addNewBuAutoNum();
        lst.setType(STTextAutonumberScheme.Enum.forInt(scheme.ooxmlId));
        lst.setStartAt(startAt);
    }

    @Override
    public String toString() {
        return "[" + getClass() + "]" + getText();
    }


    /**
     * @return master style text paragraph properties, or <code>null</code> if
     * there are no master slides or the master slides do not contain a text paragraph
     */
    @Internal
    public CTTextParagraphProperties getDefaultMasterStyle() {
        CTPlaceholder ph = _shape.getPlaceholderDetails().getCTPlaceholder(false);
        String defaultStyleSelector;
        switch(ph == null ? -1 : ph.getType().intValue()) {
            case STPlaceholderType.INT_TITLE:
            case STPlaceholderType.INT_CTR_TITLE:
                defaultStyleSelector = "titleStyle";
                break;
            case -1: // no placeholder means plain text box
            case STPlaceholderType.INT_FTR:
            case STPlaceholderType.INT_SLD_NUM:
            case STPlaceholderType.INT_DT:
                defaultStyleSelector = "otherStyle";
                break;
            default:
                defaultStyleSelector = "bodyStyle";
                break;
        }
        int level = getIndentLevel();

        // wind up and find the root master sheet which must be slide master
        final String nsPML = "http://schemas.openxmlformats.org/presentationml/2006/main";
        XSLFSheet masterSheet = _shape.getSheet();
        for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {
            masterSheet = m;
            XmlObject xo = masterSheet.getXmlObject();
            try (XmlCursor cur = xo.newCursor()) {
                cur.push();
                if ((cur.toChild(nsPML, "txStyles") && cur.toChild(nsPML, defaultStyleSelector)) ||
                    (cur.pop() && cur.toChild(nsPML, "notesStyle"))) {
                    while (level >= 0) {
                        cur.push();
                        if (cur.toChild(XSLFRelation.NS_DRAWINGML, "lvl" +(level+1)+ "pPr")) {
                            return (CTTextParagraphProperties)cur.getObject();
                        }
                        cur.pop();
                        level--;
                    }
                }
            }
        }

        return null;
    }

    private <T> T fetchParagraphProperty(ParaPropFetcher<T> fetcher) {
        final XSLFTextShape shape = getParentShape();
        return new ParagraphPropertyFetcher<>(this, fetcher).fetchProperty(shape);
    }


    void copy(XSLFTextParagraph other) {
        if (other == this) {
            return;
        }

        CTTextParagraph thisP = getXmlObject();
        CTTextParagraph otherP = other.getXmlObject();

        if (thisP.isSetPPr()) {
            thisP.unsetPPr();
        }
        if (thisP.isSetEndParaRPr()) {
            thisP.unsetEndParaRPr();
        }

        _runs.clear();
        for (int i=thisP.sizeOfBrArray(); i>0; i--) {
            thisP.removeBr(i-1);
        }
        for (int i=thisP.sizeOfRArray(); i>0; i--) {
            thisP.removeR(i-1);
        }
        for (int i=thisP.sizeOfFldArray(); i>0; i--) {
            thisP.removeFld(i-1);
        }

        for (XSLFTextRun tr : other.getTextRuns()) {
            XmlObject xo = tr.getXmlObject().copy();
            XSLFTextRun run = addNewTextRun();
            run.getXmlObject().set(xo);
            run.copy(tr);
        }

        // set properties again, in case we are based on a different
        // template
        TextAlign srcAlign = other.getTextAlign();
        if(srcAlign != getTextAlign()) {
            setTextAlign(srcAlign);
        }

        boolean isBullet = other.isBullet();
        if(isBullet != isBullet()) {
            setBullet(isBullet);
            if(isBullet) {
                String buFont = other.getBulletFont();
                if(buFont != null && !buFont.equals(getBulletFont())) {
                    setBulletFont(buFont);
                }
                String buChar = other.getBulletCharacter();
                if(buChar != null && !buChar.equals(getBulletCharacter())) {
                    setBulletCharacter(buChar);
                }
                PaintStyle buColor = other.getBulletFontColor();
                if(buColor != null && !buColor.equals(getBulletFontColor())) {
                    setBulletFontColor(buColor);
                }
                Double buSize = other.getBulletFontSize();
                if(doubleNotEquals(buSize, getBulletFontSize())) {
                    setBulletFontSize(buSize);
                }
            }
        }

        Double leftMargin = other.getLeftMargin();
        if (doubleNotEquals(leftMargin, getLeftMargin())) {
            setLeftMargin(leftMargin);
        }

        Double indent = other.getIndent();
        if (doubleNotEquals(indent, getIndent())) {
            setIndent(indent);
        }

        Double spaceAfter = other.getSpaceAfter();
        if (doubleNotEquals(spaceAfter, getSpaceAfter())) {
            setSpaceAfter(spaceAfter);
        }

        Double spaceBefore = other.getSpaceBefore();
        if (doubleNotEquals(spaceBefore, getSpaceBefore())) {
            setSpaceBefore(spaceBefore);
        }

        Double lineSpacing = other.getLineSpacing();
        if (doubleNotEquals(lineSpacing, getLineSpacing())) {
            setLineSpacing(lineSpacing);
        }
    }

    private static boolean doubleNotEquals(Double d1, Double d2) {
        return !Objects.equals(d1, d2);
    }

    @Override
    public Double getDefaultFontSize() {
        CTTextCharacterProperties endPr = _p.getEndParaRPr();
        if (endPr == null || !endPr.isSetSz()) {
            // inherit the font size from the master style
            CTTextParagraphProperties masterStyle = getDefaultMasterStyle();
            if (masterStyle != null) {
                endPr = masterStyle.getDefRPr();
            }
        }
        return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100.);
    }

    @Override
    public String getDefaultFontFamily() {
        String family = (_runs.isEmpty() ? null : _runs.get(0).getFontFamily());
        return (family == null) ? "Arial" : family;
    }

    @Override
    public BulletStyle getBulletStyle() {
        if (!isBullet()) {
            return null;
        }
        return new BulletStyle() {
            @Override
            public String getBulletCharacter() {
                return XSLFTextParagraph.this.getBulletCharacter();
            }

            @Override
            public String getBulletFont() {
                return XSLFTextParagraph.this.getBulletFont();
            }

            @Override
            public Double getBulletFontSize() {
                return XSLFTextParagraph.this.getBulletFontSize();
            }

            @Override
            public PaintStyle getBulletFontColor() {
                return XSLFTextParagraph.this.getBulletFontColor();
            }

            @Override
            public void setBulletFontColor(Color color) {
                setBulletFontColor(DrawPaint.createSolidPaint(color));
            }

            @Override
            public void setBulletFontColor(PaintStyle color) {
                XSLFTextParagraph.this.setBulletFontColor(color);
            }

            @Override
            public AutoNumberingScheme getAutoNumberingScheme() {
                return XSLFTextParagraph.this.getAutoNumberingScheme();
            }

            @Override
            public Integer getAutoNumberingStartAt() {
                return XSLFTextParagraph.this.getAutoNumberingStartAt();
            }

        };
    }

    @Override
    public void setBulletStyle(Object... styles) {
        if (styles.length == 0) {
            setBullet(false);
        } else {
            setBullet(true);
            for (Object ostyle : styles) {
                if (ostyle instanceof Number) {
                    setBulletFontSize(((Number)ostyle).doubleValue());
                } else if (ostyle instanceof Color) {
                    setBulletFontColor((Color)ostyle);
                } else if (ostyle instanceof Character) {
                    setBulletCharacter(ostyle.toString());
                } else if (ostyle instanceof String) {
                    setBulletFont((String)ostyle);
                } else if (ostyle instanceof AutoNumberingScheme) {
                    setBulletAutoNumber((AutoNumberingScheme)ostyle, 0);
                }
            }
        }
    }

    @Override
    public List<XSLFTabStop> getTabStops() {
        return fetchParagraphProperty(XSLFTextParagraph::fetchTabStops);
    }

    private static void fetchTabStops(CTTextParagraphProperties props, Consumer<List<XSLFTabStop>> val) {
        if (props.isSetTabLst()) {
            final List<XSLFTabStop> list = new ArrayList<>();
            //noinspection deprecation
            for (final CTTextTabStop ta : props.getTabLst().getTabArray()) {
                list.add(new XSLFTabStop(ta));
            }
            val.accept(list);
        }
    }



    @Override
    public void addTabStops(double positionInPoints, TabStopType tabStopType) {
        final XSLFSheet sheet = getParentShape().getSheet();
        final CTTextParagraphProperties tpp;
        if (sheet instanceof XSLFSlideMaster) {
            tpp = getDefaultMasterStyle();
        } else {
            final CTTextParagraph xo = getXmlObject();
            tpp = (xo.isSetPPr()) ? xo.getPPr() : xo.addNewPPr();
        }

        if (tpp == null) {
            return;
        }
        final CTTextTabStopList stl = (tpp.isSetTabLst()) ? tpp.getTabLst() : tpp.addNewTabLst();
        XSLFTabStop tab = new XSLFTabStop(stl.addNewTab());
        tab.setPositionInPoints(positionInPoints);
        tab.setType(tabStopType);
    }

    @Override
    public void clearTabStops() {
        final XSLFSheet sheet = getParentShape().getSheet();
        CTTextParagraphProperties tpp = (sheet instanceof XSLFSlideMaster) ? getDefaultMasterStyle() : getXmlObject().getPPr();
        if (tpp != null && tpp.isSetTabLst()) {
            tpp.unsetTabLst();
        }
    }

    /**
     * Helper method for appending text and keeping paragraph and character properties.
     * The character properties are moved to the end paragraph marker
     */
    /* package */ void clearButKeepProperties() {
        CTTextParagraph thisP = getXmlObject();
        for (int i=thisP.sizeOfBrArray(); i>0; i--) {
            thisP.removeBr(i-1);
        }
        for (int i=thisP.sizeOfFldArray(); i>0; i--) {
            thisP.removeFld(i-1);
        }
        if (!_runs.isEmpty()) {
            int size = _runs.size();
            XSLFTextRun lastRun = _runs.get(size-1);
            CTTextCharacterProperties cpOther = lastRun.getRPr(false);
            if (cpOther != null) {
                if (thisP.isSetEndParaRPr()) {
                    thisP.unsetEndParaRPr();
                }
                CTTextCharacterProperties cp = thisP.addNewEndParaRPr();
                cp.set(cpOther);
            }
            for (int i=size; i>0; i--) {
                thisP.removeR(i-1);
            }
            _runs.clear();
        }
    }

    @Override
    public boolean isHeaderOrFooter() {
        CTPlaceholder ph = _shape.getPlaceholderDetails().getCTPlaceholder(false);
        int phId = (ph == null ? -1 : ph.getType().intValue());
        switch (phId) {
            case STPlaceholderType.INT_SLD_NUM:
            case STPlaceholderType.INT_DT:
            case STPlaceholderType.INT_FTR:
            case STPlaceholderType.INT_HDR:
                return true;
            default:
                return false;
        }
    }

    /**
     * Helper method to allow subclasses to provide their own text run
     *
     * @param r the xml reference
     *
     * @return a new text paragraph
     *
     * @since POI 3.15-beta2
     */
    protected XSLFTextRun newTextRun(XmlObject r) {
        return new XSLFTextRun(r, this);
    }

    @SuppressWarnings("WeakerAccess")
    protected XSLFTextRun newTextRun(CTTextLineBreak r) {
        return new XSLFLineBreak(r, this);
    }
}
