/*
 * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

/*
 * $Id: ChartServlet.java,v 1.4 2004/11/14 07:33:14 tcfujii Exp $
 */

package components.renderkit;

import components.model.ChartItem;

import com.sun.image.codec.jpeg.*;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.geom.Ellipse2D;
import java.awt.RenderingHints;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

/**
 * <p><strong>ChartServlet</strong> is used to render the chart image.
 */
public final class ChartServlet extends HttpServlet {

    /**
     * <p>The <code>ServletConfig</code> instance for this servlet.</p>
     */
    private ServletConfig servletConfig = null;



    /**
     * <p>Release all resources acquired at startup time.</p>
     */
    public void destroy() {
        servletConfig = null;
    }

    /**
     * <p>Return the <code>ServletConfig</code> instance for this servlet.</p>
     */
    public ServletConfig getServletConfig() {

        return (this.servletConfig);

    }

    /**
     * <p>Return information about this Servlet.</p>
     */
    public String getServletInfo() {

        return (this.getClass().getName());

    }

    /**
     * <p>Perform initialization.</p>
     *
     * @exception ServletException if, for any reason,
     * bn error occurred during the processing of
     * this <code>init()</code> method.
     */
    public void init(ServletConfig servletConfig) throws ServletException {

        // Save our ServletConfig instance
        this.servletConfig = servletConfig;
    }

    /**
     * <p>Process an incoming request, and create the corresponding
     * response.</p>
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException if an input/output error occurs during processing
     * @exception ServletException if a servlet error occurs during processing
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {


    // Here's where we'd get the ChartBean from the session and determine
    // whether we're generating a pie chart or bar chart...
    //
    String type = request.getParameter("type");
    if ((type == null) ||
        (!type.equals("bar")) && (!type.equals("pie"))) {
        type = "bar";
    }

    if (type.equals("bar")) {
        generateBarChart(request, response);
    } else {
            generatePieChart(request, response);
    }
    }

    /**
     * <p>Process an incoming request, and create the corresponding
     * response.</p>
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException if an input/output error occurs during processing
     * @exception ServletException if a servlet error occurs during processing
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
    doGet(request, response);
    }

    /**
     * <p> Generate a bar chart from data.
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException if an input/output error occurs during processing
     * @exception ServletException if a servlet error occurs during processing
     */
    private void generateBarChart(HttpServletRequest request,
                          HttpServletResponse response)
        throws IOException, ServletException {

        final int VERTICAL = 0;
    final int HORIZONTAL = 1;

    response.setContentType("image/jpeg");

        String id = request.getParameter("chartId");

    // get chart parameters
    String title = request.getParameter("title");
    if (title == null) {
        title = "Chart";
    }

    int orientation = VERTICAL;
    String orientationStr = request.getParameter("orientation");
    if ((orientationStr == null) ||
        (!orientationStr.equals("horizontal")) && (!orientationStr.equals("vertical"))) {
        orientation = VERTICAL;
    } else if (orientationStr.equals("vertical")) {
        orientation = VERTICAL;
    } else {
        orientation = HORIZONTAL;
    }

    // label for x/y axis
    String xLabel = request.getParameter("xlabel");
    String yLabel = request.getParameter("ylabel");

    // default image size
    int width = 400;
    int height = 300;
    String widthStr = request.getParameter("width");
    String heightStr = request.getParameter("height");
    if (widthStr != null) {
        width = Integer.parseInt(widthStr);
    }
    if (heightStr != null) {
        height = Integer.parseInt(heightStr);
    }

    // get an array of chart items containing our data..
        HttpSession session = request.getSession(true);
    ChartItem[] chartItems = (ChartItem[])session.getAttribute(id);
    if (chartItems == null) {
            System.out.println("No data items specified...");
        throw new ServletException("No data items specified...");
    }

        // remove the chart data from session now that chart has been rendered.
        session.removeAttribute(id);

    // maximum data value
    int maxDataValue = 0;
    // maximum label width
    int maxLabelWidth = 0;
    // space between bars
    int barSpacing = 10;
    // width of each bar
    int barWidth = 0;
    // x,y coordinates
    int cx, cy;
    // number of chart items
    int columns = chartItems.length;
    int scale = 10;
        // an individual chart data item
    ChartItem chartItem = null;
    String label = null;
    int value = 0;

        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bi.createGraphics();
        Font titleFont = new java.awt.Font("Courier", Font.BOLD, 12);
        FontMetrics titleFontMetrics = g2d.getFontMetrics(titleFont);

    // loop through and figure out the the widest item label, as well as
    // the maximum value.
        for (int i=0; i < columns; i++) {
        chartItem = chartItems[i];
        label = chartItem.getLabel();
        value = chartItem.getValue();
        if (value > maxDataValue) {
            maxDataValue = value;
        }
        maxLabelWidth = Math.max(titleFontMetrics.stringWidth(label), maxLabelWidth);
    }

    // calculate chart dimensions
    int[] xcoords = new int[columns];
    int[] ycoords = new int[columns];
    int totalWidth = 0;
    int totalHeight = 0;
    for (int i=0; i < columns; i++) {
        switch (orientation) {
          case VERTICAL:
          default:
                barWidth = maxLabelWidth;
        cx = (Math.max((barWidth + barSpacing),maxLabelWidth) * i) +
            barSpacing;
        totalWidth = cx + (4 * titleFont.getSize());
        break;
          case HORIZONTAL:
        barWidth = titleFont.getSize();
        cy = ((barWidth + barSpacing) * i) + barSpacing;
        totalHeight = cy + (4 * titleFont.getSize());
        break;
        }
    }
    if (orientation == VERTICAL) {
            totalHeight = maxDataValue + (8 * titleFont.getSize());
        totalWidth = totalWidth + 50;
    } else {
        totalWidth = maxDataValue + (4 * titleFont.getSize() +
        (Integer.toString(maxDataValue).length() * titleFont.getSize())+50);
    }

    // Make sure the the total height of the chart provides enough room
    // for the vertical label..
    //
    int yLabelHeight = 0;
    for (int i=0; i<yLabel.length(); i++) {
        yLabelHeight += titleFontMetrics.getAscent();
    }
    if ((yLabelHeight+(12 * titleFontMetrics.getDescent())) > totalHeight) {
        totalHeight = yLabelHeight+(8*titleFont.getSize());
    }


        bi = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_INT_RGB);
        g2d = bi.createGraphics();
        titleFontMetrics = g2d.getFontMetrics(titleFont);

