/*
 * Copyright (c) 2007-2010 by The Broad Institute, Inc. and the Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * This software is licensed under the terms of the GNU Lesser General Public License (LGPL), Version 2.1 which
 * is available at http://www.opensource.org/licenses/lgpl-2.1.php.
 *
 * THE SOFTWARE IS PROVIDED "AS IS." THE BROAD AND MIT MAKE NO REPRESENTATIONS OR WARRANTIES OF
 * ANY KIND CONCERNING THE SOFTWARE, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT
 * OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE.  IN NO EVENT SHALL THE BROAD OR MIT, OR THEIR
 * RESPECTIVE TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES, AND AFFILIATES BE LIABLE FOR ANY DAMAGES OF
 * ANY KIND, INCLUDING, WITHOUT LIMITATION, INCIDENTAL OR CONSEQUENTIAL DAMAGES, ECONOMIC
 * DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER THE BROAD OR MIT SHALL
 * BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE
 * FOREGOING.
 */


/*
* LocationPanel.java
*
* Created on September 11, 2007, 2:29 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.broad.igv.ui.panel;

//~--- non-JDK imports --------------------------------------------------------

import org.broad.igv.Globals;
import org.broad.igv.feature.Chromosome;
import org.broad.igv.feature.Cytoband;
import org.broad.igv.renderer.CytobandRenderer;
import org.broad.igv.session.ViewContext;
import org.broad.igv.ui.FontManager;
import org.broad.igv.ui.WaitCursorManager;
import org.broad.igv.util.LongRunningTask;
import org.broad.igv.util.NamedRunnable;

import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;

/**
 * @author jrobinso
 */
public class CytobandPanel extends JPanel {

    private static int fontHeight = 10;
    private static int bandHeight = 10;
    private static String fontFamilyName = "Lucida Sans";
    private boolean isDragging = false;
    private double viewOrigin;
    double cytobandScale;

    /**
     * Creates a new instance of LocationPanel
     */
    public CytobandPanel() {

        FontManager.getScalableFont(fontHeight);
        this.setFont(new Font(fontFamilyName, Font.BOLD, fontHeight));


        // TODO SwingUtilities2 is not compatible with 1.6
        // this.putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, new Boolean(true));
        initialize();


    }

    /**
     * The panel is divided into 2 regions. (1) the cytoband itself, and 2)
     * location ellipsis
     */
    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);

        if (getViewContext().getChrName().equals(Globals.CHR_ALL)) {
            Graphics g2 = g.create();
            g2.setFont(FontManager.getScalableFont(Font.ITALIC, 12));
            String text = "Whole genome view.  To jump to a chromosome click on its label.";
            g2.drawString(text, 20, getHeight() - 5);
            return;
        }

        int dataPanelWidth = getWidth(); //getViewContext().getDataPanelWidth();
        Rectangle cytoRect = new Rectangle(0, 10, dataPanelWidth, bandHeight);

        Chromosome chromosome = getViewContext().getChromosome();
        if (chromosome == null) {
            return;
        }
        java.util.List<Cytoband> cytobands = chromosome.getCytobands();
        if (cytobands == null) {
            return;
        }
        (new CytobandRenderer()).draw(cytobands, g, cytoRect);

        int chromosomeLength = getViewContext().getChromosomeLength();
        cytobandScale = ((double) chromosomeLength) / dataPanelWidth;

        // The test is true if we are zoomed in 
        if (getViewContext().getZoom() > 0) {

            double scale = getViewContext().getScale();

            double origin = isDragging ? viewOrigin : getViewContext().getOrigin();

            int start = (int) (origin / cytobandScale);
            double scaledDataPanelWidth = dataPanelWidth * scale;
            int span = (int) (scaledDataPanelWidth / cytobandScale);

            // Draw Cytoband current region viewer
            int height = (int) cytoRect.getHeight();
            g.setColor(Color.RED);
            int y = (int) (cytoRect.getY()) + CytobandRenderer.CYTOBAND_Y_OFFSET;

            g.drawRect(start, y, span, height);
            g.drawRect(start - 1, (y - 1), span + 2, height + 2);
            g.drawRect(start - 2, (y - 2), span + 4, height + 4);
            if (span < 2) {

                g.drawRect(start - 2, (y - 2), span + 4, height + 4);
            }
        }
    }

    int toolOrigin = -1;

    private void initialize() {

        setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        this.setToolTipText(
                "<html>Click anywhere on the cytoband <p>to center view at that location.");


        MouseInputAdapter mouseAdapter = new MouseInputAdapter() {

            int lastMousePressX;

            public void mouseClicked(MouseEvent e) {
                final int mouseX = e.getX();
                final int clickCount = e.getClickCount();
                WaitCursorManager.CursorToken token = WaitCursorManager.showWaitCursor();
                try {

                    double newLocation = cytobandScale * mouseX;
                    if (clickCount > 1) {
                        final int newZoom = getViewContext().getZoom() + 1;
                        getViewContext().zoomTo(newZoom, newLocation);
                    } else {
                        getViewContext().centerOnLocation(newLocation);
                    }

                } finally {
                    WaitCursorManager.removeWaitCursor(token);
                }
            }

            @Override
            public void mousePressed(MouseEvent e) {
                lastMousePressX = e.getX();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                if (isDragging) {
                    WaitCursorManager.CursorToken token = WaitCursorManager.showWaitCursor();
                    try {
                        getViewContext().setOrigin(viewOrigin);
                    } finally {
                        WaitCursorManager.removeWaitCursor(token);
                    }
                }
                isDragging = false;
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                if (!isDragging) {
                    isDragging = true;
                    viewOrigin = getViewContext().getOrigin();
                }

                // Dragging disabled until image thread is improved.  Currently
                // dragging will overwhelm the queue

                /*
                 *   int start = (int) (origin / cytobandScale);
                 * double scaledDataPanelWidth = dataPanelWidth * scale;
                 * int span = (int) (scaledDataPanelWidth / cytobandScale);
                 */
                int w = getWidth();
                double scale = getViewContext().getScale();
                int x = (int) Math.max(0, Math.min(e.getX(), w * (cytobandScale - scale)));
                int delta = x - lastMousePressX;
                if ((delta != 0) && (cytobandScale > 0)) {
                    viewOrigin = Math.max(0, Math.min(viewOrigin + delta * cytobandScale,
                            w * (cytobandScale - scale)));
                    repaint();
                }
                lastMousePressX = x;

                // Dragging disabled until image thread is improved.  Currently
                // dragging will overwhelm the queue

                /*
                 * int x = e.getX();
                 * int delta = x - lastMousePressX;
                 * if(delta != 0 && visibleFraction > 0) {
                 * getViewContext().shiftOriginPixels((int) (delta / visibleFraction));
                 * }
                 * lastMousePressX = x;
                 */

            }

            @Override
            public void mouseEntered(MouseEvent e) {
            }

            @Override
            public void mouseExited(MouseEvent e) {

            }
        };

        addMouseMotionListener(mouseAdapter);
        addMouseListener(mouseAdapter);
    }

    // TODO remove reference to IGVMainFrame.theInstance

    private ViewContext getViewContext() {
        return ViewContext.getInstance();
    }
}
