/* ====================================================================
   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.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.poi.POIDataSamples;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.apache.poi.util.Units;
import org.apache.poi.xslf.XSLFTestDataSamples;
import org.apache.poi.xslf.util.PPTX2PNG;
import org.apache.xmlbeans.XmlObject;
import org.junit.jupiter.api.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleList;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;

class TestXSLFSimpleShape {

    @Test
    void testLineStyles() throws IOException {
        try (XMLSlideShow ppt = new XMLSlideShow()) {
            XSLFSlide slide = ppt.createSlide();

            XSLFSimpleShape shape = slide.createAutoShape();
            assertEquals(1, slide.getShapes().size());
            // line properties are not set by default
            assertFalse(getSpPr(shape).isSetLn());

            assertEquals(0., shape.getLineWidth(), 0);
            assertNull(shape.getLineColor());
            assertNull(shape.getLineDash());
            assertNull(shape.getLineCap());

            shape.setLineWidth(0);
            shape.setLineColor(null);
            shape.setLineDash(null);
            shape.setLineCap(null);

            assertTrue(getSpPr(shape).isSetLn());
            assertTrue(getSpPr(shape).getLn().isSetNoFill());

            // line width
            shape.setLineWidth(1.0);
            assertEquals(1.0, shape.getLineWidth(), 0);
            assertEquals(Units.EMU_PER_POINT, getSpPr(shape).getLn().getW());
            shape.setLineWidth(5.5);
            assertEquals(5.5, shape.getLineWidth(), 0);
            assertEquals(Units.toEMU(5.5), getSpPr(shape).getLn().getW());
            shape.setLineWidth(0.0);
            // setting line width to zero unsets the W attribute
            assertFalse(getSpPr(shape).getLn().isSetW());

            // line cap
            shape.setLineCap(LineCap.FLAT);
            assertEquals(LineCap.FLAT, shape.getLineCap());
            assertEquals(STLineCap.FLAT, getSpPr(shape).getLn().getCap());
            shape.setLineCap(LineCap.SQUARE);
            assertEquals(LineCap.SQUARE, shape.getLineCap());
            assertEquals(STLineCap.SQ, getSpPr(shape).getLn().getCap());
            shape.setLineCap(LineCap.ROUND);
            assertEquals(LineCap.ROUND, shape.getLineCap());
            assertEquals(STLineCap.RND, getSpPr(shape).getLn().getCap());
            shape.setLineCap(null);
            // setting cap to null unsets the Cap attribute
            assertFalse(getSpPr(shape).getLn().isSetCap());

            // line dash
            shape.setLineDash(LineDash.SOLID);
            assertEquals(LineDash.SOLID, shape.getLineDash());
            assertEquals(STPresetLineDashVal.SOLID, getSpPr(shape).getLn().getPrstDash().getVal());
            shape.setLineDash(LineDash.DASH_DOT);
            assertEquals(LineDash.DASH_DOT, shape.getLineDash());
            assertEquals(STPresetLineDashVal.DASH_DOT, getSpPr(shape).getLn().getPrstDash().getVal());
            shape.setLineDash(LineDash.LG_DASH_DOT);
            assertEquals(LineDash.LG_DASH_DOT, shape.getLineDash());
            assertEquals(STPresetLineDashVal.LG_DASH_DOT, getSpPr(shape).getLn().getPrstDash().getVal());
            shape.setLineDash(null);
            // setting dash width to null unsets the Dash element
            assertFalse(getSpPr(shape).getLn().isSetPrstDash());

            // line color
            assertFalse(getSpPr(shape).getLn().isSetSolidFill());
            shape.setLineColor(Color.RED);
            assertEquals(Color.RED, shape.getLineColor());
            assertTrue(getSpPr(shape).getLn().isSetSolidFill());
            shape.setLineColor(Color.BLUE);
            assertEquals(Color.BLUE, shape.getLineColor());
            assertTrue(getSpPr(shape).getLn().isSetSolidFill());
            shape.setLineColor(null);
            assertNull(shape.getLineColor());
            // setting dash width to null unsets the SolidFill element
            assertFalse(getSpPr(shape).getLn().isSetSolidFill());

            XSLFSimpleShape ln2 = slide.createAutoShape();
            ln2.setLineDash(LineDash.DOT);
            assertEquals(LineDash.DOT, ln2.getLineDash());
            ln2.setLineWidth(0.);
            assertEquals(0., ln2.getLineWidth(), 0);

            XSLFSimpleShape ln3 = slide.createAutoShape();
            ln3.setLineWidth(1.);
            assertEquals(1., ln3.getLineWidth(), 0);
            ln3.setLineDash(null);
            assertNull(ln3.getLineDash());
            ln3.setLineCap(null);
            assertNull(ln3.getLineDash());
        }
    }

    @Test
    void testFill() throws IOException {
        try (XMLSlideShow ppt = new XMLSlideShow()) {
            XSLFSlide slide = ppt.createSlide();

            XSLFAutoShape shape = slide.createAutoShape();
            // line properties are not set by default
            assertFalse(getSpPr(shape).isSetSolidFill());

            assertNull(shape.getFillColor());
            shape.setFillColor(null);
            assertNull(shape.getFillColor());
            assertFalse(getSpPr(shape).isSetSolidFill());

            shape.setFillColor(Color.RED);
            assertEquals(Color.RED, shape.getFillColor());
            shape.setFillColor(Color.DARK_GRAY);
            assertEquals(Color.DARK_GRAY, shape.getFillColor());
            assertTrue(getSpPr(shape).isSetSolidFill());

            shape.setFillColor(null);
            assertNull(shape.getFillColor());
            assertFalse(getSpPr(shape).isSetSolidFill());
        }
    }

    @Test
    void testDefaultProperties() throws IOException {
        try (XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx")) {
            XSLFSlide slide6 = ppt.getSlides().get(5);
            List<XSLFShape> shapes = slide6.getShapes();
            for (XSLFShape xs : shapes) {
                XSLFSimpleShape s = (XSLFSimpleShape) xs;
                // all shapes have a theme color="accent1"
                assertEquals("accent1", s.getSpStyle().getFillRef().getSchemeClr().getVal().toString());
                assertEquals(2.0, s.getLineWidth(), 0);
                assertEquals(LineCap.FLAT, s.getLineCap());
                assertEquals(new Color(79, 129, 189), s.getLineColor());
            }

            XSLFSimpleShape s0 = (XSLFSimpleShape) shapes.get(0);
            // fill is not set
            assertNull(getSpPr(s0).getSolidFill());
            //assertEquals(slide6.getTheme().getColor("accent1").getColor(), s0.getFillColor());
            assertEquals(new Color(79, 129, 189), s0.getFillColor());

            // lighter 80%
            XSLFSimpleShape s1 = (XSLFSimpleShape) shapes.get(1);
            CTSchemeColor ref1 = getSpPr(s1).getSolidFill().getSchemeClr();
            assertEquals(1, ref1.sizeOfLumModArray());
            assertEquals(1, ref1.sizeOfLumOffArray());
            assertEquals(20000, ref1.getLumModArray(0).getVal());
            assertEquals(80000, ref1.getLumOffArray(0).getVal());
            assertEquals("accent1", ref1.getVal().toString());
            assertEquals(new Color(220, 230, 242), s1.getFillColor());

            // lighter 60%
            XSLFSimpleShape s2 = (XSLFSimpleShape) shapes.get(2);
            CTSchemeColor ref2 = getSpPr(s2).getSolidFill().getSchemeClr();
            assertEquals(1, ref2.sizeOfLumModArray());
            assertEquals(1, ref2.sizeOfLumOffArray());
            assertEquals(40000, ref2.getLumModArray(0).getVal());
            assertEquals(60000, ref2.getLumOffArray(0).getVal());
            assertEquals("accent1", ref2.getVal().toString());
            assertEquals(new Color(185, 205, 229), s2.getFillColor());

            // lighter 40%
            XSLFSimpleShape s3 = (XSLFSimpleShape) shapes.get(3);
            CTSchemeColor ref3 = getSpPr(s3).getSolidFill().getSchemeClr();
            assertEquals(1, ref3.sizeOfLumModArray());
            assertEquals(1, ref3.sizeOfLumOffArray());
            assertEquals(60000, ref3.getLumModArray(0).getVal());
            assertEquals(40000, ref3.getLumOffArray(0).getVal());
            assertEquals("accent1", ref3.getVal().toString());
            assertEquals(new Color(149, 179, 215), s3.getFillColor());

            // darker 25%
            XSLFSimpleShape s4 = (XSLFSimpleShape) shapes.get(4);
            CTSchemeColor ref4 = getSpPr(s4).getSolidFill().getSchemeClr();
            assertEquals(1, ref4.sizeOfLumModArray());
            assertEquals(0, ref4.sizeOfLumOffArray());
            assertEquals(75000, ref4.getLumModArray(0).getVal());
            assertEquals("accent1", ref3.getVal().toString());
            assertEquals(new Color(55, 96, 146), s4.getFillColor());

            XSLFSimpleShape s5 = (XSLFSimpleShape) shapes.get(5);
            CTSchemeColor ref5 = getSpPr(s5).getSolidFill().getSchemeClr();
            assertEquals(1, ref5.sizeOfLumModArray());
            assertEquals(0, ref5.sizeOfLumOffArray());
            assertEquals(50000, ref5.getLumModArray(0).getVal());
            assertEquals("accent1", ref5.getVal().toString());
            assertEquals(new Color(37, 64, 97), s5.getFillColor());
        }
    }

    @Test
    void testAnchor() throws IOException {
        try (XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx")) {
            List<XSLFSlide> slide = ppt.getSlides();

            XSLFSlide slide2 = slide.get(1);
            XSLFSlideLayout layout2 = slide2.getSlideLayout();
            List<XSLFShape> shapes2 = slide2.getShapes();
            XSLFTextShape sh1 = (XSLFTextShape) shapes2.get(0);
            assertEquals(Placeholder.CENTERED_TITLE, sh1.getTextType());
            assertEquals("PPTX Title", sh1.getText());
            assertFalse(getSpPr(sh1).isSetXfrm()); // xfrm is not set, the query is delegated to the slide layout
            assertEquals(sh1.getAnchor(), layout2.getTextShapeByType(Placeholder.CENTERED_TITLE).getAnchor());

            XSLFTextShape sh2 = (XSLFTextShape) shapes2.get(1);
            assertEquals("Subtitle\nAnd second line", sh2.getText());
            assertEquals(Placeholder.SUBTITLE, sh2.getTextType());
            assertFalse(getSpPr(sh2).isSetXfrm()); // xfrm is not set, the query is delegated to the slide layout
            assertEquals(sh2.getAnchor(), layout2.getTextShapeByType(Placeholder.SUBTITLE).getAnchor());

            XSLFSlide slide5 = slide.get(4);
            XSLFSlideLayout layout5 = slide5.getSlideLayout();
            XSLFTextShape shTitle = slide5.getTextShapeByType(Placeholder.TITLE);
            assertEquals("Hyperlinks", shTitle.getText());
            // xfrm is not set, the query is delegated to the slide layout
            assertFalse(getSpPr(shTitle).isSetXfrm());
            // xfrm is not set, the query is delegated to the slide master
            assertFalse(getSpPr(layout5.getTextShapeByType(Placeholder.TITLE)).isSetXfrm());
            assertTrue(getSpPr(layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE)).isSetXfrm());
            assertEquals(shTitle.getAnchor(), layout5.getSlideMaster().getTextShapeByType(Placeholder.TITLE).getAnchor());
        }
    }

    @SuppressWarnings({"unused", "deprecation"})
    @Test
    void testShadowEffects() throws IOException{
        try (XMLSlideShow ppt = new XMLSlideShow()) {
            XSLFSlide slide = ppt.createSlide();
            CTStyleMatrix styleMatrix = slide.getTheme().getXmlObject().getThemeElements().getFmtScheme();
            CTEffectStyleList lst = styleMatrix.getEffectStyleLst();
            assertNotNull(lst);
            for (CTEffectStyleItem ef : lst.getEffectStyleArray()) {
                CTOuterShadowEffect obj = ef.getEffectLst().getOuterShdw();
            }
        }
    }

    @Test
    void testValidGeometry() throws Exception {
        try (XMLSlideShow ppt = new XMLSlideShow()) {
            XSLFSlide slide = ppt.createSlide();

            XSLFSimpleShape shape = slide.createAutoShape();
            CTShapeProperties spPr = getSpPr(shape);

            CTPresetGeometry2D prstGeom = CTPresetGeometry2D.Factory.newInstance();
            prstGeom.setPrst(STShapeType.Enum.forInt(1));

            assertNotNull(prstGeom.getPrst());
            assertNotNull(prstGeom.getPrst().toString());
            assertNotNull(spPr.getPrstGeom());
            spPr.setPrstGeom(prstGeom);
            assertNotNull(spPr.getPrstGeom().getPrst());
            assertNotNull(spPr.getPrstGeom().getPrst().toString());

            assertNotNull(shape.getGeometry());
        }
    }

    @Test
    void testArrayStoreException() throws Exception {
        File tmpDir = new File("build/tmp/");

        // fix maven build errors
        if (!tmpDir.exists()) {
            assertTrue(tmpDir.mkdirs());
        }

        File file = POIDataSamples.getSlideShowInstance().getFile("aascu.org_workarea_downloadasset.aspx_id=5864.pptx");
        String[] args = {
                "-format", "null", // png,gif,jpg,svg or null for test
                "-slide", "-1", // -1 for all
                "-outdir", tmpDir.getCanonicalPath(),
                "-quiet",
                "-fixside", "long",
                "-scale", "800",
                file.getAbsolutePath()
        };
        PPTX2PNG.main(args);
    }

    static CTShapeProperties getSpPr(XSLFShape shape) {
        XmlObject xo = shape.getShapeProperties();
        assertTrue(xo instanceof CTShapeProperties);
        return (CTShapeProperties)xo;
    }
}