/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2007 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $$Id: GraphUtils.java 15428 2008-10-07 11:20:29Z sauthieg $$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.webapp.jonasadmin.monitoring.graph.utils;

import java.awt.Color;
import java.awt.Graphics;

public class GraphUtils {
    public  final static int DEF_SIZE_TABLE_MEASURES = 120;
    public final static int DEF_RANGE = 10;
    //this index will be increased when getting a memory value from proxy mandatory
    public static final int DEF_NUM_MESURE = 120;

    public static final int HEIGHT = 180;
    public static final int TOP_MARGIN = 35;
    public static final int RIGHT_MARGIN = 80;
    public static final int BOTTOM_MARGIN = 2;
    public static final int LEFT_MARGIN = 70;
    public static final int HORIZONTAL_SPACE = 30;

    public static final int Y_LENGTH = HEIGHT - TOP_MARGIN - BOTTOM_MARGIN; // the graph height
    public static final int GAUGE_WIDTH = 10;

    public static final Color BG_COLOR = new Color(0x006699);
    public static final Color FG_COLOR = Color.white;
    public static final Color GRAPHICS_BG_COLOR = Color.lightGray;
    public static final Color GAUGE_FG_COLOR = new Color(0x2A7FFF);
    public static final Color GRAPHICS_FG_COLOR = Color.darkGray;
    public static final Color AXIS_COLOR = Color.white;
    public static final Color TEXT_COLOR = Color.white;
    public static final Color HORIZONTAL_LINE_COLOR = new Color(0x006699);
    //space between lines of the graph
    public static final int DEF_SPACE_BETWEEN_LINES = 4;
    public static final int GAUGE_TEXT_MAX_LENGTH = 20;
    public static final int GRAPHIC_SEPARATOR = 5;


    /**
     * @param length the data array size (data.length)
     * @return the picture width when displaying an array of the specified size
     */
    public synchronized static int getWidth(int length) {
        return LEFT_MARGIN + 2 * length + HORIZONTAL_SPACE + GAUGE_WIDTH + RIGHT_MARGIN;
    }

    /**
     * @return the picture height
     */
    public synchronized static int getHeight() {
        return HEIGHT;
    }

    public synchronized static int cartesianXToGraphicsX(int x) {
        return x + LEFT_MARGIN;
    }

    /**
     *
     * @param y the value to convert into cartesian
     * @param factor represents the graph rank on the image stream
     * @return cartesian value of first parameter.
     */

    public synchronized static int cartesianYToGraphicsY(int y, int factor) {
        if (factor == 1) {
            return HEIGHT - 2 - y - BOTTOM_MARGIN;
        }
        return (HEIGHT * factor + GRAPHIC_SEPARATOR) - 2 - y - BOTTOM_MARGIN;
    }
    /**
     * Draw main monitoring Graph
     * @param g the graphic (contained in the servlet image)
     * @param k used when
     * @param xLength 2*monitored data number
     * @param width Graph width, depends on xLength
     * @param pow = 10^n
     * @param n
     * @param data datas to draw
     * @param maxExpectedValue over this value, current measured value is considered critical
     */

    public synchronized static void drawGraph(Graphics g, long k, int xLength, int width, int pow ,int n, int index, Long[] data, Long maxExpectedValue, String graphTitle, String meausreUnit, int graphRank) {
        // fill the image background:
        g.setColor(BG_COLOR);
        g.fillRect(0, 0, width, HEIGHT);
        // firstly, the memory used history:
        // draw the chart area:
        g.setColor(GRAPHICS_BG_COLOR);
        //    g.fillRect(cartesianXToGraphicsX(0), cartesianYToGraphicsY(Y_LENGTH), xLength - 1, Y_LENGTH);
        g.fill3DRect(cartesianXToGraphicsX(0), cartesianYToGraphicsY(Y_LENGTH, graphRank), xLength - 1, Y_LENGTH, true);
        for (int i = 1; i <= k; i++) {
            int y = (new Long(i * Y_LENGTH / (k + 1))).intValue();
            g.setColor(FG_COLOR);
            g.drawLine(cartesianXToGraphicsX( -3), cartesianYToGraphicsY(y, graphRank)
                    , cartesianXToGraphicsX(xLength), cartesianYToGraphicsY(y, graphRank));
            g.setColor(TEXT_COLOR);
            g.drawString("" + (i * pow), cartesianXToGraphicsX( -18 - n * 6)
                    , cartesianYToGraphicsY(y - 5, graphRank));
        }
        // draw the values:
        int xLineBottom = 0;
        int xLineTop = 0;
        int yLineBottom = 0;
        int yLineTop = 0;

        int xLineTopPrevious = 0;
        int yLineTopPrevious = 0;

        for (int i = 0; i < index; i++) {
            int y = (new Long(data[i].longValue() * Y_LENGTH / ((k + 1) * pow))).intValue();
            //draw vertical line
            g.setColor(Color.green);
            xLineBottom = GraphUtils.cartesianXToGraphicsX(DEF_SPACE_BETWEEN_LINES * i);
            yLineBottom =  GraphUtils.cartesianYToGraphicsY(0, graphRank);
            xLineTop = GraphUtils.cartesianXToGraphicsX(DEF_SPACE_BETWEEN_LINES * i);
            yLineTop = GraphUtils.cartesianYToGraphicsY(y, graphRank);
            g.drawLine(xLineBottom, yLineBottom
                    , xLineTop, yLineTop);
            if (i != 0) {
                //draw horizontal line
                g.setColor(HORIZONTAL_LINE_COLOR);
                g.drawLine( xLineTopPrevious, yLineTopPrevious
                        , xLineTop, yLineTop);
            }
            xLineTopPrevious = xLineTop;
            yLineTopPrevious = yLineTop;
        }

        g.setColor(TEXT_COLOR);
        g.drawString(graphTitle, cartesianXToGraphicsX(0)
                , cartesianYToGraphicsY(Y_LENGTH + 20, graphRank));
        g.drawString(meausreUnit, cartesianXToGraphicsX(0), cartesianYToGraphicsY(Y_LENGTH + 10, graphRank));
        g.drawString("0", cartesianXToGraphicsX( -12), cartesianYToGraphicsY( -5, graphRank));
        g.setColor(AXIS_COLOR);
        g.drawLine(cartesianXToGraphicsX( -3), cartesianYToGraphicsY(0, graphRank)
                , cartesianXToGraphicsX(xLength), cartesianYToGraphicsY(0, graphRank));
        g.drawLine(cartesianXToGraphicsX( -1), cartesianYToGraphicsY(0, graphRank), cartesianXToGraphicsX( -1)
                , cartesianYToGraphicsY(Y_LENGTH, graphRank));
        g.drawLine(cartesianXToGraphicsX(xLength - 2), cartesianYToGraphicsY(0, graphRank)
                , cartesianXToGraphicsX(xLength - 2), cartesianYToGraphicsY(Y_LENGTH, graphRank));



    }