    // graph dimensions
    Dimension graphDim = new Dimension(totalWidth,totalHeight);
        Rectangle graphRect = new Rectangle(graphDim);

    // border dimensions
    Dimension borderDim = new Dimension(totalWidth-2,totalHeight-2);
        Rectangle borderRect = new Rectangle(borderDim);

    // background color
    g2d.setColor(Color.white);
    g2d.fill(graphRect);

    // draw border
    g2d.setColor(Color.black);
    borderRect.setLocation(1,1);
        g2d.draw(borderRect);

    // draw the title centered at the bottom of the bar graph
    int i = titleFontMetrics.stringWidth(title);
    g2d.setFont(titleFont);
    g2d.setColor(Color.black);
    g2d.drawString(title, Math.max((totalWidth - i)/2, 0),
        totalHeight - titleFontMetrics.getDescent());

    // draw the x axis label
    i = titleFontMetrics.stringWidth(xLabel);
    g2d.drawString(xLabel, Math.max((totalWidth - i)/2, 0),
        totalHeight - (6 * titleFontMetrics.getDescent()));

    // draw the y axis label
    i = titleFontMetrics.stringWidth(yLabel);
    cx = totalWidth-(totalWidth-6);
    cy = totalHeight - (12 * titleFontMetrics.getDescent());
    for (int j=yLabel.length(); j>0; j--) {
        g2d.drawString(yLabel.substring(j-1,j), cx, cy);
        cy -= titleFontMetrics.getAscent();
    }

