/* ====================================================================
   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 static org.apache.poi.sl.TestCommonSL.sameColor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;

import org.apache.poi.sl.draw.DrawTextFragment;
import org.apache.poi.sl.draw.DrawTextParagraph;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.junit.Assume;
import org.junit.Test;

/**
 * @author Yegor Kozlov
 */
public class TestXSLFTextParagraph {
    // private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class);

    static class DrawTextParagraphProxy extends DrawTextParagraph {
        DrawTextParagraphProxy(XSLFTextParagraph p) {
            super(p);
        }
        
        public void breakText(Graphics2D graphics) {
            super.breakText(graphics);
        }
        
        public double getWrappingWidth(boolean firstLine, Graphics2D graphics) {
            return super.getWrappingWidth(firstLine, graphics);
        }
        
        public List<DrawTextFragment> getLines() {
            return lines;
        }
    }
    
    @Test
    public void testWrappingWidth() throws IOException {
        XMLSlideShow ppt = new XMLSlideShow();
        XSLFSlide slide = ppt.createSlide();
        XSLFTextShape sh = slide.createAutoShape();
        sh.setLineColor(Color.black);

        XSLFTextParagraph p = sh.addNewTextParagraph();
        p.addNewTextRun().setText(
                "Paragraph formatting allows for more granular control " +
                "of text within a shape. Properties here apply to all text " +
                "residing within the corresponding paragraph.");

        Rectangle2D anchor = new Rectangle2D.Double(50, 50, 300, 200);
        sh.setAnchor(anchor);
        
        DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p);

        Double leftInset = sh.getLeftInset();
        Double rightInset = sh.getRightInset();
        assertEquals(7.2, leftInset, 0);
        assertEquals(7.2, rightInset, 0);

        Double leftMargin = p.getLeftMargin();
        assertEquals(0.0, leftMargin, 0);

        Double indent = p.getIndent();
        assertNull(indent); // default

        double expectedWidth;

