/*

   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.batik.util.gui;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.apache.batik.util.gui.resource.ActionMap;
import org.apache.batik.util.gui.resource.ButtonFactory;
import org.apache.batik.util.gui.resource.MissingListenerException;
import org.apache.batik.util.resources.ResourceManager;

/**
 * This class contains a collection of components that can be used to
 * track and display the memory usage.
 *
 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
 * @version $Id$
 */
public class MemoryMonitor extends JFrame implements ActionMap {
    /**
     * The resource file name
     */
    protected static final String RESOURCE =
        "org.apache.batik.util.gui.resources.MemoryMonitorMessages";

    /**
     * The resource bundle
     */
    protected static ResourceBundle bundle;

    /**
     * The resource manager
     */
    protected static ResourceManager resources;

    static {
        bundle = ResourceBundle.getBundle(RESOURCE, Locale.getDefault());
        resources = new ResourceManager(bundle);
    }

    /**
     * The map that contains the listeners
     */
    protected Map listeners = new HashMap();

    /**
     * The Panel instance.
     */
    protected Panel panel;

    /**
     * Creates a new memory monitor frame.
     * The time beetween two repaints is 1s.
     */
    public MemoryMonitor() {
        this(1000);
    }

    /**
     * Creates a new memory monitor frame.
     * @param time The time beetween two repaints in ms.
     */
    public MemoryMonitor(long time) {
        super(resources.getString("Frame.title"));
        listeners.put("CollectButtonAction", new CollectButtonAction());
        listeners.put("CloseButtonAction", new CloseButtonAction());

        panel = new Panel(time);

        getContentPane().add(panel);
        panel.setBorder(BorderFactory.createTitledBorder
                        (BorderFactory.createEtchedBorder(),
                         resources.getString("Frame.border_title")));

        JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        ButtonFactory bf = new ButtonFactory(bundle, this);
        p.add(bf.createJButton("CollectButton"));
        p.add(bf.createJButton("CloseButton"));
        getContentPane().add( p, BorderLayout.SOUTH );

        pack();

        addWindowListener(new WindowAdapter() {
            public void windowActivated(WindowEvent e) {
                RepaintThread t = panel.getRepaintThread();
                if (!t.isAlive()) {
                    t.start();
                } else {
                    t.safeResume();
                }
            }
            public void windowClosing(WindowEvent ev) {
                panel.getRepaintThread().safeSuspend();
            }
            public void windowDeiconified(WindowEvent e) {
                panel.getRepaintThread().safeResume();
            }
            public void windowIconified(WindowEvent e) {
                panel.getRepaintThread().safeSuspend();
            }
        });
    }

    // ActionMap implementation

    /**
     * Returns the action associated with the given string
     * or null on error
     * @param key the key mapped with the action to get
     * @throws MissingListenerException if the action is not found
     */
    public Action getAction(String key) throws MissingListenerException {
        return (Action)listeners.get(key);
    }

