/*
 * jNPad v0.3 - jNPad's an Simple Text Editor written in Java
 *
 * Copyright (C) 2014-2017  rgs
 *
 * Require JDK 1.6 (or later)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program 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 General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 *
 * Info, Questions, Suggestions & Bugs Report to rgsevero@gmail.com
 */

package jnpad.ui.status;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

import jnpad.GUIUtilities;
import jnpad.JNPadBundle;
import jnpad.ui.JNPadMenuItem;
import jnpad.ui.plaf.LAFUtils;
import jnpad.util.Utilities;

/**
 * The Class HeapMonitor.
 *
 * @version 0.3
 * @since   jNPad v0.1
 */
public class HeapMonitor extends JComponent {
  JPopupMenu                    popupMenu         = new JPopupMenu();
  JNPadMenuItem                 miCleaningMemory  = new JNPadMenuItem(JNPadBundle.getString("HeapMonitor.cleaningMemory.text"), //$NON-NLS-1$
                                                      GUIUtilities.loadIcon("gc.png"));        //$NON-NLS-1$
  JNPadMenuItem                 miHideHeapMonitor = new JNPadMenuItem(JNPadBundle.getString("HeapMonitor.hide.text"), //$NON-NLS-1$
                                                      GUIUtilities.loadIcon("java-close.png")); //$NON-NLS-1$

  // % umbrales para los cambios de color de la barra
  private static final int      ORANGE_THRESHOLD  = 70;
  private static final int      RED_THRESHOLD     = 90;

  private static final Color    ORANGE;
  private static final Color    RED;

  private static final long     M                 = 1024 * 1024;

  private long                  total;
  private long                  used;

  private IHeapMonitorStatusBar statusBar;

  /** UID */
  private static final long     serialVersionUID  = 3548053449964476421L;
  
  static {
    if (LAFUtils.isDarkLAF()) {
      ORANGE = new Color(139, 90, 0);
      RED = new Color(139, 0, 0);
    }
    else {
      ORANGE = new Color(255, 190, 125);
      RED = new Color(255, 70, 70);
    }
  }
  
  /**
   * Instantiates a new heap monitor.
   *
   * @param statusBar IHeapMonitorStatusBar
   */
  public HeapMonitor(IHeapMonitorStatusBar statusBar) {
    this.statusBar = statusBar;

    setPreferredSize(new Dimension(200, 1));

    updateStats();

    Timer timer = new Timer(1000, new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        updateStats();
        repaint();
      }
    });
    timer.start();

    popupMenu.add(miCleaningMemory);
    popupMenu.addSeparator();
    popupMenu.add(miHideHeapMonitor);
    
    miCleaningMemory.setDescription(JNPadBundle.getString("HeapMonitor.cleaningMemory.description")); //$NON-NLS-1$
    miHideHeapMonitor.setDescription(JNPadBundle.getString("HeapMonitor.hide.description")); //$NON-NLS-1$

    miCleaningMemory.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        Utilities.gc();
      }
    });

    miHideHeapMonitor.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        HeapMonitor.this.statusBar.showHeapMonitor(false);
      }
    });
  }

  /**
   * Gets the minimum size.
   *
   * @return Dimension
   * @see javax.swing.JComponent#getMinimumSize()
   */
  @Override
  public Dimension getMinimumSize() {
    return new Dimension(0, 0);
  }


  /**
   * Process mouse event.
   *
   * @param e the e
   * @see javax.swing.JComponent#processMouseEvent(java.awt.event.MouseEvent)
   */
  @Override
  protected void processMouseEvent(MouseEvent e) {
    super.processMouseEvent(e);
    if (e.getID() == MouseEvent.MOUSE_PRESSED && SwingUtilities.isRightMouseButton(e)) {
      SwingUtilities.updateComponentTreeUI(popupMenu);
      popupMenu.pack();
      popupMenu.show(e.getComponent(), e.getX(), e.getY());
    }
  }

  /**
   * Paint.
   *
   * @param g Graphics
   * @see javax.swing.JComponent#paint(java.awt.Graphics)
   */
  @Override
  public void paint(Graphics g) {
    Rectangle bounds = getBounds();
    int usedX = (int) (used * bounds.width / total);
    int warnX = ORANGE_THRESHOLD * bounds.width / 100;
    int dangerX = RED_THRESHOLD * bounds.width / 100;

    final Color savedColor = g.getColor();

    g.setColor(LAFUtils.isDarkLAF() ? getBackground().brighter() : getBackground().darker());
    g.fillRect(0, 0, Math.min(usedX, warnX), bounds.height);

    g.setColor(ORANGE);
    g.fillRect(warnX, 0,
               Math.min(usedX - warnX, dangerX - warnX),
               bounds.height);

    g.setColor(RED);
    g.fillRect(dangerX, 0,
               Math.min(usedX - dangerX, bounds.width - dangerX),
               bounds.height);

    g.setColor(getForeground());
    
    String s = JNPadBundle.getString("HeapMonitor.label", (used / M), (total / M)); //$NON-NLS-1$

    int x = (bounds.width - g.getFontMetrics().stringWidth(s)) / 2;
    int y = (bounds.height + g.getFontMetrics().getHeight()) / 2;
    g.drawString(s, x, y - 2);

    g.setColor(savedColor);
  }

  /**
   * Update stats.
   */
  private void updateStats() {
    long free = Runtime.getRuntime().freeMemory();
    total = Runtime.getRuntime().totalMemory();
    long max = Runtime.getRuntime().maxMemory();
    used  = total - free;

    String tip = JNPadBundle.getString("HeapMonitor.tooltip", (used * 100 / total), (used / M), (total / M), (max / M)); //$NON-NLS-1$

    setToolTipText(tip);
  }

} // fin de la clase HeapMonitor