    // loop through to draw the chart items.
        for (i=0; i < columns; i++) {
        chartItem = chartItems[i];
        label = chartItem.getLabel();
        value = chartItem.getValue();
        String colorStr = chartItem.getColor();

        Object color = getColor(colorStr);
        switch (orientation) {
          case VERTICAL:
          default:
                barWidth = maxLabelWidth;
        // set the next X coordinate to account for the label
        // being wider than the bar width.
        cx = (Math.max((barWidth + barSpacing),maxLabelWidth) * i) +
            barSpacing + 12;

        // center the bar chart
        cx += Math.max((totalWidth - (columns * (barWidth +
            (2 * barSpacing))))/2,0);

        // set the next Y coordinate to account for the height
        // of the bar as well as the title and labels painted
        // at the bottom of the chart.
        cy = totalHeight - (value) - 1 - (2 * titleFont.getSize());

        // draw the label
        g2d.setColor(Color.black);
        g2d.drawString((String)label, cx,
            totalHeight - titleFont.getSize() - (8 * titleFontMetrics.getDescent()));

        // draw the shadow bar
        if (color == Color.black) {
            g2d.setColor(Color.gray);
        }
        g2d.fillRect(cx + 5, cy - 28, barWidth,  (value));
        // draw the bar with the specified color
        g2d.setColor((Color)(color));
                g2d.fillRect(cx, cy - 30, barWidth, (value));
                g2d.drawString("" + value, cx, cy - 30 - titleFontMetrics.getDescent());
        break;
          case HORIZONTAL:
        barWidth = titleFont.getSize();
        // set the Y coordinate
            cy = totalHeight - (((barWidth + barSpacing) * i) + barSpacing +
            (12 * titleFontMetrics.getDescent()));


        // set the X coordinate to be the width of the widest label
        cx = maxLabelWidth + 1;

        cx += Math.max((totalWidth - (maxLabelWidth + 1 +
                titleFontMetrics.stringWidth("" + maxDataValue) +
                    (maxDataValue))) / 2, 0);
        // draw the labels and the shadow
        g2d.setColor(Color.black);
        g2d.drawString((String)label, cx - maxLabelWidth - 1,
                 cy + titleFontMetrics.getAscent());
        if (color == Color.black) {
            g2d.setColor(Color.gray);
        }
        g2d.fillRect(cx + 3, cy + 5, (value), barWidth);

        // draw the bar in the current color
        g2d.setColor((Color)(color));
                g2d.fillRect(cx, cy, (value), barWidth);
                g2d.drawString("" + value, cx + (value ) + 3,
                    cy + titleFontMetrics.getAscent());
        break;
        }
    }
        OutputStream output = response.getOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output);
        encoder.encode(bi);
        output.close();
    }

    /**
     * <p> Generate a pie chart from data.
     *
     * @param request The servlet request we are processing
     * @param response The servlet response we are creating
     *
     * @exception IOException if an input/output error occurs during processing
     * @exception ServletException if a servlet error occurs during processing
     */
    private void generatePieChart(HttpServletRequest request,
                          HttpServletResponse response)
        throws IOException, ServletException {
        response.setContentType("image/jpeg");

    // get chart parameters
        String id = request.getParameter("chartId");
    String title = request.getParameter("title");
    if (title == null) {
        title = "Chart";
    }

    // label for x/y axis
    String xLabel = request.getParameter("xlabel");
    String yLabel = request.getParameter("ylabel");

    // default image size
    int width = 400;
    int height = 200;
    String widthStr = request.getParameter("width");
    String heightStr = request.getParameter("height");
    if (widthStr != null) {
        width = Integer.parseInt(widthStr);
    }
    if (heightStr != null) {
        height = Integer.parseInt(heightStr);
    }

    // get an array of chart items containing our data..
        HttpSession session = request.getSession();
    ChartItem[] chartItems = (ChartItem[])session.getAttribute(id);
    if (chartItems == null) {
            System.out.println("No data items specified...");
        throw new ServletException("No data items specified...");
    }

        // remove the chart data from session now that chart has been rendered.
        session.removeAttribute(id);

        // begin pie chart
        Color dropShadow = new Color(240,240,240);
        //inner padding to make sure bars never touch the outer border
        int innerOffset = 20;

        int pieHeight = height - (innerOffset * 2);
        int pieWidth =  pieHeight;
        int halfWidth = width/2;

        //Width of the inner graphable area
        int innerWidth = width - (innerOffset * 2);

        //graph dimension
        Dimension graphDim = new Dimension(width, height);
        Rectangle graphRect = new Rectangle(graphDim);

        //border dimensions
        Dimension borderDim = new Dimension(halfWidth-2,height-2);
        Rectangle borderRect = new Rectangle(borderDim);

        //Set content type
        response.setContentType("image/jpeg");

        //Create BufferedImage & Graphics2D
        BufferedImage bi = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bi.createGraphics();

        // Set Antialiasing
        RenderingHints renderHints =
            new RenderingHints(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHints(renderHints);

        //Set graph background color to white:
        g2d.setColor(Color.white);
        g2d.fill(graphRect);

        //Draw black border
        g2d.setColor(Color.black);
        borderRect.setLocation(1,1);
        g2d.draw(borderRect);

        //Now draw border for legend
        borderRect.setLocation((width/2) + 1,1);
        g2d.draw(borderRect);

        //Draw data onto the graph:
        int x_pie = innerOffset;
        int y_pie = innerOffset;
        int border = 20;

        //Main chart Ellipse
        Ellipse2D.Double elb = new Ellipse2D.Double(x_pie - border/2,
            y_pie - border/2, pieWidth + border, pieHeight + border);
        //Shadow
        g2d.setColor(dropShadow);
        g2d.fill(elb);

        //Border
        g2d.setColor(Color.black);
        g2d.draw(elb);

        // Calculate the total value so that the pies can be calculated.
        float yTotal = 0.0f;
        int lastElement = 0;
        for(int i=0; i<chartItems.length; i++) {
           int ycoord = chartItems[i].getValue();
           if(ycoord > 0.0f) {
               yTotal += ycoord;
               lastElement = i;
          }
        }

        // Draw the pie chart
        int startAngle = 0;

        //Legend variables
        int legendWidth = 20;
        int x_legendText = halfWidth + innerOffset/2 + legendWidth + 5;
        int x_legendBar = halfWidth + innerOffset/2;
        int textHeight = 20;
        int curElement = 0;
        int y_legend = 0;

        //Dimensions of the legend bar
        Dimension legendDim = new Dimension(legendWidth , textHeight/2);
        Rectangle legendRect = new Rectangle(legendDim);
        for(int i=0; i< chartItems.length; i++) {
            int ycoord = chartItems[i].getValue();
            if(ycoord > 0.0f) {
                //Calculate percentage sales
                float perc = (ycoord/yTotal);
                //Calculate new angle
                int sweepAngle = (int)(perc * 360);
                //Check that the last element goes back to 0 position
                if (i == lastElement) {sweepAngle = 360-startAngle;}
                // Draw Arc
                g2d.setColor(getColor(chartItems[i].getColor()));
                g2d.fillArc(x_pie, y_pie, pieWidth, pieHeight, startAngle,
                        sweepAngle);
                //Increment startAngle with the sweepAngle
                startAngle += sweepAngle;

                //Draw Legend
                //Set y position for bar
                y_legend = curElement * textHeight + innerOffset;
                //Display the current column
                String display = chartItems[i].getLabel();
                g2d.setColor(Color.black);
                g2d.drawString(display, x_legendText, y_legend);
                //Display the total sales
                display = "" + ycoord;
                g2d.setColor(Color.black);
                g2d.drawString(display, x_legendText + 80, y_legend);
                //Display the sales percentage
                display = "  (" + (int)(perc*100) + "%)";
                g2d.setColor(Color.red);
                g2d.drawString(display, x_legendText + 110, y_legend);
                //Draw the bar
                g2d.setColor(getColor(chartItems[i].getColor()));
                legendRect.setLocation(x_legendBar,y_legend - textHeight/2);
                g2d.fill(legendRect);
                //Increment
                curElement++;
            }
        }
        // Encode the graph
        OutputStream output = response.getOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output);
        encoder.encode(bi);
        output.close();
    }

    /**
     * Returns the Color instance corresponding the color passed in.
     *
     * @param colorStr a string representing a color instance.
     * @return Color instance corresponding to the input color.
     */
    protected Color getColor(String colorStr) {
        Color color = null;
    if (colorStr == null) {
            color = Color.gray;
        }
        if (colorStr.equals("red")) {
            color = Color.red;
        } else if (colorStr.equals("green")) {
            color = Color.green;
        } else if (colorStr.equals("blue")) {
            color = Color.blue;
        } else if (colorStr.equals("pink")) {
            color = Color.pink;
        } else if (colorStr.equals("orange")) {
            color = Color.orange;
        } else if (colorStr.equals("magenta")) {
            color = Color.magenta;
        } else if (colorStr.equals("cyan")) {
            color = Color.cyan;
        } else if (colorStr.equals("white")) {
            color = Color.white;
        } else if (colorStr.equals("yellow")) {
            color = Color.yellow;
        } else if (colorStr.equals("gray")) {
            color = Color.gray;
        } else if (colorStr.equals("darkGray")) {
            color = Color.darkGray;
        } else {
            color = Color.gray;
        }
        return color;
    }
}