    /**
     * The action associated with the 'Collect' button of the memory monitor.
     */
    protected class CollectButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
            System.gc();
        }
    }

    /**
     * The action associated with the 'Close' button of the memory monitor.
     */
    protected class CloseButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
            panel.getRepaintThread().safeSuspend();
            dispose();
        }
    }

    /**
     * A panel composed of a Usage instance and a History instance.
     */
    public static class Panel extends JPanel {
        /**
         * The repaint thread.
         */
        protected RepaintThread repaintThread;

        /**
         * Creates a new memory monitor panel, composed of a Usage instance
         * and a History instance.
         * The time beetween two repaints is 1s.
         */
        public Panel() {
            this(1000);
        }

        /**
         * Creates a new memory monitor panel, composed of a Usage instance
         * and a History instance.
         * The repaint thread must be started by hands.
         * @param time The time beetween two repaints in ms.
         */
        public Panel(long time) {
            super(new GridBagLayout());

            ExtendedGridBagConstraints constraints
                = new ExtendedGridBagConstraints();
            constraints.insets = new Insets(5, 5, 5, 5);

            List l = new ArrayList();
            JPanel p = new JPanel(new BorderLayout());
            p.setBorder(BorderFactory.createLoweredBevelBorder());
            JComponent c = new Usage();
            p.add(c);
            constraints.weightx = 0.3;
            constraints.weighty = 1;
            constraints.fill = GridBagConstraints.BOTH;
            constraints.setGridBounds(0, 0, 1, 1);
            add(p, constraints);
            l.add(c);

            p = new JPanel(new BorderLayout());
            p.setBorder(BorderFactory.createLoweredBevelBorder());
            c = new MemoryMonitor.History();
            p.add(c);
            constraints.weightx = 0.7;
            constraints.setGridBounds(1, 0, 1, 1);
            add(p, constraints);
            l.add(c);

            repaintThread = new RepaintThread(time, l);
        }

        /**
         * Returns the repaint thread.
         */
        public RepaintThread getRepaintThread() {
            return repaintThread;
        }
    }

    /**
     * Displays the current memory usage.
     */
    public static class Usage extends JPanel implements MemoryChangeListener {
        /**
         * The preferred width.
         */
        public static final int PREFERRED_WIDTH = 90;

        /**
         * The preferred height.
         */
        public static final int PREFERRED_HEIGHT = 100;

        /**
         * The units string.
         */
        protected static final String UNITS
            = resources.getString("Usage.units");

        /**
         * The total string.
         */
        protected static final String TOTAL
            = resources.getString("Usage.total");

        /**
         * The used string.
         */
        protected static final String USED
            = resources.getString("Usage.used");

        /**
         * The text position.
         */
        protected static final boolean POSTFIX
            = resources.getBoolean("Usage.postfix");

        /**
         * The font size.
         */
        protected static final int FONT_SIZE = 9;

        /**
         * The blocks margin.
         */
        protected static final int BLOCK_MARGIN = 10;

        /**
         * The number of blocks.
         */
        protected static final int BLOCKS = 15;

        /**
         * The blocks width.
         */
        protected static final double BLOCK_WIDTH =
            PREFERRED_WIDTH-BLOCK_MARGIN*2;

        /**
         * The blocks height.
         */
        protected static final double BLOCK_HEIGHT =
            ((double)PREFERRED_HEIGHT-(3*FONT_SIZE)-BLOCKS) / BLOCKS;

        /**
         * The blocks type.
         */
        protected static final int[] BLOCK_TYPE =
            { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2 };

        /**
         * The color of the used blocks for each block type.
         */
        protected Color[] usedColors = {
            Color.red,
            new Color(255, 165, 0),
            Color.green
        };

        /**
         * The color of the free blocks for each block type.
         */
        protected Color[] freeColors = {
            new Color(130, 0, 0),
            new Color(130, 90, 0),
            new Color(0, 130, 0)
        };

        /**
         * The font used to draw the strings.
         */
        protected Font font = new Font("SansSerif", Font.BOLD, FONT_SIZE);

        /**
         * The text color.
         */
        protected Color textColor = Color.green;

        /**
         * The total memory.
         */
        protected long totalMemory;

        /**
         * The free memory.
         */
        protected long freeMemory;

        /**
         * Creates a new Usage object.
         */
        public Usage() {
            this.setBackground(Color.black);
            setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));
        }

        /**
         * Indicates that the memory state has changed.
         * @param total The total amount of memory.
         * @param free  The free memory.
         */
        public void memoryStateChanged(long total, long free) {
            totalMemory = total;
            freeMemory  = free;
        }

        /**
         * Sets the text color.
         */
        public void setTextColor(Color c) {
            textColor = c;
        }

        /**
         * Sets the low used memory block color.
         */
        public void setLowUsedMemoryColor(Color c) {
            usedColors[2] = c;
        }

        /**
         * Sets the medium used memory block color.
         */
        public void setMediumUsedMemoryColor(Color c) {
            usedColors[1] = c;
        }

        /**
         * Sets the high used memory block color.
         */
        public void setHighUsedMemoryColor(Color c) {
            usedColors[0] = c;
        }

        /**
         * Sets the low free memory block color.
         */
        public void setLowFreeMemoryColor(Color c) {
            freeColors[2] = c;
        }

        /**
         * Sets the medium free memory block color.
         */
        public void setMediumFreeMemoryColor(Color c) {
            freeColors[1] = c;
        }

        /**
         * Sets the high free memory block color.
         */
        public void setHighFreeMemoryColor(Color c) {
            freeColors[0] = c;
        }

        /**
         * To paint the component.
         */
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;

            // Sets the transform
            Dimension dim = getSize();
            double sx = ((double)dim.width) / PREFERRED_WIDTH;
            double sy = ((double)dim.height) / PREFERRED_HEIGHT;
            g2d.transform(AffineTransform.getScaleInstance(sx, sy));

            // Turns the antialiasing on
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                 RenderingHints.VALUE_ANTIALIAS_ON);

            // Draw the memory blocks
            int nfree = (int)Math.round(((double)BLOCKS)
                                        * freeMemory / totalMemory);

            for (int i = 0; i < nfree; i++) {
                Rectangle2D rect = new Rectangle2D.Double(10,
                                                   i*BLOCK_HEIGHT+i+FONT_SIZE+5,
                                                          BLOCK_WIDTH,
                                                          BLOCK_HEIGHT);
                g2d.setPaint(freeColors[BLOCK_TYPE[i]]);
                g2d.fill(rect);
            }

            for (int i = nfree; i < 15; i++) {
                Rectangle2D rect = new Rectangle2D.Double(10,
                                                   i*BLOCK_HEIGHT+i+FONT_SIZE+5,
                                                          BLOCK_WIDTH,
                                                          BLOCK_HEIGHT);
                g2d.setPaint(usedColors[BLOCK_TYPE[i]]);
                g2d.fill(rect);
            }

            // Draw the memory usage text
            g2d.setPaint(textColor);
            g2d.setFont(font);

            long total = totalMemory / 1024;
            long used  = (totalMemory - freeMemory) / 1024;
            String totalText;
            String usedText;
            if (POSTFIX) {
                totalText = total + UNITS + " " + TOTAL;
                usedText  = used + UNITS + " " + USED;
            } else {
                totalText = TOTAL + " " + total + UNITS;
                usedText  = USED + " " + used + UNITS;
            }

            g2d.drawString(totalText, 10, 10);
            g2d.drawString(usedText, 10, PREFERRED_HEIGHT-3);
        }
    }

    /**
     * Displays the memory usage history in a chart.
     */
    public static class History extends JPanel implements MemoryChangeListener {
        /**
         * The preferred width.
         */
        public static final int PREFERRED_WIDTH = 200;

        /**
         * The preferred height.
         */
        public static final int PREFERRED_HEIGHT = 100;

        /**
         * The grid lines stroke.
         */
        protected static final Stroke GRID_LINES_STROKE = new BasicStroke(1);

        /**
         * The curve stroke.
         */
        protected static final Stroke CURVE_STROKE =
            new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);

        /**
         * The border stroke.
         */
        protected static final Stroke BORDER_STROKE = new BasicStroke(2);

        /**
         * The grid lines color.
         */
        protected Color gridLinesColor = new Color(0, 130, 0);

        /**
         * The curve color.
         */
        protected Color curveColor = Color.yellow;

        /**
         * The border color.
         */
        protected Color borderColor = Color.green;

        /**
         * The data.
         */
        protected List data = new LinkedList();

        /**
         * The vertical lines shift.
         */
        protected int xShift = 0;

        /**
         * The total memory.
         */
        protected long totalMemory;

        /**
         * The free memory.
         */
        protected long freeMemory;

        /**
         * The curve representation.
         */
        protected GeneralPath path = new GeneralPath();

        /**
         * Creates a new History object.
         */
        public History() {
            this.setBackground(Color.black);
            setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));
        }

        /**
         * Indicates that the memory state has changed.
         * @param total The total amount of memory.
         * @param free  The free memory.
         */
        public void memoryStateChanged(long total, long free) {
            totalMemory = total;
            freeMemory  = free;

            // Add a new point to the data
            data.add(totalMemory - freeMemory);
            if (data.size() > 190) {
                data.remove(0);
                xShift = (xShift + 1) % 10;
            }

            // Create the path that match the data
            Iterator it = data.iterator();
            GeneralPath p = new GeneralPath();
            long l = (Long) it.next();
            p.moveTo(5, ((float)(totalMemory - l) / totalMemory) * 80 + 10);
            int i = 6;
            while (it.hasNext()) {
                l = (Long) it.next();
                p.lineTo(i, ((float)(totalMemory - l) / totalMemory) * 80 + 10);
                i++;
            }
            path = p;
        }

        /**
         * To paint the component.
         */
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;

            // Turns the antialiasing on
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                                 RenderingHints.VALUE_ANTIALIAS_ON);

            // Sets the transform
            Dimension dim = getSize();
            double sx = ((double)dim.width) / PREFERRED_WIDTH;
            double sy = ((double)dim.height) / PREFERRED_HEIGHT;
            g2d.transform(AffineTransform.getScaleInstance(sx, sy));

            // The vertical lines
            g2d.setPaint(gridLinesColor);
            g2d.setStroke(GRID_LINES_STROKE);
            for (int i = 1; i < 20; i++) {
                int lx = i * 10 + 5 - xShift;
                g2d.draw(new Line2D.Double(lx, 5, lx, PREFERRED_HEIGHT - 5));
            }

            // The horizontal lines
            for (int i = 1; i < 9; i++) {
                int ly = i * 10 + 5;
                g2d.draw(new Line2D.Double(5, ly, PREFERRED_WIDTH - 5, ly));
            }

            // The curve.
            g2d.setPaint(curveColor);
            g2d.setStroke(CURVE_STROKE);

            g2d.draw(path);

            // The border
            g2d.setStroke(BORDER_STROKE);
            g2d.setPaint(borderColor);
            g2d.draw(new Rectangle2D.Double(5,
                                            5,
                                            PREFERRED_WIDTH - 10,
                                            PREFERRED_HEIGHT - 10));

        }
    }

    /**
     * This interface allows the RepaintThread to notify an object that the
     * current memory state has changed.
     */
    public interface MemoryChangeListener {
        /**
         * Indicates that the memory state has changed.
         * @param total The total amount of memory.
         * @param free  The free memory.
         */
        void memoryStateChanged(long total, long free);
    }

    /**
     * This thread repaints a list of components.
     */
    public static class RepaintThread extends Thread {
        /**
         * The repaint timeout
         */
        protected long timeout;

        /**
         * The components to repaint.
         */
        protected List components;

        /**
         * The runtime.
         */
        protected Runtime runtime = Runtime.getRuntime();

        /**
         * Whether or not the thread was supended.
         */
        protected boolean suspended;

        /**
         * Runnable for updating components.
         */
        protected UpdateRunnable updateRunnable;

        /**
         * Creates a new Thread.
         * @param timeout    The time between two repaint in ms.
         * @param components The components to repaint.
         */
        public RepaintThread(long timeout, List components) {
            this.timeout = timeout;
            this.components = components;
            this.updateRunnable = createUpdateRunnable();
            setPriority(Thread.MIN_PRIORITY);
        }

        /**
         * The thread main method.
         */
        public void run() {
            for (;;) {
                try {
                    synchronized (updateRunnable) { 
                        if (!updateRunnable.inEventQueue)
                            EventQueue.invokeLater(updateRunnable);
                        updateRunnable.inEventQueue = true; 
                    }
                    sleep(timeout);
                    synchronized(this) {
                        while (suspended) {
                            wait();
                        }
                    }
                } catch (InterruptedException e) {}
            }
        }

        protected UpdateRunnable createUpdateRunnable() {
            return new UpdateRunnable();
        }

        protected class UpdateRunnable implements Runnable {
            public boolean inEventQueue = false;
            public void run() {
                long free  = runtime.freeMemory();
                long total = runtime.totalMemory();
                for (Object component : components) {
                    Component c = (Component) component;
                    ((MemoryChangeListener) c).memoryStateChanged(total, free);
                    c.repaint();
                }
                synchronized (this) { inEventQueue = false; }
            }
        }

        /**
         * Suspends the thread.
         */
        public synchronized void safeSuspend() {
            if (!suspended) {
                suspended = true;
            }
        }

        /**
         * Resumes the thread.
         */
        public synchronized void safeResume() {
            if (suspended) {
                suspended = false;
                notify();
            }
        }
    }
}
