/*
 * 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.
 */

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.broad.igv.ui.panel;

import org.broad.igv.feature.SequenceManager;
import org.broad.igv.session.ViewContext;
import org.broad.igv.track.RegionScoreType;
import org.broad.igv.track.TrackType;
import org.broad.igv.ui.IGVMainFrame;
import org.broad.igv.ui.RegionOfInterest;
import org.broad.igv.ui.util.MessageUtils;
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.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.util.Collection;
import java.util.Set;

/**
 * @author eflakes
 */
public class RegionOfInterestPanel extends JPanel {

    PopupMenu popup;

    private RegionOfInterest selectedRegion = null;

    public RegionOfInterestPanel() {

        setToolTipText("Regions of Interest");

        MouseInputAdapter ma = new ROIMouseAdapater();
        addMouseListener(ma);
        addMouseMotionListener(ma);
    }

    @Override
    public void paintComponent(final Graphics g) {

        super.paintComponent(g);

        // Draw regions of interest?
        drawRegionsOfInterest((Graphics2D) g, getHeight());

        g.setColor(Color.BLACK);
        g.drawRect(0, 0, getWidth(), getHeight());
    }

    Collection<RegionOfInterest> getRegions() {
        return IGVMainFrame.getInstance().getSession().getRegionsOfInterest(ViewContext.getInstance().getChrName());
    }

    public void drawRegionsOfInterest(final Graphics2D g, int height) {

        ViewContext viewContext = ViewContext.getInstance();
        Collection<RegionOfInterest> regions = getRegions();

        if (regions == null || regions.isEmpty()) {
            return;
        }


        for (RegionOfInterest regionOfInterest : regions) {

            Integer regionStart = regionOfInterest.getStart();
            if (regionStart == null) {
                // skip - null starts are bad regions of interest
                continue;
            }

            Integer regionEnd = regionOfInterest.getEnd();
            if (regionEnd == null) {
                regionEnd = regionStart;
            }
            int start = viewContext.getPixelPosition(regionStart);
            int end = viewContext.getPixelPosition(regionEnd);
            int regionWidth = Math.max(1, end - start);

            g.setColor(regionOfInterest.getBackgroundColor());
            g.setBackground(regionOfInterest.getBackgroundColor());
            g.fillRect(start, 0, regionWidth, height);

        }
    }


    RegionOfInterest getRegionOfInterest(int px) {

        double pos = ViewContext.getInstance().getChromosomePosition(px);

        Collection<RegionOfInterest> roiList = getRegions();
        if (roiList != null) {
            for (RegionOfInterest roi : roiList) {
                if (pos > roi.getStart() && pos < roi.getEnd()) {
                    return roi;
                }
            }
        }

        return null;

    }

    protected JPopupMenu getPopupMenu(final RegionOfInterest roi) {

        Set<TrackType> loadedTypes = IGVMainFrame.getInstance().getTrackManager().getLoadedTypes();

        JPopupMenu popupMenu = new JPopupMenu();

        if (loadedTypes.contains(TrackType.COPY_NUMBER) ||
                loadedTypes.contains(TrackType.ALLELE_SPECIFIC_COPY_NUMBER) ||
                loadedTypes.contains(TrackType.CNV)) {
            JMenuItem item = new JMenuItem("Sort by amplification");
            item.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {

                    IGVMainFrame.getInstance().getTrackManager().sortByRegionScore(roi, RegionScoreType.AMPLIFICATION);
                    IGVMainFrame.getInstance().getContentPane().repaint();
                }
            });
            popupMenu.add(item);


