/*
 *  ====================================================================
 *    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.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.ooxml.util.POIXMLUnits;
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.TextShape;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.text.TextContainer;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.poi.xslf.model.TextBodyPropertyFetcher;
import org.apache.xmlbeans.XmlObject;
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.CTTextListStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;

/**
 * Represents a shape that can hold text.
 */
@Beta
public abstract class XSLFTextShape extends XSLFSimpleShape
    implements TextContainer, TextShape<XSLFShape, XSLFTextParagraph> {
    private final List<XSLFTextParagraph> _paragraphs;

    /* package */ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
        super(shape, sheet);

        _paragraphs = new ArrayList<>();
        CTTextBody txBody = getTextBody(false);
        if (txBody != null) {
            for (CTTextParagraph p : txBody.getPArray()) {
                _paragraphs.add(newTextParagraph(p));
            }
        }
    }

    @Beta
    public XDDFTextBody getTextBody() {
        CTTextBody txBody = getTextBody(false);
        if (txBody == null) {
            return null;
        }
        return new XDDFTextBody(this, txBody);
    }

    @Override
    public Iterator<XSLFTextParagraph> iterator() {
        return getTextParagraphs().iterator();
    }

    @Override
    public String getText() {
        StringBuilder out = new StringBuilder();
        for (XSLFTextParagraph p : _paragraphs) {
            if (out.length() > 0) {
                out.append('\n');
            }
            out.append(p.getText());
        }
        return out.toString();
    }

    /**
     * unset text from this shape
     */
    public void clearText() {
        _paragraphs.clear();
        CTTextBody txBody = getTextBody(true);
        txBody.setPArray(null); // remove any existing paragraphs
    }

    @Override
    public XSLFTextRun setText(String text) {
        // calling clearText or setting to a new Array leads to a
        // XmlValueDisconnectedException
        if (!_paragraphs.isEmpty()) {
            CTTextBody txBody = getTextBody(false);
            int cntPs = txBody.sizeOfPArray();
            for (int i = cntPs; i > 1; i--) {
                txBody.removeP(i - 1);
                _paragraphs.remove(i - 1);
            }

            _paragraphs.get(0).clearButKeepProperties();
        }

        return appendText(text, false);
    }

    @Override
    public XSLFTextRun appendText(String text, boolean newParagraph) {
        if (text == null) {
            return null;
        }

        // copy properties from last paragraph / textrun or paragraph end marker
        CTTextParagraphProperties otherPPr = null;
        CTTextCharacterProperties otherRPr = null;

        boolean firstPara;
        XSLFTextParagraph para;
        if (_paragraphs.isEmpty()) {
            firstPara = false;
            para = null;
        } else {
            firstPara = !newParagraph;
            para = _paragraphs.get(_paragraphs.size() - 1);
            CTTextParagraph ctp = para.getXmlObject();
            otherPPr = ctp.getPPr();
            List<XSLFTextRun> runs = para.getTextRuns();
            if (!runs.isEmpty()) {
                XSLFTextRun r0 = runs.get(runs.size() - 1);
                otherRPr = r0.getRPr(false);
                if (otherRPr == null) {
                    otherRPr = ctp.getEndParaRPr();
                }
            }
            // don't copy endParaRPr to the run in case there aren't any other
            // runs
            // this is the case when setText() was called initially
            // otherwise the master style will be overridden/ignored
        }

        XSLFTextRun run = null;
        for (String lineTxt : text.split("\\r\\n?|\\n")) {
            if (!firstPara) {
                if (para != null) {
                    CTTextParagraph ctp = para.getXmlObject();
                    CTTextCharacterProperties unexpectedRPr = ctp.getEndParaRPr();
                    if (unexpectedRPr != null && unexpectedRPr != otherRPr) {
                        ctp.unsetEndParaRPr();
                    }
                }
                para = addNewTextParagraph();
                if (otherPPr != null) {
                    para.getXmlObject().setPPr(otherPPr);
                }
            }
            boolean firstRun = true;
            for (String runText : lineTxt.split("[\u000b]")) {
                if (!firstRun) {
                    para.addLineBreak();
                }
                run = para.addNewTextRun();
                run.setText(runText);
                if (otherRPr != null) {
                    run.getRPr(true).set(otherRPr);
                }
                firstRun = false;
            }
            firstPara = false;
        }

        assert (run != null);
        return run;
    }

    @Override
    public List<XSLFTextParagraph> getTextParagraphs() {
        return _paragraphs;
    }

    /**
     * add a new paragraph run to this shape
     *
     * @return created paragraph run
     */
    public XSLFTextParagraph addNewTextParagraph() {
        CTTextBody txBody = getTextBody(false);
        CTTextParagraph p;
        if (txBody == null) {
            txBody = getTextBody(true);
            new XDDFTextBody(this, txBody).initialize();
            p = txBody.getPArray(0);
            p.removeR(0);
        } else {
            p = txBody.addNewP();
        }
        XSLFTextParagraph paragraph = newTextParagraph(p);
        _paragraphs.add(paragraph);
        return paragraph;
    }

    @Override
    public void setVerticalAlignment(VerticalAlignment anchor) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            if (anchor == null) {
                if (bodyPr.isSetAnchor()) {
                    bodyPr.unsetAnchor();
                }
            } else {
                bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
            }
        }
    }

    @Override
    public VerticalAlignment getVerticalAlignment() {
        PropertyFetcher<VerticalAlignment> fetcher = new TextBodyPropertyFetcher<VerticalAlignment>() {
            @Override
            public boolean fetch(CTTextBodyProperties props) {
                if (props.isSetAnchor()) {
                    int val = props.getAnchor().intValue();
                    setValue(VerticalAlignment.values()[val - 1]);
                    return true;
                }
                return false;
            }
        };
        fetchShapeProperty(fetcher);
        return fetcher.getValue() == null ? VerticalAlignment.TOP : fetcher.getValue();
    }

    @Override
    public void setHorizontalCentered(Boolean isCentered) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            if (isCentered == null) {
                if (bodyPr.isSetAnchorCtr()) {
                    bodyPr.unsetAnchorCtr();
                }
            } else {
                bodyPr.setAnchorCtr(isCentered);
            }
        }
    }

    @Override
    public boolean isHorizontalCentered() {
        PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>() {
            @Override
            public boolean fetch(CTTextBodyProperties props) {
                if (props.isSetAnchorCtr()) {
                    setValue(props.getAnchorCtr());
                    return true;
                }
                return false;
            }
        };
        fetchShapeProperty(fetcher);
        return fetcher.getValue() != null && fetcher.getValue();
    }

    @Override
    public void setTextDirection(TextDirection orientation) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            if (orientation == null) {
                if (bodyPr.isSetVert()) {
                    bodyPr.unsetVert();
                }
            } else {
                bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1));
            }
        }
    }

    @Override
    public TextDirection getTextDirection() {
        CTTextBodyProperties bodyPr = getTextBodyPr();
        if (bodyPr != null) {
            STTextVerticalType.Enum val = bodyPr.getVert();
            if (val != null) {
                switch (val.intValue()) {
                default:
                case STTextVerticalType.INT_HORZ:
                    return TextDirection.HORIZONTAL;
                case STTextVerticalType.INT_EA_VERT:
                case STTextVerticalType.INT_MONGOLIAN_VERT:
                case STTextVerticalType.INT_VERT:
                    return TextDirection.VERTICAL;
                case STTextVerticalType.INT_VERT_270:
                    return TextDirection.VERTICAL_270;
                case STTextVerticalType.INT_WORD_ART_VERT_RTL:
                case STTextVerticalType.INT_WORD_ART_VERT:
                    return TextDirection.STACKED;
                }
            }
        }
        return TextDirection.HORIZONTAL;
    }

    @Override
    public Double getTextRotation() {
        CTTextBodyProperties bodyPr = getTextBodyPr();
        if (bodyPr != null && bodyPr.isSetRot()) {
            return bodyPr.getRot() / 60000.;
        }
        return null;
    }

    @Override
    public void setTextRotation(Double rotation) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            bodyPr.setRot((int) (rotation * 60000.));
        }
    }

    /**
     * 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() {
        PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
            @Override
            public boolean fetch(CTTextBodyProperties props) {
                if (props.isSetBIns()) {
                    double val = Units.toPoints(POIXMLUnits.parseLength(props.xgetBIns()));
                    setValue(val);
                    return true;
                }
                return false;
            }
        };
        fetchShapeProperty(fetcher);
        // If this attribute is omitted, then a value of 0.05 inches is implied
        return fetcher.getValue() == null ? 3.6 : fetcher.getValue();
    }

    /**
     * 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() {
        PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
            @Override
            public boolean fetch(CTTextBodyProperties props) {
                if (props.isSetLIns()) {
                    double val = Units.toPoints(POIXMLUnits.parseLength(props.xgetLIns()));
                    setValue(val);
                    return true;
                }
                return false;
            }
        };
        fetchShapeProperty(fetcher);
        // If this attribute is omitted, then a value of 0.1 inches is implied
        return fetcher.getValue() == null ? 7.2 : fetcher.getValue();
    }

    /**
     * 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() {
        PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
            @Override
            public boolean fetch(CTTextBodyProperties props) {
                if (props.isSetRIns()) {
                    double val = Units.toPoints(POIXMLUnits.parseLength(props.xgetRIns()));
                    setValue(val);
                    return true;
                }
                return false;
            }
        };
        fetchShapeProperty(fetcher);
        // If this attribute is omitted, then a value of 0.1 inches is implied
        return fetcher.getValue() == null ? 7.2 : fetcher.getValue();
    }

    /**
     * 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() {
        PropertyFetcher<Double> fetcher = new TextBodyPropertyFetcher<Double>() {
            @Override
            public boolean fetch(CTTextBodyProperties props) {
                if (props.isSetTIns()) {
                    double val = Units.toPoints(POIXMLUnits.parseLength(props.xgetTIns()));
                    setValue(val);
                    return true;
                }
                return false;
            }
        };
        fetchShapeProperty(fetcher);
        // If this attribute is omitted, then a value of 0.05 inches is implied
        return fetcher.getValue() == null ? 3.6 : fetcher.getValue();
    }

    /**
     * Sets the bottom margin.
     *
     * @see #getBottomInset()
     *
     * @param margin
     *            the bottom margin
     */
    public void setBottomInset(double margin) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            if (margin == -1) {
                bodyPr.unsetBIns();
            } else {
                bodyPr.setBIns(Units.toEMU(margin));
            }
        }
    }

    /**
     * Sets the left margin.
     *
     * @see #getLeftInset()
     *
     * @param margin
     *            the left margin
     */
    public void setLeftInset(double margin) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            if (margin == -1) {
                bodyPr.unsetLIns();
            } else {
                bodyPr.setLIns(Units.toEMU(margin));
            }
        }
    }

    /**
     * Sets the right margin.
     *
     * @see #getRightInset()
     *
     * @param margin
     *            the right margin
     */
    public void setRightInset(double margin) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            if (margin == -1) {
                bodyPr.unsetRIns();
            } else {
                bodyPr.setRIns(Units.toEMU(margin));
            }
        }
    }

    /**
     * Sets the top margin.
     *
     * @see #getTopInset()
     *
     * @param margin
     *            the top margin
     */
    public void setTopInset(double margin) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        if (bodyPr != null) {
            if (margin == -1) {
                bodyPr.unsetTIns();
            } else {
                bodyPr.setTIns(Units.toEMU(margin));
            }
        }
    }

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

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

    @Override
    public boolean getWordWrap() {
        PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>() {
            @Override
            public boolean fetch(CTTextBodyProperties props) {
                if (props.isSetWrap()) {
                    setValue(props.getWrap() == STTextWrappingType.SQUARE);
                    return true;
                }
                return false;
            }
        };
        fetchShapeProperty(fetcher);
        return fetcher.getValue() == null || fetcher.getValue();
    }

    @Override
    public void setWordWrap(boolean wrap) {
        CTTextBodyProperties bodyPr = getTextBodyPr(true);
        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 = getTextBodyPr(true);
        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 = getTextBodyPr();
        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;
    }

    protected CTTextBodyProperties getTextBodyPr() {
        return getTextBodyPr(false);
    }

    protected CTTextBodyProperties getTextBodyPr(boolean create) {
        CTTextBody textBody = getTextBody(create);
        if (textBody == null) {
            return null;
        }
        CTTextBodyProperties textBodyPr = textBody.getBodyPr();
        if (textBodyPr == null && create) {
            textBodyPr = textBody.addNewBodyPr();
        }
        return textBodyPr;
    }

    protected abstract CTTextBody getTextBody(boolean create);

    @Override
    public void setPlaceholder(Placeholder placeholder) {
        super.setPlaceholder(placeholder);
    }

    public Placeholder getTextType() {
        return getPlaceholder();
    }

    @Override
    public double getTextHeight() {
        return getTextHeight(null);
    }

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

    @Override
    public Rectangle2D resizeToFitText() {
        return resizeToFitText(null);
    }

    @Override
    public Rectangle2D resizeToFitText(Graphics2D graphics) {
        Rectangle2D anchor = getAnchor();

        if (anchor.getWidth() == 0.) {
            throw new POIXMLException("Anchor of the shape was not set.");
        }
        double height = getTextHeight(graphics);
        height += 1; // add a pixel to compensate rounding errors

        Insets2D insets = getInsets();
        anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height + insets.top + insets.bottom);
        setAnchor(anchor);

        return anchor;
    }

    @Override
    void copy(XSLFShape other) {
        super.copy(other);

        XSLFTextShape otherTS = (XSLFTextShape) other;
        CTTextBody otherTB = otherTS.getTextBody(false);
        if (otherTB == null) {
            return;
        }

        CTTextBody thisTB = getTextBody(true);
        thisTB.setBodyPr((CTTextBodyProperties) otherTB.getBodyPr().copy());

        if (thisTB.isSetLstStyle()) {
            thisTB.unsetLstStyle();
        }
        if (otherTB.isSetLstStyle()) {
            thisTB.setLstStyle((CTTextListStyle) otherTB.getLstStyle().copy());
        }

        boolean srcWordWrap = otherTS.getWordWrap();
        if (srcWordWrap != getWordWrap()) {
            setWordWrap(srcWordWrap);
        }

        double leftInset = otherTS.getLeftInset();
        if (leftInset != getLeftInset()) {
            setLeftInset(leftInset);
        }
        double rightInset = otherTS.getRightInset();
        if (rightInset != getRightInset()) {
            setRightInset(rightInset);
        }
        double topInset = otherTS.getTopInset();
        if (topInset != getTopInset()) {
            setTopInset(topInset);
        }
        double bottomInset = otherTS.getBottomInset();
        if (bottomInset != getBottomInset()) {
            setBottomInset(bottomInset);
        }

        VerticalAlignment vAlign = otherTS.getVerticalAlignment();
        if (vAlign != getVerticalAlignment()) {
            setVerticalAlignment(vAlign);
        }

        clearText();

        for (XSLFTextParagraph srcP : otherTS.getTextParagraphs()) {
            XSLFTextParagraph tgtP = addNewTextParagraph();
            tgtP.copy(srcP);
        }
    }

    @Override
    public void setTextPlaceholder(TextPlaceholder placeholder) {
        switch (placeholder) {
        default:
        case NOTES:
        case HALF_BODY:
        case QUARTER_BODY:
        case BODY:
            setPlaceholder(Placeholder.BODY);
            break;
        case TITLE:
            setPlaceholder(Placeholder.TITLE);
            break;
        case CENTER_BODY:
            setPlaceholder(Placeholder.BODY);
            setHorizontalCentered(true);
            break;
        case CENTER_TITLE:
            setPlaceholder(Placeholder.CENTERED_TITLE);
            break;
        case OTHER:
            setPlaceholder(Placeholder.CONTENT);
            break;
        }
    }

    @Override
    public TextPlaceholder getTextPlaceholder() {
        Placeholder ph = getTextType();
        if (ph == null) {
            return TextPlaceholder.BODY;
        }
        switch (ph) {
        case BODY:
            return TextPlaceholder.BODY;
        case TITLE:
            return TextPlaceholder.TITLE;
        case CENTERED_TITLE:
            return TextPlaceholder.CENTER_TITLE;
        default:
        case CONTENT:
            return TextPlaceholder.OTHER;
        }
    }

    /**
     * Helper method to allow subclasses to provide their own text paragraph
     *
     * @param p
     *            the xml reference
     *
     * @return a new text paragraph
     *
     * @since POI 3.15-beta2
     */
    protected XSLFTextParagraph newTextParagraph(CTTextParagraph p) {
        return new XSLFTextParagraph(p, this);
    }

    @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();
    }

}
