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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.NotImplemented;
import org.apache.poi.util.SuppressForbidden;

import java.awt.*;
import java.awt.image.ImageObserver;
import java.text.AttributedCharacterIterator;

/**
 * Translates Graphics calls into escher calls.  The translation is lossy so
 * many features are not supported and some just aren't implemented yet.  If
 * in doubt test the specific calls you wish to make. Graphics calls are
 * always performed into an EscherGroup so one will need to be created.
 * <p>
 * <b>Important:</b>
 * <blockquote>
 * One important concept worth considering is that of font size.  One of the
 * difficulties in converting Graphics calls into escher drawing calls is that
 * Excel does not have the concept of absolute pixel positions.  It measures
 * it's cell widths in 'characters' and the cell heights in points.
 * Unfortunately it's not defined exactly what a type of character it's
 * measuring.  Presumably this is due to the fact that the Excel will be
 * using different fonts on different platforms or even within the same
 * platform.
 * <p>
 * Because of this constraint we've had to calculate the
 * verticalPointsPerPixel.  This the amount the font should be scaled by when
 * you issue commands such as drawString().  A good way to calculate this
 * is to use the follow formula:
 * <p>
 * <pre>
 *      multipler = groupHeightInPoints / heightOfGroup
 * </pre>
 * <p>
 * The height of the group is calculated fairly simply by calculating the
 * difference between the y coordinates of the bounding box of the shape.  The
 * height of the group can be calculated by using a convenience called
 * <code>HSSFClientAnchor.getAnchorHeightInPoints()</code>.
 * </blockquote>
 */
public class EscherGraphics extends Graphics {
    private static final Logger LOG = LogManager.getLogger(EscherGraphics.class);

    private final HSSFShapeGroup escherGroup;
    private final HSSFWorkbook workbook;
    private float verticalPointsPerPixel = 1.0f;
    private final float verticalPixelsPerPoint;
    private Color foreground;
    private Color background = Color.white;
    private Font font;

    /**
     * Construct an escher graphics object.
     *
     * @param escherGroup           The escher group to write the graphics calls into.
     * @param workbook              The workbook we are using.
     * @param forecolor             The foreground color to use as default.
     * @param verticalPointsPerPixel    The font multiplier.  (See class description for information on how this works.).
     */
    public EscherGraphics(HSSFShapeGroup escherGroup, HSSFWorkbook workbook, Color forecolor, float verticalPointsPerPixel )
    {
        this.escherGroup = escherGroup;
        this.workbook = workbook;
        this.verticalPointsPerPixel = verticalPointsPerPixel;
        this.verticalPixelsPerPoint = 1 / verticalPointsPerPixel;
        this.font = new Font("Arial", 0, 10);
        this.foreground = forecolor;
//        background = backcolor;
    }

    /**
     * Constructs an escher graphics object.
     *
     * @param escherGroup           The escher group to write the graphics calls into.
     * @param workbook              The workbook we are using.
     * @param foreground            The foreground color to use as default.
     * @param verticalPointsPerPixel    The font multiplier.  (See class description for information on how this works.).
     * @param font                  The font to use.
     */
    EscherGraphics( HSSFShapeGroup escherGroup, HSSFWorkbook workbook, Color foreground, Font font, float verticalPointsPerPixel )
    {
        this.escherGroup = escherGroup;
        this.workbook = workbook;
        this.foreground = foreground;
//        this.background = background;
        this.font = font;
        this.verticalPointsPerPixel = verticalPointsPerPixel;
        this.verticalPixelsPerPoint = 1 / verticalPointsPerPixel;
    }

//    /**
//     * Constructs an escher graphics object.
//     *
//     * @param escherGroup           The escher group to write the graphics calls into.
//     * @param workbook              The workbook we are using.
//     * @param forecolor             The default foreground color.
//     */
//    public EscherGraphics( HSSFShapeGroup escherGroup, HSSFWorkbook workbook, Color forecolor)
//    {
//        this(escherGroup, workbook, forecolor, 1.0f);
//    }