    /**
     * Draw a box on right of monitoring graph to show current used value
     * compared to total value
     * @param g The main graphic. The drawn box will be added in this graphic
     * @param currentUsed current used value of a given measure
     * @param total total used value of a measure
     * @param xLength width of the box
     * @param usedLabel label to display for currentUsed value
     * @param unit measure unit (e.g MB for memory measure)
     * @param compareWithTotal if true then the graph will display comparison betxeen current and total value
     */

    public synchronized static  void drawCurrentUsedPerTotal(Graphics g, Long currentUsed, Long total, int xLength, String usedLabel, String unit, boolean compareWithTotal, int graphRank) {
        int xGauge = LEFT_MARGIN + xLength + HORIZONTAL_SPACE;

        g.setColor(GRAPHICS_BG_COLOR);
        g.fillRect(xGauge, cartesianYToGraphicsY(Y_LENGTH, graphRank), GAUGE_WIDTH, Y_LENGTH);


        int y = 0;
        g.setColor(GAUGE_FG_COLOR);
        if (compareWithTotal) {
            if (total != 0) {
                y = (new Long(currentUsed * Y_LENGTH / total)).intValue();
                //to avoid division by zero
            }
            g.fillRect(xGauge, cartesianYToGraphicsY(y, graphRank), GAUGE_WIDTH, y);
            g.setColor(AXIS_COLOR);
            g.drawRect(xGauge, cartesianYToGraphicsY(Y_LENGTH, graphRank), GAUGE_WIDTH, Y_LENGTH);

            g.setColor(TEXT_COLOR);
            g.drawString("0", xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY( -7, graphRank));
            g.drawString("" + currentUsed, xGauge + GAUGE_WIDTH + 3
                    , cartesianYToGraphicsY(Math.min(y - 5, Y_LENGTH - 25), graphRank));
            g.drawString("(current)", xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY(Math.min(y - 15
                    , Y_LENGTH - 35), graphRank));
            g.drawString("" + total, xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY(Y_LENGTH - 5, graphRank));
            g.drawString("(total)", xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY(Y_LENGTH - 15, graphRank));
            g.drawString(usedLabel, xGauge, cartesianYToGraphicsY(Y_LENGTH + 20, graphRank));
            g.drawString(unit, xGauge, cartesianYToGraphicsY(Y_LENGTH + 10, graphRank));
        } else {
            //Don't draw the graph comparison between current and total value
            y = (new Long(Y_LENGTH )).intValue();
            g.fillRect(xGauge, cartesianYToGraphicsY(y, graphRank), GAUGE_WIDTH, y);
            g.setColor(AXIS_COLOR);
            g.drawRect(xGauge, cartesianYToGraphicsY(Y_LENGTH, graphRank), GAUGE_WIDTH, Y_LENGTH);

            g.setColor(TEXT_COLOR);
            g.drawString("0", xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY( -7, graphRank));
            g.drawString("" + currentUsed, xGauge + GAUGE_WIDTH + 3
                    , cartesianYToGraphicsY(Math.min(y - 5, Y_LENGTH - 25), graphRank));
            g.drawString("(current)", xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY(Math.min(y - 15
                    , Y_LENGTH - 35), graphRank));
            g.drawString("" , xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY(Y_LENGTH - 5, graphRank));
            g.drawString("", xGauge + GAUGE_WIDTH + 3, cartesianYToGraphicsY(Y_LENGTH - 15, graphRank));
            g.drawString(usedLabel, xGauge, cartesianYToGraphicsY(Y_LENGTH + 20, graphRank));
            g.drawString(unit, xGauge, cartesianYToGraphicsY(Y_LENGTH + 10, graphRank));
        }


    }


}
