/* ====================================================================
   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.sl.draw;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.EventFilter;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.apache.poi.sl.draw.binding.CTCustomGeometry2D;
import org.apache.poi.sl.draw.geom.Context;
import org.apache.poi.sl.draw.geom.CustomGeometry;
import org.apache.poi.sl.draw.geom.Outline;
import org.apache.poi.sl.draw.geom.Path;
import org.apache.poi.sl.usermodel.LineDecoration;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.Shadow;
import org.apache.poi.sl.usermodel.SimpleShape;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;


public class DrawSimpleShape extends DrawShape {
    
    private static final double DECO_SIZE_POW = 1.5d;

    public DrawSimpleShape(SimpleShape<?,?> shape) {
        super(shape);
    }

    @Override
    public void draw(Graphics2D graphics) {
        DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(getShape());
        Paint fill = drawPaint.getPaint(graphics, getShape().getFillStyle().getPaint());
        Paint line = drawPaint.getPaint(graphics, getShape().getStrokeStyle().getPaint());
        BasicStroke stroke = getStroke(); // the stroke applies both to the shadow and the shape
        graphics.setStroke(stroke);

        Collection<Outline> elems = computeOutlines(graphics);

        // first paint the shadow
        drawShadow(graphics, elems, fill, line);

        // then fill the shape interior
        if (fill != null) {
            graphics.setPaint(fill);
            for (Outline o : elems) {
                if (o.getPath().isFilled()){
                    java.awt.Shape s = o.getOutline();
                    graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
                    graphics.fill(s);
                }
            }
        }

        // then draw any content within this shape (text, image, etc.)
        drawContent(graphics);

        // then stroke the shape outline
        if(line != null) {
            graphics.setPaint(line);
            graphics.setStroke(stroke);
            for(Outline o : elems){
                if(o.getPath().isStroked()){
                    java.awt.Shape s = o.getOutline();
                    graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
                    graphics.draw(s);
                }
            }
        }

        // draw line decorations
        drawDecoration(graphics, line, stroke);
    }

    protected void drawDecoration(Graphics2D graphics, Paint line, BasicStroke stroke) {
        if(line == null) {
            return;
        }
        graphics.setPaint(line);

        List<Outline> lst = new ArrayList<Outline>();
        LineDecoration deco = getShape().getLineDecoration();
        Outline head = getHeadDecoration(graphics, deco, stroke);
        if (head != null) {
            lst.add(head);
        }
        Outline tail = getTailDecoration(graphics, deco, stroke);
        if (tail != null) {
            lst.add(tail);
        }


        for(Outline o : lst){
            java.awt.Shape s = o.getOutline();
            Path p = o.getPath();
            graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);

            if(p.isFilled()) {
                graphics.fill(s);
            }
            if(p.isStroked()) {
                graphics.draw(s);
            }
        }
    }

    protected Outline getTailDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) {
        if (deco == null || stroke == null) {
            return null;
        }
        DecorationSize tailLength = deco.getTailLength();
        if (tailLength == null) {
            tailLength = DecorationSize.MEDIUM;
        }
        DecorationSize tailWidth = deco.getTailWidth();
        if (tailWidth == null) {
            tailWidth = DecorationSize.MEDIUM;
        }

        double lineWidth = Math.max(2.5, stroke.getLineWidth());

        Rectangle2D anchor = getAnchor(graphics, getShape());
        double x2 = anchor.getX() + anchor.getWidth(),
               y2 = anchor.getY() + anchor.getHeight();

        double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());

        AffineTransform at = new AffineTransform();
        java.awt.Shape tailShape = null;
        Path p = null;
        Rectangle2D bounds;
        final double scaleY = Math.pow(DECO_SIZE_POW, tailWidth.ordinal()+1.);
        final double scaleX = Math.pow(DECO_SIZE_POW, tailLength.ordinal()+1.);

        DecorationShape tailShapeEnum = deco.getTailShape();

        if (tailShapeEnum == null) {
            return null;
        }

        switch (tailShapeEnum) {
            case OVAL:
                p = new Path();
                tailShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
                bounds = tailShape.getBounds2D();
                at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2);
                at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
                break;
            case STEALTH:
            case ARROW:
                p = new Path(false, true);
                Path2D.Double arrow = new Path2D.Double();
                arrow.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2));
                arrow.lineTo(0, 0);
                arrow.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2));
                tailShape = arrow;
                at.translate(x2, y2);
                at.rotate(alpha);
                break;
            case TRIANGLE:
                p = new Path();
                Path2D.Double triangle = new Path2D.Double();
                triangle.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2));
                triangle.lineTo(0, 0);
                triangle.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2));
                triangle.closePath();
                tailShape = triangle;
                at.translate(x2, y2);
                at.rotate(alpha);
                break;
            default:
                break;
        }

        if (tailShape != null) {
            tailShape = at.createTransformedShape(tailShape);
        }
        return tailShape == null ? null : new Outline(tailShape, p);
    }

    protected Outline getHeadDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) {
        if (deco == null || stroke == null) {
            return null;
        }
        DecorationSize headLength = deco.getHeadLength();
        if (headLength == null) {
            headLength = DecorationSize.MEDIUM;
        }
        DecorationSize headWidth = deco.getHeadWidth();
        if (headWidth == null) {
            headWidth = DecorationSize.MEDIUM;
        }

        double lineWidth = Math.max(2.5, stroke.getLineWidth());

        Rectangle2D anchor = getAnchor(graphics, getShape());
        double x1 = anchor.getX(), y1 = anchor.getY();

        double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());

        AffineTransform at = new AffineTransform();
        java.awt.Shape headShape = null;
        Path p = null;
        Rectangle2D bounds;
        final double scaleY = Math.pow(DECO_SIZE_POW, headWidth.ordinal()+1.);
        final double scaleX = Math.pow(DECO_SIZE_POW, headLength.ordinal()+1.);
        DecorationShape headShapeEnum = deco.getHeadShape();

        if (headShapeEnum == null) {
            return null;
        }

        switch (headShapeEnum) {
            case OVAL:
                p = new Path();
                headShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
                bounds = headShape.getBounds2D();
                at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);
                at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
                break;
            case STEALTH:
            case ARROW:
                p = new Path(false, true);
                Path2D.Double arrow = new Path2D.Double();
                arrow.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2));
                arrow.lineTo(0, 0);
                arrow.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2));
                headShape = arrow;
                at.translate(x1, y1);
                at.rotate(alpha);
                break;
            case TRIANGLE:
                p = new Path();
                Path2D.Double triangle = new Path2D.Double();
                triangle.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2));
                triangle.lineTo(0, 0);
                triangle.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2));
                triangle.closePath();
                headShape = triangle;
                at.translate(x1, y1);
                at.rotate(alpha);
                break;
            default:
                break;
        }

        if (headShape != null) {
            headShape = at.createTransformedShape(headShape);
        }
        return headShape == null ? null : new Outline(headShape, p);
    }

    public BasicStroke getStroke() {
        return getStroke(getShape().getStrokeStyle());
    }

    protected void drawShadow(
        Graphics2D graphics
      , Collection<Outline> outlines
      , Paint fill
      , Paint line
    ) {
          Shadow<?,?> shadow = getShape().getShadow();
          if (shadow == null || (fill == null && line == null)) {
              return;
          }

          SolidPaint shadowPaint = shadow.getFillStyle();
          Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor());

          double shapeRotation = getShape().getRotation();
          if(getShape().getFlipVertical()) {
              shapeRotation += 180;
          }
          double angle = shadow.getAngle() - shapeRotation;
          double dist = shadow.getDistance();
          double dx = dist * Math.cos(Math.toRadians(angle));
          double dy = dist * Math.sin(Math.toRadians(angle));

          graphics.translate(dx, dy);

          for(Outline o : outlines){
              java.awt.Shape s = o.getOutline();
              Path p = o.getPath();
              graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
              graphics.setPaint(shadowColor);

              if(fill != null && p.isFilled()){
                  graphics.fill(s);
              } else if (line != null && p.isStroked()) {
                  graphics.draw(s);
              }
          }

          graphics.translate(-dx, -dy);
      }

    protected static CustomGeometry getCustomGeometry(String name) {
        return getCustomGeometry(name, null);
    }

    protected static CustomGeometry getCustomGeometry(String name, Graphics2D graphics) {
        @SuppressWarnings("unchecked")
        Map<String, CustomGeometry> presets = (graphics == null)
            ? null
            : (Map<String, CustomGeometry>)graphics.getRenderingHint(Drawable.PRESET_GEOMETRY_CACHE);

        if (presets == null) {
            presets = new HashMap<String,CustomGeometry>();
            if (graphics != null) {
                graphics.setRenderingHint(Drawable.PRESET_GEOMETRY_CACHE, presets);
            }

            String packageName = "org.apache.poi.sl.draw.binding";
            InputStream presetIS = Drawable.class.getResourceAsStream("presetShapeDefinitions.xml");

            // StAX:
            EventFilter startElementFilter = new EventFilter() {
                @Override
                public boolean accept(XMLEvent event) {
                    return event.isStartElement();
                }
            };

            try {
                XMLInputFactory staxFactory = XMLInputFactory.newInstance();
                XMLEventReader staxReader = staxFactory.createXMLEventReader(presetIS);
                XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter);
                // Ignore StartElement:
                staxFiltRd.nextEvent();
                // JAXB:
                JAXBContext jaxbContext = JAXBContext.newInstance(packageName);
                Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

                while (staxFiltRd.peek() != null) {
                    StartElement evRoot = (StartElement)staxFiltRd.peek();
                    String cusName = evRoot.getName().getLocalPart();
                    // XMLEvent ev = staxReader.nextEvent();
                    JAXBElement<org.apache.poi.sl.draw.binding.CTCustomGeometry2D> el = unmarshaller.unmarshal(staxReader, CTCustomGeometry2D.class);
                    CTCustomGeometry2D cusGeom = el.getValue();

                    presets.put(cusName, new CustomGeometry(cusGeom));
                }
                
                staxFiltRd.close();
                staxReader.close();
            } catch (Exception e) {
                throw new RuntimeException("Unable to load preset geometries.", e);
            } finally {
                IOUtils.closeQuietly(presetIS);
            }
        }

        return presets.get(name);
    }

    protected Collection<Outline> computeOutlines(Graphics2D graphics) {

        List<Outline> lst = new ArrayList<Outline>();
        CustomGeometry geom = getShape().getGeometry();
        if(geom == null) {
            return lst;
        }

        Rectangle2D anchor = getAnchor(graphics, getShape());
        for (Path p : geom) {

            double w = p.getW() == -1 ? anchor.getWidth() * Units.EMU_PER_POINT : p.getW();
            double h = p.getH() == -1 ? anchor.getHeight() * Units.EMU_PER_POINT : p.getH();

            // the guides in the shape definitions are all defined relative to each other,
            // so we build the path starting from (0,0).
            final Rectangle2D pathAnchor = new Rectangle2D.Double(0,0,w,h);

            Context ctx = new Context(geom, pathAnchor, getShape());

            java.awt.Shape gp = p.getPath(ctx);

            // translate the result to the canvas coordinates in points
            AffineTransform at = new AffineTransform();
            at.translate(anchor.getX(), anchor.getY());

            double scaleX, scaleY;
            if (p.getW() != -1) {
                scaleX = anchor.getWidth() / p.getW();
            } else {
                scaleX = 1.0 / Units.EMU_PER_POINT;
            }
            if (p.getH() != -1) {
                scaleY = anchor.getHeight() / p.getH();
            } else {
                scaleY = 1.0 / Units.EMU_PER_POINT;
            }

            at.scale(scaleX, scaleY);

            java.awt.Shape canvasShape = at.createTransformedShape(gp);

            lst.add(new Outline(canvasShape, p));
        }

        return lst;
    }

    @Override
    protected SimpleShape<?,?> getShape() {
        return (SimpleShape<?,?>)shape;
    }
}