    @Override
    public void clearRect(int x, int y, int width, int height)
    {
        Color color = foreground;
        setColor(background);
        fillRect(x,y,width,height);
        setColor(color);
    }

    @Override
    @NotImplemented
    public void clipRect(int x, int y, int width, int height)
    {
        LOG.atWarn().log("clipRect not supported");
    }

    @Override
    @NotImplemented
    public void copyArea(int x, int y, int width, int height, int dx, int dy)
    {
        LOG.atWarn().log("copyArea not supported");
    }

    @Override
    public Graphics create()
    {
        return new EscherGraphics(escherGroup, workbook,
                foreground, font, verticalPointsPerPixel );
    }

    @Override
    public void dispose()
    {
    }

    @Override
    @NotImplemented
    public void drawArc(int x, int y, int width, int height,
				 int startAngle, int arcAngle)
    {
        LOG.atWarn().log("drawArc not supported");
    }

    @Override
    @NotImplemented
    public boolean drawImage(Image img,
				      int dx1, int dy1, int dx2, int dy2,
				      int sx1, int sy1, int sx2, int sy2,
				      Color bgcolor,
				      ImageObserver observer)
    {
        LOG.atWarn().log("drawImage not supported");

        return true;
    }

    @Override
    @NotImplemented
    public boolean drawImage(Image img,
				      int dx1, int dy1, int dx2, int dy2,
				      int sx1, int sy1, int sx2, int sy2,
				      ImageObserver observer)
    {
        LOG.atWarn().log("drawImage not supported");
        return true;
    }

    @Override
    public boolean drawImage(Image image, int i, int j, int k, int l, Color color, ImageObserver imageobserver)
    {
        return drawImage(image, i, j, i + k, j + l, 0, 0, image.getWidth(imageobserver), image.getHeight(imageobserver), color, imageobserver);
    }

    @Override
    public boolean drawImage(Image image, int i, int j, int k, int l, ImageObserver imageobserver)
    {
        return drawImage(image, i, j, i + k, j + l, 0, 0, image.getWidth(imageobserver), image.getHeight(imageobserver), imageobserver);
    }

    @Override
    public boolean drawImage(Image image, int i, int j, Color color, ImageObserver imageobserver)
    {
        return drawImage(image, i, j, image.getWidth(imageobserver), image.getHeight(imageobserver), color, imageobserver);
    }

    @Override
    public boolean drawImage(Image image, int i, int j, ImageObserver imageobserver)
    {
        return drawImage(image, i, j, image.getWidth(imageobserver), image.getHeight(imageobserver), imageobserver);
    }

    @Override
    public void drawLine(int x1, int y1, int x2, int y2)
    {
        drawLine(x1,y1,x2,y2,0);
    }

    public void drawLine(int x1, int y1, int x2, int y2, int width)
    {
        HSSFSimpleShape shape = escherGroup.createShape(new HSSFChildAnchor(x1, y1, x2, y2) );
        shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
        shape.setLineWidth(width);
        shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
    }