            item = new JMenuItem("Sort by deletion");
            item.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {

                    IGVMainFrame.getInstance().getTrackManager().sortByRegionScore(roi, RegionScoreType.DELETION);
                    IGVMainFrame.getInstance().getContentPane().repaint();
                }
            });
            popupMenu.add(item);

            item = new JMenuItem("Sort by breakpoint amplitudes");
            item.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {

                    IGVMainFrame.getInstance().getTrackManager().sortByRegionScore(roi, RegionScoreType.FLUX);
                    IGVMainFrame.getInstance().getContentPane().repaint();
                }
            });
            popupMenu.add(item);
        }

        if (loadedTypes.contains(TrackType.GENE_EXPRESSION)) {
            JMenuItem item = new JMenuItem("Sort by expression");
            item.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {

                    IGVMainFrame.getInstance().getTrackManager().sortByRegionScore(roi, RegionScoreType.EXPRESSION);
                    IGVMainFrame.getInstance().getContentPane().repaint();

                }
            });

            popupMenu.add(item);
        }

        JMenuItem item = new JMenuItem("Sort by value");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                IGVMainFrame.getInstance().getTrackManager().sortByRegionScore(roi, RegionScoreType.SCORE);
                IGVMainFrame.getInstance().getContentPane().repaint();

            }
        });
        popupMenu.add(item);

        popupMenu.addSeparator();

        item = new JMenuItem("Zoom");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                ViewContext.getInstance().jumpTo(roi.getChr(), roi.getStart(), roi.getEnd());

                String locusString = roi.getLocusString();
                ViewContext.getInstance().history.push(locusString);

            }
        });
        popupMenu.add(item);

        item = new JMenuItem("Edit description...");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {


                String desc = JOptionPane.showInputDialog(RegionOfInterestPanel.this, "Add or edit region description:", roi.getDescription());
                roi.setDescription(desc);

            }
        });
        popupMenu.add(item);

        item = new JMenuItem("Copy sequence");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                LongRunningTask.submit(new NamedRunnable() {
                    public String getName() {
                        return "Copy sequence";
                    }

                    public void run() {
                        String genomeId = ViewContext.getInstance().getGenomeId();
                        byte[] seqBytes = SequenceManager.readSequence(genomeId, roi.getChr(), roi.getStart(), roi.getEnd());
                        if (seqBytes == null) {
                            MessageUtils.showMessage("Sequence not available");
                        } else {
                            String sequence = new String(seqBytes);
                            StringSelection stringSelection = new StringSelection(sequence);
                            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                            clipboard.setContents(stringSelection, null);
                        }
                    }
                });


            }
        });

        // Disable copySequence if region exceeds a MB
        if (roi.getEnd() - roi.getStart() > 1000000) {
            item.setEnabled(false);
        }
        popupMenu.add(item);


        popupMenu.add(new JSeparator());

        item = new JMenuItem("Delete");
        item.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                getRegions().remove(roi);
                IGVMainFrame.getInstance().repaintDataAndHeaderPanels();
            }
        });
        popupMenu.add(item);

        return popupMenu;
    }


    public RegionOfInterest getSelectedRegion() {
        return selectedRegion;
    }

    public void setSelectedRegion(RegionOfInterest selectedRegion) {
        this.selectedRegion = selectedRegion;
    }

    class ROIMouseAdapater extends MouseInputAdapter {
        /**
         * Method description
         *
         * @param e
         */
        @Override
        public void mousePressed(MouseEvent e) {
            showPopup(e);
        }

        /**
         * Method description
         *
         * @param e
         */
        @Override
        public void mouseReleased(MouseEvent e) {
            showPopup(e);
        }


        @Override
        public void mouseMoved(MouseEvent e) {
            RegionOfInterest roi = getRegionOfInterest(e.getX());
            if (roi != null) {
                setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                setToolTipText(roi.getTooltip());
                if (selectedRegion != roi) {
                    selectedRegion = roi;
                    IGVMainFrame.getInstance().repaintDataPanels();
                }

            } else {
                if (selectedRegion != null) {
                    selectedRegion = null;
                    IGVMainFrame.getInstance().repaintDataPanels();
                }
                setToolTipText("");
                setCursor(Cursor.getDefaultCursor());
            }
        }

        @Override
        public void mouseExited(MouseEvent mouseEvent) {
            //if (selectedRegion != null) {
            //    selectedRegion = null;
            //    IGVMainFrame.getInstance().repaintDataPanels();
            //}
        }

        private void showPopup(MouseEvent e) {

            RegionOfInterest roi = getRegionOfInterest(e.getX());
            if (roi != null) {

                getPopupMenu(roi).show(e.getComponent(), e.getX(), e.getY());
            }

        }
    }
}