        // Case 1: bullet=false, leftMargin=0, indent=0.
        expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
        assertEquals(285.6, expectedWidth, 0); // 300 - 7.2 - 7.2 - 0
        assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0);
        assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);

        p.setLeftMargin(36d); // 0.5"
        leftMargin = p.getLeftMargin();
        assertEquals(36.0, leftMargin, 0);
        expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
        assertEquals(249.6, expectedWidth, 1E-5); // 300 - 7.2 - 7.2 - 36
        assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0);
        assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);

        // increase insets, the wrapping width should get smaller
        sh.setLeftInset(10);
        sh.setRightInset(10);
        leftInset = sh.getLeftInset();
        rightInset = sh.getRightInset();
        assertEquals(10.0, leftInset, 0);
        assertEquals(10.0, rightInset, 0);
        expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
        assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36
        assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0);
        assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);

        // set a positive indent of a 0.5 inch. This means "First Line" indentation:
        // |<---  indent -->|Here goes first line of the text
        // Here go other lines (second and subsequent)

        p.setIndent(36.0);  // 0.5"
        indent = p.getIndent();
        assertEquals(36.0, indent, 0);
        expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin - indent;
        assertEquals(208.0, expectedWidth, 0); // 300 - 10 - 10 - 36 - 6.4
        assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is indented
        // other lines are not indented
        expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
        assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36
        assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);

        // set a negative indent of a 1 inch. This means "Hanging" indentation:
        // Here goes first line of the text
        // |<---  indent -->|Here go other lines (second and subsequent)
        p.setIndent(-72.0);  // 1"
        indent = p.getIndent();
        assertEquals(-72.0, indent, 0);
        expectedWidth = anchor.getWidth() - leftInset - rightInset;
        assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10 
        assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is NOT indented
        // other lines are indented by leftMargin (the value of indent is not used)
        expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;
        assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 
        assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);
        
        ppt.close();
     }

    /**
     * test breaking test into lines.
     * This test requires that the Arial font is available and will run only on windows
     */
    @Test
    public void testBreakLines() throws IOException {
        String os = System.getProperty("os.name");
        Assume.assumeTrue("Skipping testBreakLines(), it is executed only on Windows machines", (os != null && os.contains("Windows")));

        XMLSlideShow ppt = new XMLSlideShow();
        XSLFSlide slide = ppt.createSlide();
        XSLFTextShape sh = slide.createAutoShape();

        XSLFTextParagraph p = sh.addNewTextParagraph();
        XSLFTextRun r = p.addNewTextRun();
        r.setFontFamily("Arial"); // this should always be available
        r.setFontSize(12d);
        r.setText(
                "Paragraph formatting allows for more granular control " +
                "of text within a shape. Properties here apply to all text " +
                "residing within the corresponding paragraph.");

        sh.setAnchor(new Rectangle2D.Double(50, 50, 300, 200));
        DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p);

        BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = img.createGraphics();

        List<DrawTextFragment> lines;
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(4, lines.size());

        // decrease the shape width from 300 pt to 100 pt
        sh.setAnchor(new Rectangle2D.Double(50, 50, 100, 200));
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(12, lines.size());

        // decrease the shape width from 300 pt to 100 pt
        sh.setAnchor(new Rectangle2D.Double(50, 50, 600, 200));
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(2, lines.size());

        // set left and right margins to 200pt. This leaves 200pt for wrapping text
        sh.setLeftInset(200);
        sh.setRightInset(200);
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(5, lines.size());

        r.setText("Apache POI");
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(1, lines.size());
        assertEquals("Apache POI", lines.get(0).getString());

        r.setText("Apache\nPOI");
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(2, lines.size());
        assertEquals("Apache", lines.get(0).getString());
        assertEquals("POI", lines.get(1).getString());

        // trailing newlines are ignored
        r.setText("Apache\nPOI\n");
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(2, lines.size());
        assertEquals("Apache", lines.get(0).getString());
        assertEquals("POI", lines.get(1).getString());

        XSLFAutoShape sh2 = slide.createAutoShape();
        sh2.setAnchor(new Rectangle2D.Double(50, 50, 300, 200));
        XSLFTextParagraph p2 = sh2.addNewTextParagraph();
        XSLFTextRun r2 = p2.addNewTextRun();
        r2.setFontFamily("serif"); // this should always be available
        r2.setFontSize(30d);
        r2.setText("Apache\n");
        XSLFTextRun r3 = p2.addNewTextRun();
        r3.setFontFamily("serif"); // this should always be available
        r3.setFontSize(10d);
        r3.setText("POI");
        dtp = new DrawTextParagraphProxy(p2);
        dtp.breakText(graphics);
        lines = dtp.getLines();
        assertEquals(2, lines.size());
        assertEquals("Apache", lines.get(0).getString());
        assertEquals("POI", lines.get(1).getString());
        // the first line is at least two times higher than the second
        assertTrue(lines.get(0).getHeight() > lines.get(1).getHeight()*2);

        ppt.close();
    }

    @Test
    public void testThemeInheritance() throws IOException {
        XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx");
        List<XSLFShape> shapes = ppt.getSlides().get(0).getShapes();
        XSLFTextShape sh1 = (XSLFTextShape)shapes.get(0);
        assertEquals("Apache", sh1.getText());
        assertEquals(TextAlign.CENTER, sh1.getTextParagraphs().get(0).getTextAlign());
        XSLFTextShape sh2 = (XSLFTextShape)shapes.get(1);
        assertEquals("Software", sh2.getText());
        assertEquals(TextAlign.CENTER, sh2.getTextParagraphs().get(0).getTextAlign());
        XSLFTextShape sh3 = (XSLFTextShape)shapes.get(2);
        assertEquals("Foundation", sh3.getText());
        assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign());
        ppt.close();
    }

    @Test
    public void testParagraphProperties() throws IOException {
        XMLSlideShow ppt = new XMLSlideShow();
        XSLFSlide slide = ppt.createSlide();
        XSLFTextShape sh = slide.createAutoShape();

        XSLFTextParagraph p = sh.addNewTextParagraph();
        assertFalse(p.isBullet());
        p.setBullet(true);
        assertTrue(p.isBullet());

        assertEquals("\u2022", p.getBulletCharacter());
        p.setBulletCharacter("*");
        assertEquals("*", p.getBulletCharacter());

        assertEquals("Arial", p.getBulletFont());
        p.setBulletFont("Calibri");
        assertEquals("Calibri", p.getBulletFont());

        assertEquals(null, p.getBulletFontColor());
        p.setBulletFontColor(Color.red);
        assertTrue(sameColor(Color.red, p.getBulletFontColor()));

        assertNull(p.getBulletFontSize());
        p.setBulletFontSize(200.);
        assertEquals(200., p.getBulletFontSize(), 0);
        p.setBulletFontSize(-20.);
        assertEquals(-20.0, p.getBulletFontSize(), 0);

        assertEquals(72.0, p.getDefaultTabSize(), 0);
        
        assertNull(p.getIndent());
        p.setIndent(72.0);
        assertEquals(72.0, p.getIndent(), 0);
        p.setIndent(-1d); // the value of -1.0 resets to the defaults (not any more ...)
        assertEquals(-1d, p.getIndent(), 0);
        p.setIndent(null); 
        assertNull(p.getIndent());

        assertEquals(0.0, p.getLeftMargin(), 0);
        p.setLeftMargin(72.0);
        assertEquals(72.0, p.getLeftMargin(), 0);
        p.setLeftMargin(-1.0); // the value of -1.0 resets to the defaults
        assertEquals(-1.0, p.getLeftMargin(), 0);
        p.setLeftMargin(null);
        assertEquals(0d, p.getLeftMargin(), 0); // default will be taken from master

        assertEquals(0, p.getIndentLevel());
        p.setIndentLevel(1);
        assertEquals(1, p.getIndentLevel());
        p.setIndentLevel(2);
        assertEquals(2, p.getIndentLevel());

        assertNull(p.getLineSpacing());
        p.setLineSpacing(200.);
        assertEquals(200.0, p.getLineSpacing(), 0);
        p.setLineSpacing(-15.);
        assertEquals(-15.0, p.getLineSpacing(), 0);

        assertNull(p.getSpaceAfter());
        p.setSpaceAfter(200.);
        assertEquals(200.0, p.getSpaceAfter(), 0);
        p.setSpaceAfter(-15.);
        assertEquals(-15.0, p.getSpaceAfter(), 0);
        p.setSpaceAfter(null);
        assertNull(p.getSpaceAfter());
        p.setSpaceAfter(null);
        assertNull(p.getSpaceAfter());

        assertNull(p.getSpaceBefore());
        p.setSpaceBefore(200.);
        assertEquals(200.0, p.getSpaceBefore(), 0);
        p.setSpaceBefore(-15.);
        assertEquals(-15.0, p.getSpaceBefore(), 0);
        p.setSpaceBefore(null);
        assertNull(p.getSpaceBefore());
        p.setSpaceBefore(null);
        assertNull(p.getSpaceBefore());

        assertEquals(TextAlign.LEFT, p.getTextAlign());
        p.setTextAlign(TextAlign.RIGHT);
        assertEquals(TextAlign.RIGHT, p.getTextAlign());

        p.setBullet(false);
        assertFalse(p.isBullet());

        p.setBulletAutoNumber(AutoNumberingScheme.alphaLcParenBoth, 1);

        double tabStop = p.getTabStop(0);
        assertEquals(0.0, tabStop, 0);

        p.addTabStop(100.);
        assertEquals(100., p.getTabStop(0), 0);

        assertEquals(72.0, p.getDefaultTabSize(), 0);

        ppt.close();
    }

    @Test(expected = IllegalStateException.class)
    public void testLineBreak() throws IOException {
        XMLSlideShow ppt = new XMLSlideShow();
        try {
            XSLFSlide slide = ppt.createSlide();
            XSLFTextShape sh = slide.createAutoShape();
    
            XSLFTextParagraph p = sh.addNewTextParagraph();
            XSLFTextRun r1 = p.addNewTextRun();
            r1.setText("Hello,");
            XSLFTextRun r2 = p.addLineBreak();
            assertEquals("\n", r2.getRawText());
            r2.setFontSize(10.0);
            assertEquals(10.0, r2.getFontSize(), 0);
            XSLFTextRun r3 = p.addNewTextRun();
            r3.setText("World!");
            r3.setFontSize(20.0);
            XSLFTextRun r4 = p.addLineBreak();
            assertEquals(20.0, r4.getFontSize(), 0);
    
            assertEquals("Hello,\nWorld!\n",sh.getText());

            // "You cannot change text of a line break, it is always '\\n'"
            r2.setText("aaa");
        } finally {
            ppt.close();
        }
    }
}