    @Override
    public void drawOval(int x, int y, int width, int height)
    {
        HSSFSimpleShape shape = escherGroup.createShape(new HSSFChildAnchor(x,y,x+width,y+height) );
        shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL);
        shape.setLineWidth(0);
        shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
        shape.setNoFill(true);
    }

    @Override
    public void drawPolygon(int[] xPoints, int[] yPoints,
                            int nPoints)
    {
        int right  = findBiggest(xPoints);
        int bottom = findBiggest(yPoints);
        int left   = findSmallest(xPoints);
        int top    = findSmallest(yPoints);
        HSSFPolygon shape = escherGroup.createPolygon(new HSSFChildAnchor(left,top,right,bottom) );
        shape.setPolygonDrawArea(right - left, bottom - top);
        shape.setPoints(addToAll(xPoints, -left), addToAll(yPoints, -top));
        shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
        shape.setLineWidth(0);
        shape.setNoFill(true);
    }

    private int[] addToAll( int[] values, int amount )
    {
        int[] result = new int[values.length];
        for ( int i = 0; i < values.length; i++ )
            result[i] = values[i] + amount;
        return result;
    }

    @Override
    @NotImplemented
    public void drawPolyline(int[] xPoints, int[] yPoints,
                             int nPoints)
    {
        LOG.atWarn().log("drawPolyline not supported");
    }

    @Override
    @NotImplemented
    public void drawRect(int x, int y, int width, int height)
    {
        LOG.atWarn().log("drawRect not supported");
    }

    @Override
    @NotImplemented
    public void drawRoundRect(int x, int y, int width, int height,
				       int arcWidth, int arcHeight)
    {
        LOG.atWarn().log("drawRoundRect not supported");
    }

    @Override
    public void drawString(String str, int x, int y)
    {
        if (str == null || str.isEmpty())
            return;

        Font excelFont = font;
        if ( font.getName().equals( "SansSerif" ) )
        {
            excelFont = new Font( "Arial", font.getStyle(), (int) ( font.getSize() / verticalPixelsPerPoint ) );
        }
        else
        {
            excelFont = new Font( font.getName(), font.getStyle(), (int) ( font.getSize() / verticalPixelsPerPoint ));
        }
        FontDetails d = StaticFontMetrics.getFontDetails( excelFont );
        int width = d.getStringWidth( str ) * 8  + 12;
        int height = (int) ( ( font.getSize() / verticalPixelsPerPoint ) + 6 ) * 2;
        y -= ( font.getSize() / verticalPixelsPerPoint ) + 2 * verticalPixelsPerPoint;    // we want to draw the shape from the top-left
        HSSFTextbox textbox = escherGroup.createTextbox( new HSSFChildAnchor( x, y, x + width, y + height ) );
        textbox.setNoFill( true );
        textbox.setLineStyle( HSSFShape.LINESTYLE_NONE );
        HSSFRichTextString s = new HSSFRichTextString( str );
        HSSFFont hssfFont = matchFont( excelFont );
        s.applyFont( hssfFont );
        textbox.setString( s );
    }

    private HSSFFont matchFont( Font matchFont )
    {
        HSSFColor hssfColor = workbook.getCustomPalette()
                .findColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
        if (hssfColor == null)
            hssfColor = workbook.getCustomPalette().findSimilarColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
        boolean bold = (matchFont.getStyle() & Font.BOLD) != 0;
        boolean italic = (matchFont.getStyle() & Font.ITALIC) != 0;
        HSSFFont hssfFont = workbook.findFont(bold,
                    hssfColor.getIndex(),
                    (short)(matchFont.getSize() * 20),
                    matchFont.getName(),
                    italic,
                    false,
                    (short)0,
                    (byte)0);
        if (hssfFont == null)
        {
            hssfFont = workbook.createFont();
            hssfFont.setBold(bold);
            hssfFont.setColor(hssfColor.getIndex());
            hssfFont.setFontHeight((short)(matchFont.getSize() * 20));
            hssfFont.setFontName(matchFont.getName());
            hssfFont.setItalic(italic);
            hssfFont.setStrikeout(false);
            hssfFont.setTypeOffset((short) 0);
            hssfFont.setUnderline((byte) 0);
        }

        return hssfFont;
    }


    @Override
    public void drawString(AttributedCharacterIterator iterator,
                                    int x, int y)
    {
        LOG.atWarn().log("drawString not supported");
    }

    @Override
    public void fillArc(int x, int y, int width, int height,
				 int startAngle, int arcAngle)
    {
        LOG.atWarn().log("fillArc not supported");
    }

    @Override
    public void fillOval(int x, int y, int width, int height)
    {
        HSSFSimpleShape shape = escherGroup.createShape(new HSSFChildAnchor( x, y, x + width, y + height ) );
        shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL);
        shape.setLineStyle(HSSFShape.LINESTYLE_NONE);
        shape.setFillColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
        shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
        shape.setNoFill(false);
    }

    /**
     * Fills a (closed) polygon, as defined by a pair of arrays, which
     *  hold the <i>x</i> and <i>y</i> coordinates.
     * <p>
     * This draws the polygon, with <code>nPoint</code> line segments.
     * The first <code>nPoint&nbsp;-&nbsp;1</code> line segments are
     *  drawn between sequential points
     *  (<code>xPoints[i],yPoints[i],xPoints[i+1],yPoints[i+1]</code>).
     * The final line segment is a closing one, from the last point to
     *  the first (assuming they are different).
     * <p>
     * The area inside of the polygon is defined by using an
     *  even-odd fill rule (also known as the alternating rule), and
     *  the area inside of it is filled.
     * @param xPoints array of the <code>x</code> coordinates.
     * @param yPoints array of the <code>y</code> coordinates.
     * @param nPoints the total number of points in the polygon.
     * @see   Graphics#drawPolygon(int[], int[], int)
     */
    @Override
    public void fillPolygon(int[] xPoints, int[] yPoints,
                            int nPoints)
    {
        int right  = findBiggest(xPoints);
        int bottom = findBiggest(yPoints);
        int left   = findSmallest(xPoints);
        int top    = findSmallest(yPoints);
        HSSFPolygon shape = escherGroup.createPolygon(new HSSFChildAnchor(left,top,right,bottom) );
        shape.setPolygonDrawArea(right - left, bottom - top);
        shape.setPoints(addToAll(xPoints, -left), addToAll(yPoints, -top));
        shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
        shape.setFillColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
    }

    private int findBiggest( int[] values )
    {
        int result = Integer.MIN_VALUE;
        for ( int i = 0; i < values.length; i++ )
        {
            if (values[i] > result)
                result = values[i];
        }
        return result;
    }

    private int findSmallest( int[] values )
    {
        int result = Integer.MAX_VALUE;
        for ( int i = 0; i < values.length; i++ )
        {
            if (values[i] < result)
                result = values[i];
        }
        return result;
    }

    @Override
    public void fillRect(int x, int y, int width, int height)
    {
        HSSFSimpleShape shape = escherGroup.createShape(new HSSFChildAnchor( x, y, x + width, y + height ) );
        shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_RECTANGLE);
        shape.setLineStyle(HSSFShape.LINESTYLE_NONE);
        shape.setFillColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
        shape.setLineStyleColor(foreground.getRed(), foreground.getGreen(), foreground.getBlue());
    }

    @Override
    public void fillRoundRect(int x, int y, int width, int height,
				       int arcWidth, int arcHeight)
    {
        LOG.atWarn().log("fillRoundRect not supported");
    }

    @Override
    public Shape getClip()
    {
        return getClipBounds();
    }

    @Override
    public Rectangle getClipBounds()
    {
        return null;
    }

    @Override
    public Color getColor()
    {
        return foreground;
    }

    @Override
    public Font getFont()
    {
        return font;
    }

    @Override
    @SuppressWarnings("deprecation")
    @SuppressForbidden
    public FontMetrics getFontMetrics(Font f)
    {
        return Toolkit.getDefaultToolkit().getFontMetrics(f);
    }

    @Override
    public void setClip(int x, int y, int width, int height)
    {
        setClip(new Rectangle(x,y,width,height));
    }

    @Override
    @NotImplemented
    public void setClip(Shape shape)
    {
        LOG.atWarn().log("setClip not supported");
    }

    @Override
    public void setColor(Color color)
    {
        foreground = color;
    }

    @Override
    public void setFont(Font f)
    {
        font = f;
    }

    @Override
    @NotImplemented
    public void setPaintMode()
    {
        LOG.atWarn().log("setPaintMode not supported");
    }

    @Override
    @NotImplemented
    public void setXORMode(Color color)
    {
        LOG.atWarn().log("setXORMode not supported");
    }

    @Override
    @NotImplemented
    public void translate(int x, int y)
    {
        LOG.atWarn().log("translate not supported");
    }

    public Color getBackground()
    {
        return background;
    }

    public void setBackground( Color background )
    {
        this.background = background;
    }

    HSSFShapeGroup getEscherGraphics()
    {
        return escherGroup;
    }
}

