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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Spliterator;
import java.util.function.Function;
import java.util.function.Predicate;

import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.SimpleShape;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.poi.xddf.usermodel.XDDFColor;
import org.apache.poi.xddf.usermodel.XDDFColorRgbBinary;
import org.apache.poi.xddf.usermodel.XDDFFillProperties;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.text.TextContainer;
import org.apache.poi.xddf.usermodel.text.XDDFRunProperties;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextHorzOverflowType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVertOverflowType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRElt;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRPrElt;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues;

/**
 * Represents a shape with a predefined geometry in a SpreadsheetML drawing.
 * Possible shape types are defined in
 * {@link org.apache.poi.ss.usermodel.ShapeTypes}
 */
public class XSSFSimpleShape extends XSSFShape implements Iterable<XSSFTextParagraph>, SimpleShape, TextContainer {
    /**
     * The text body containing the paragraphs for this shape.
     */
    private final XDDFTextBody _textBody;
    /**
     * List of the paragraphs that make up the text in this shape
     */
    private final List<XSSFTextParagraph> _paragraphs;
    /**
     * A default instance of CTShape used for creating new shapes.
     */
    private static CTShape prototype;

    /**
     * Xml bean that stores properties of this shape
     */
    private CTShape ctShape;

    protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) {
        this.drawing = drawing;
        this.ctShape = ctShape;

        _paragraphs = new ArrayList<>();

        // initialize any existing paragraphs - this will be the default body
        // paragraph in a new shape,
        // or existing paragraphs that have been loaded from the file
        CTTextBody body = ctShape.getTxBody();
        if (body == null) {
            _textBody = null;
        } else {
            _textBody = new XDDFTextBody(this, body);
            for (int i = 0; i < body.sizeOfPArray(); i++) {
                _paragraphs.add(new XSSFTextParagraph(body.getPArray(i), ctShape));
            }
        }
    }

    /**
     * Prototype with the default structure of a new auto-shape.
     */
    protected static CTShape prototype() {
        if (prototype == null) {
            CTShape shape = CTShape.Factory.newInstance();

            CTShapeNonVisual nv = shape.addNewNvSpPr();
            CTNonVisualDrawingProps nvp = nv.addNewCNvPr();
            nvp.setId(1);
            nvp.setName("Shape 1");
            nv.addNewCNvSpPr();

            CTShapeProperties sp = shape.addNewSpPr();
            CTTransform2D t2d = sp.addNewXfrm();
            CTPositiveSize2D p1 = t2d.addNewExt();
            p1.setCx(0);
            p1.setCy(0);
            CTPoint2D p2 = t2d.addNewOff();
            p2.setX(0);
            p2.setY(0);

            CTPresetGeometry2D geom = sp.addNewPrstGeom();
            geom.setPrst(STShapeType.RECT);
            geom.addNewAvLst();

            XDDFTextBody body = new XDDFTextBody(null, shape.addNewTxBody());
            XDDFTextParagraph p = body.initialize();
            XDDFRunProperties rp = p.getAfterLastRunProperties();
            XDDFColor black = new XDDFColorRgbBinary(new byte[] { 0, 0, 0 });
            XDDFFillProperties fp = new XDDFSolidFillProperties(black);
            rp.setFillProperties(fp);

            prototype = shape;
        }
        return prototype;
    }

    @Internal
    public CTShape getCTShape() {
        return ctShape;
    }

    @Beta
    public XDDFTextBody getTextBody() {
        return _textBody;
    }

    protected void setXfrm(CTTransform2D t2d) {
        ctShape.getSpPr().setXfrm(t2d);
    }

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

    /**
     * @since POI 5.2.0
     */
    @Override
    public Spliterator<XSSFTextParagraph> spliterator() {
        return _paragraphs.spliterator();
    }

    /**
     * Returns the text from all paragraphs in the shape. Paragraphs are
     * separated by new lines.
     *
     * @return text contained within this shape or empty string
     */
    public String getText() {
        final int MAX_LEVELS = 9;
        StringBuilder out = new StringBuilder();
        List<Integer> levelCount = new ArrayList<>(MAX_LEVELS); // maximum 9
                                                                // levels
        // initialise the levelCount array - this maintains a record of the
        // numbering to be used at each level
        for (int k = 0; k < MAX_LEVELS; k++) {
            levelCount.add(0);
        }

        for (int i = 0; i < _paragraphs.size(); i++) {
            if (out.length() > 0) {
                out.append('\n');
            }
            XSSFTextParagraph p = _paragraphs.get(i);

            if (p.isBullet() && p.getText().length() > 0) {

                int level = Math.min(p.getLevel(), MAX_LEVELS - 1);

                if (p.isBulletAutoNumber()) {
                    i = processAutoNumGroup(i, level, levelCount, out);
                } else {
                    // indent appropriately for the level
                    for (int j = 0; j < level; j++) {
                        out.append('\t');
                    }
                    String character = p.getBulletCharacter();
                    out.append(character.length() > 0 ? character + " " : "- ");
                    out.append(p.getText());
                }
            } else {
                out.append(p.getText());

                // this paragraph is not a bullet, so reset the count array
                for (int k = 0; k < MAX_LEVELS; k++) {
                    levelCount.set(k, 0);
                }
            }
        }

        return out.toString();
    }

    /**
     *
     */
    private int processAutoNumGroup(int index, int level, List<Integer> levelCount, StringBuilder out) {
        XSSFTextParagraph p = _paragraphs.get(index);

        // The rules for generating the auto numbers are as follows. If the
        // following paragraph is also
        // an auto-number, has the same type/scheme (and startAt if defined on
        // this paragraph) then they are
        // considered part of the same group. An empty bullet paragraph is
        // counted as part of the same
        // group but does not increment the count for the group. A change of
        // type, startAt or the paragraph
        // not being a bullet resets the count for that level to 1.

        // first auto-number paragraph so initialise to 1 or the bullets startAt
        // if present
        int startAt = p.getBulletAutoNumberStart();
        ListAutoNumber scheme = p.getBulletAutoNumberScheme();
        if (levelCount.get(level) == 0) {
            levelCount.set(level, startAt == 0 ? 1 : startAt);
        }
        // indent appropriately for the level
        for (int j = 0; j < level; j++) {
            out.append('\t');
        }
        if (p.getText().length() > 0) {
            out.append(getBulletPrefix(scheme, levelCount.get(level)));
            out.append(p.getText());
        }
        while (true) {
            XSSFTextParagraph nextp = (index + 1) == _paragraphs.size() ? null : _paragraphs.get(index + 1);
            if (nextp == null) {
                break; // out of paragraphs
            }
            if (!(nextp.isBullet() && p.isBulletAutoNumber())) {
                break; // not an auto-number bullet
            }
            if (nextp.getLevel() > level) {
                // recurse into the new level group
                if (out.length() > 0) {
                    out.append('\n');
                }
                index = processAutoNumGroup(index + 1, nextp.getLevel(), levelCount, out);
                continue; // restart the loop given the new index
            } else if (nextp.getLevel() < level) {
                break; // changed level
            }
            ListAutoNumber nextScheme = nextp.getBulletAutoNumberScheme();
            int nextStartAt = nextp.getBulletAutoNumberStart();

            if (nextScheme == scheme && nextStartAt == startAt) {
                // bullet is valid, so increment i
                ++index;
                if (out.length() > 0) {
                    out.append('\n');
                }
                // indent for the level
                for (int j = 0; j < level; j++) {
                    out.append('\t');
                }
                // check for empty text - only output a bullet if there is text,
                // but it is still part of the group
                if (nextp.getText().length() > 0) {
                    // increment the count for this level
                    levelCount.set(level, levelCount.get(level) + 1);
                    out.append(getBulletPrefix(nextScheme, levelCount.get(level)));
                    out.append(nextp.getText());
                }
            } else {
                // something doesn't match so stop
                break;
            }
        }
        // end of the group so reset the count for this level
        levelCount.set(level, 0);

        return index;
    }

    /**
     * Returns a string containing an appropriate prefix for an auto-numbering
     * bullet
     *
     * @param scheme
     *            the auto-numbering scheme used by the bullet
     * @param value
     *            the value of the bullet
     * @return appropriate prefix for an auto-numbering bullet
     */
    private String getBulletPrefix(ListAutoNumber scheme, int value) {
        StringBuilder out = new StringBuilder();

        switch (scheme) {
        case ALPHA_LC_PARENT_BOTH:
        case ALPHA_LC_PARENT_R:
            if (scheme == ListAutoNumber.ALPHA_LC_PARENT_BOTH) {
                out.append('(');
            }
            out.append(valueToAlpha(value).toLowerCase(Locale.ROOT));
            out.append(')');
            break;
        case ALPHA_UC_PARENT_BOTH:
        case ALPHA_UC_PARENT_R:
            if (scheme == ListAutoNumber.ALPHA_UC_PARENT_BOTH) {
                out.append('(');
            }
            out.append(valueToAlpha(value));
            out.append(')');
            break;
        case ALPHA_LC_PERIOD:
            out.append(valueToAlpha(value).toLowerCase(Locale.ROOT));
            out.append('.');
            break;
        case ALPHA_UC_PERIOD:
            out.append(valueToAlpha(value));
            out.append('.');
            break;
        case ARABIC_PARENT_BOTH:
        case ARABIC_PARENT_R:
            if (scheme == ListAutoNumber.ARABIC_PARENT_BOTH) {
                out.append('(');
            }
            out.append(value);
            out.append(')');
            break;
        case ARABIC_PERIOD:
            out.append(value);
            out.append('.');
            break;
        case ARABIC_PLAIN:
            out.append(value);
            break;
        case ROMAN_LC_PARENT_BOTH:
        case ROMAN_LC_PARENT_R:
            if (scheme == ListAutoNumber.ROMAN_LC_PARENT_BOTH) {
                out.append('(');
            }
            out.append(valueToRoman(value).toLowerCase(Locale.ROOT));
            out.append(')');
            break;
        case ROMAN_UC_PARENT_BOTH:
        case ROMAN_UC_PARENT_R:
            if (scheme == ListAutoNumber.ROMAN_UC_PARENT_BOTH) {
                out.append('(');
            }
            out.append(valueToRoman(value));
            out.append(')');
            break;
        case ROMAN_LC_PERIOD:
            out.append(valueToRoman(value).toLowerCase(Locale.ROOT));
            out.append('.');
            break;
        case ROMAN_UC_PERIOD:
            out.append(valueToRoman(value));
            out.append('.');
            break;
        default:
            out.append('\u2022'); // can't set the font to wingdings so use the
                                  // default bullet character
            break;
        }
        out.append(" ");
        return out.toString();
    }

    /**
     * Convert an integer to its alpha equivalent e.g. 1 = A, 2 = B, 27 = AA etc
     */
    private String valueToAlpha(int value) {
        StringBuilder alpha = new StringBuilder();
        int modulo;
        while (value > 0) {
            modulo = (value - 1) % 26;
            alpha.append((char) (65 + modulo));
            value = (value - modulo) / 26;
        }
        alpha.reverse();
        return alpha.toString();
    }

    private static String[] _romanChars = new String[] { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V",
            "IV", "I" };
    private static int[] _romanAlphaValues = new int[] { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };

    /**
     * Convert an integer to its roman equivalent e.g. 1 = I, 9 = IX etc
     */
    private String valueToRoman(int value) {
        StringBuilder out = new StringBuilder();
        for (int i = 0; value > 0 && i < _romanChars.length; i++) {
            while (_romanAlphaValues[i] <= value) {
                out.append(_romanChars[i]);
                value -= _romanAlphaValues[i];
            }
        }
        return out.toString();
    }

    /**
     * Clear all text from this shape
     */
    public void clearText() {
        _paragraphs.clear();
        CTTextBody txBody = ctShape.getTxBody();
        txBody.setPArray(null); // remove any existing paragraphs
    }

    /**
     * Set a single paragraph of text on the shape. Note this will replace all
     * existing paragraphs created on the shape.
     *
     * @param text
     *            string representing the paragraph text
     */
    public void setText(String text) {
        clearText();

        addNewTextParagraph().addNewTextRun().setText(text);
    }

    /**
     * Set a single paragraph of text on the shape. Note this will replace all
     * existing paragraphs created on the shape.
     *
     * @param str
     *            rich text string representing the paragraph text
     */
    public void setText(XSSFRichTextString str) {

        XSSFWorkbook wb = (XSSFWorkbook) getDrawing().getParent().getParent();
        str.setStylesTableReference(wb.getStylesSource());

        CTTextParagraph p = CTTextParagraph.Factory.newInstance();
        if (str.numFormattingRuns() == 0) {
            CTRegularTextRun r = p.addNewR();
            CTTextCharacterProperties rPr = r.addNewRPr();
            rPr.setLang("en-US");
            rPr.setSz(1100);
            r.setT(str.getString());

        } else {
            for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) {
                CTRElt lt = str.getCTRst().getRArray(i);
                CTRPrElt ltPr = lt.getRPr();
                if (ltPr == null) {
                    ltPr = lt.addNewRPr();
                }

                CTRegularTextRun r = p.addNewR();
                CTTextCharacterProperties rPr = r.addNewRPr();
                rPr.setLang("en-US");

                applyAttributes(ltPr, rPr);

                r.setT(lt.getT());
            }
        }

        clearText();
        ctShape.getTxBody().setPArray(new CTTextParagraph[] { p });
        _paragraphs.add(new XSSFTextParagraph(ctShape.getTxBody().getPArray(0), ctShape));
    }

    /**
     * Returns a collection of the XSSFTextParagraphs that are attached to this
     * shape
     *
     * @return text paragraphs in this shape
     */
    public List<XSSFTextParagraph> getTextParagraphs() {
        return _paragraphs;
    }

    /**
     * Add a new paragraph run to this shape
     *
     * @return created paragraph run
     */
    public XSSFTextParagraph addNewTextParagraph() {
        CTTextBody txBody = ctShape.getTxBody();
        CTTextParagraph p = txBody.addNewP();
        XSSFTextParagraph paragraph = new XSSFTextParagraph(p, ctShape);
        _paragraphs.add(paragraph);
        return paragraph;
    }

    /**
     * Add a new paragraph run to this shape, set to the provided string
     *
     * @return created paragraph run
     */
    public XSSFTextParagraph addNewTextParagraph(String text) {
        XSSFTextParagraph paragraph = addNewTextParagraph();
        paragraph.addNewTextRun().setText(text);
        return paragraph;
    }

    /**
     * Add a new paragraph run to this shape, set to the provided rich text
     * string
     *
     * @return created paragraph run
     */
    public XSSFTextParagraph addNewTextParagraph(XSSFRichTextString str) {
        CTTextBody txBody = ctShape.getTxBody();
        CTTextParagraph p = txBody.addNewP();

        if (str.numFormattingRuns() == 0) {
            CTRegularTextRun r = p.addNewR();
            CTTextCharacterProperties rPr = r.addNewRPr();
            rPr.setLang("en-US");
            rPr.setSz(1100);
            r.setT(str.getString());

        } else {
            for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) {
                CTRElt lt = str.getCTRst().getRArray(i);
                CTRPrElt ltPr = lt.getRPr();
                if (ltPr == null) {
                    ltPr = lt.addNewRPr();
                }

                CTRegularTextRun r = p.addNewR();
                CTTextCharacterProperties rPr = r.addNewRPr();
                rPr.setLang("en-US");

                applyAttributes(ltPr, rPr);

                r.setT(lt.getT());
            }
        }

        // Note: the XSSFTextParagraph constructor will create its required
        // XSSFTextRuns from the provided CTTextParagraph
        XSSFTextParagraph paragraph = new XSSFTextParagraph(p, ctShape);
        _paragraphs.add(paragraph);

        return paragraph;
    }

    /**
     * Sets the type of horizontal overflow for the text.
     *
     * @param overflow
     *            - the type of horizontal overflow. A <code>null</code> values
     *            unsets this property.
     */
    public void setTextHorizontalOverflow(TextHorizontalOverflow overflow) {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (overflow == null) {
                if (bodyPr.isSetHorzOverflow()) {
                    bodyPr.unsetHorzOverflow();
                }
            } else {
                bodyPr.setHorzOverflow(STTextHorzOverflowType.Enum.forInt(overflow.ordinal() + 1));
            }
        }
    }

    /**
     * Returns the type of horizontal overflow for the text.
     *
     * @return the type of horizontal overflow
     */
    public TextHorizontalOverflow getTextHorizontalOverflow() {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (bodyPr.isSetHorzOverflow()) {
                return TextHorizontalOverflow.values()[bodyPr.getHorzOverflow().intValue() - 1];
            }
        }
        return TextHorizontalOverflow.OVERFLOW;
    }

    /**
     * Sets the type of vertical overflow for the text.
     *
     * @param overflow
     *            - the type of vertical overflow. A <code>null</code> values
     *            unsets this property.
     */
    public void setTextVerticalOverflow(TextVerticalOverflow overflow) {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (overflow == null) {
                if (bodyPr.isSetVertOverflow()) {
                    bodyPr.unsetVertOverflow();
                }
            } else {
                bodyPr.setVertOverflow(STTextVertOverflowType.Enum.forInt(overflow.ordinal() + 1));
            }
        }
    }

    /**
     * Returns the type of vertical overflow for the text.
     *
     * @return the type of vertical overflow
     */
    public TextVerticalOverflow getTextVerticalOverflow() {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (bodyPr.isSetVertOverflow()) {
                return TextVerticalOverflow.values()[bodyPr.getVertOverflow().intValue() - 1];
            }
        }
        return TextVerticalOverflow.OVERFLOW;
    }

    /**
     * Sets the type of vertical alignment for the text within the shape.
     *
     * @param anchor
     *            - the type of alignment. A <code>null</code> values unsets
     *            this property.
     */
    public void setVerticalAlignment(VerticalAlignment anchor) {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (anchor == null) {
                if (bodyPr.isSetAnchor()) {
                    bodyPr.unsetAnchor();
                }
            } else {
                bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
            }
        }
    }

    /**
     * Returns the type of vertical alignment for the text within the shape.
     *
     * @return the type of vertical alignment
     */
    public VerticalAlignment getVerticalAlignment() {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (bodyPr.isSetAnchor()) {
                return VerticalAlignment.values()[bodyPr.getAnchor().intValue() - 1];
            }
        }
        return VerticalAlignment.TOP;
    }

    /**
     * Sets the vertical orientation of the text
     *
     * @param orientation
     *            vertical orientation of the text A <code>null</code> values
     *            unsets this property.
     */
    public void setTextDirection(TextDirection orientation) {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (orientation == null) {
                if (bodyPr.isSetVert()) {
                    bodyPr.unsetVert();
                }
            } else {
                bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1));
            }
        }
    }

    /**
     * Gets the vertical orientation of the text
     *
     * @return vertical orientation of the text
     */
    public TextDirection getTextDirection() {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            STTextVerticalType.Enum val = bodyPr.getVert();
            if (val != null) {
                return TextDirection.values()[val.intValue() - 1];
            }
        }
        return TextDirection.HORIZONTAL;
    }

    /**
     * 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.
     *
     * @return the bottom inset in points
     */
    public double getBottomInset() {
        Double inset = _textBody.getBodyProperties().getBottomInset();
        if (inset == null) {
            // If this attribute is omitted, then a value of 0.05 inches is
            // implied
            return 3.6;
        } else {
            return inset;
        }
    }

    /**
     * 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.
     *
     * @return the left inset in points
     */
    public double getLeftInset() {
        Double inset = _textBody.getBodyProperties().getLeftInset();
        if (inset == null) {
            // If this attribute is omitted, then a value of 0.05 inches is
            // implied
            return 3.6;
        } else {
            return inset;
        }
    }

    /**
     * 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.
     *
     * @return the right inset in points
     */
    public double getRightInset() {
        Double inset = _textBody.getBodyProperties().getRightInset();
        if (inset == null) {
            // If this attribute is omitted, then a value of 0.05 inches is
            // implied
            return 3.6;
        } else {
            return inset;
        }
    }

    /**
     * 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.
     *
     * @return the top inset in points
     */
    public double getTopInset() {
        Double inset = _textBody.getBodyProperties().getTopInset();
        if (inset == null) {
            // If this attribute is omitted, then a value of 0.05 inches is
            // implied
            return 3.6;
        } else {
            return inset;
        }
    }

    /**
     * Sets the bottom inset.
     *
     * @see #getBottomInset()
     *
     * @param margin
     *            the bottom margin
     */
    public void setBottomInset(double margin) {
        if (margin == -1) {
            _textBody.getBodyProperties().setBottomInset(null);
        } else {
            _textBody.getBodyProperties().setBottomInset(margin);
        }
    }

    /**
     * Sets the left inset.
     *
     * @see #getLeftInset()
     *
     * @param margin
     *            the left margin
     */
    public void setLeftInset(double margin) {
        if (margin == -1) {
            _textBody.getBodyProperties().setLeftInset(null);
        } else {
            _textBody.getBodyProperties().setLeftInset(margin);
        }
    }

    /**
     * Sets the right inset.
     *
     * @see #getRightInset()
     *
     * @param margin
     *            the right margin
     */
    public void setRightInset(double margin) {
        if (margin == -1) {
            _textBody.getBodyProperties().setRightInset(null);
        } else {
            _textBody.getBodyProperties().setRightInset(margin);
        }
    }

    /**
     * Sets the top inset.
     *
     * @see #getTopInset()
     *
     * @param margin
     *            the top margin
     */
    public void setTopInset(double margin) {
        if (margin == -1) {
            _textBody.getBodyProperties().setTopInset(null);
        } else {
            _textBody.getBodyProperties().setTopInset(margin);
        }
    }

    /**
     * @return whether to wrap words within the bounding rectangle
     */
    public boolean getWordWrap() {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (bodyPr.isSetWrap()) {
                return bodyPr.getWrap() == STTextWrappingType.SQUARE;
            }
        }
        return true;
    }

    /**
     *
     * @param wrap
     *            whether to wrap words within the bounding rectangle
     */
    public void setWordWrap(boolean wrap) {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE);
        }
    }

    /**
     *
     * Specifies that a shape should be auto-fit to fully contain the text
     * described within it. Auto-fitting is when text within a shape is scaled
     * in order to contain all the text inside
     *
     * @param value
     *            type of autofit
     */
    public void setTextAutofit(TextAutofit value) {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (bodyPr.isSetSpAutoFit()) {
                bodyPr.unsetSpAutoFit();
            }
            if (bodyPr.isSetNoAutofit()) {
                bodyPr.unsetNoAutofit();
            }
            if (bodyPr.isSetNormAutofit()) {
                bodyPr.unsetNormAutofit();
            }

            switch (value) {
            case NONE:
                bodyPr.addNewNoAutofit();
                break;
            case NORMAL:
                bodyPr.addNewNormAutofit();
                break;
            case SHAPE:
                bodyPr.addNewSpAutoFit();
                break;
            }
        }
    }

    /**
     *
     * @return type of autofit
     */
    public TextAutofit getTextAutofit() {
        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
        if (bodyPr != null) {
            if (bodyPr.isSetNoAutofit()) {
                return TextAutofit.NONE;
            } else if (bodyPr.isSetNormAutofit()) {
                return TextAutofit.NORMAL;
            } else if (bodyPr.isSetSpAutoFit()) {
                return TextAutofit.SHAPE;
            }
        }
        return TextAutofit.NORMAL;
    }

    /**
     * Gets the shape type, one of the constants defined in
     * {@link org.apache.poi.ss.usermodel.ShapeTypes}.
     *
     * @return the shape type
     * @see org.apache.poi.ss.usermodel.ShapeTypes
     */
    public int getShapeType() {
        return ctShape.getSpPr().getPrstGeom().getPrst().intValue();
    }

    /**
     * Sets the shape types.
     *
     * @param type
     *            the shape type, one of the constants defined in
     *            {@link org.apache.poi.ss.usermodel.ShapeTypes}.
     * @see org.apache.poi.ss.usermodel.ShapeTypes
     */
    public void setShapeType(int type) {
        ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type));
    }

    @Override
    protected CTShapeProperties getShapeProperties() {
        return ctShape.getSpPr();
    }

    /**
     * org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRPrElt to
     * org.openxmlformats.schemas.drawingml.x2006.main.CTFont adapter
     */
    private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr) {

        if (pr.sizeOfBArray() > 0) {
            rPr.setB(pr.getBArray(0).getVal());
        }
        if (pr.sizeOfUArray() > 0) {
            STUnderlineValues.Enum u1 = pr.getUArray(0).getVal();
            if (u1 == STUnderlineValues.SINGLE) {
                rPr.setU(STTextUnderlineType.SNG);
            } else if (u1 == STUnderlineValues.DOUBLE) {
                rPr.setU(STTextUnderlineType.DBL);
            } else if (u1 == STUnderlineValues.NONE) {
                rPr.setU(STTextUnderlineType.NONE);
            }
        }
        if (pr.sizeOfIArray() > 0) {
            rPr.setI(pr.getIArray(0).getVal());
        }

        if (pr.sizeOfRFontArray() > 0) {
            CTTextFont rFont = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin();
            rFont.setTypeface(pr.getRFontArray(0).getVal());
        }

        if (pr.sizeOfSzArray() > 0) {
            int sz = (int) (pr.getSzArray(0).getVal() * 100);
            rPr.setSz(sz);
        }

        if (pr.sizeOfColorArray() > 0) {
            CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();
            org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor xlsColor = pr.getColorArray(0);
            if (xlsColor.isSetRgb()) {
                CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();
                clr.setVal(xlsColor.getRgb());
            } else if (xlsColor.isSetIndexed()) {
                HSSFColor indexed = HSSFColor.getIndexHash().get((int) xlsColor.getIndexed());
                if (indexed != null) {
                    byte[] rgb = new byte[3];
                    rgb[0] = (byte) indexed.getTriplet()[0];
                    rgb[1] = (byte) indexed.getTriplet()[1];
                    rgb[2] = (byte) indexed.getTriplet()[2];
                    CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();
                    clr.setVal(rgb);
                }
            }
        }
    }

    @Override
    public String getShapeName() {
        return ctShape.getNvSpPr().getCNvPr().getName();
    }

    @Override
    public int getShapeId() {
        return (int) ctShape.getNvSpPr().getCNvPr().getId();
    }

    @Override
    public <R> Optional<R> findDefinedParagraphProperty(Predicate<CTTextParagraphProperties> isSet,
        Function<CTTextParagraphProperties, R> getter) {
        // TODO Auto-generated method stub
        return Optional.empty();
    }

    @Override
    public <R> Optional<R> findDefinedRunProperty(Predicate<CTTextCharacterProperties> isSet,
        Function<CTTextCharacterProperties, R> getter) {
        // TODO Auto-generated method stub
        return Optional.empty();
    }
}
