package org.broad.igv.feature.bedpe;

import org.broad.igv.feature.genome.Genome;
import org.broad.igv.track.AbstractTrack;
import org.broad.igv.track.RenderContext;
import org.broad.igv.track.TrackClickEvent;
import org.broad.igv.track.TrackMenuUtils;
import org.broad.igv.ui.IGV;
import org.broad.igv.ui.panel.IGVPopupMenu;
import org.broad.igv.ui.panel.ReferenceFrame;
import org.broad.igv.ui.util.MessageUtils;
import org.broad.igv.util.ResourceLocator;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;


/**
 * Created by jrobinso on 6/29/18.
 */
public class InteractionTrack extends AbstractTrack {

    private Map<String, List<BedPEFeature>> featureMap;

    private PEArcRenderer renderer;

    public InteractionTrack(ResourceLocator locator, List<BedPEFeature> featureList, Genome genome) {
        super(locator);
        init(featureList, genome);
        renderer = new PEArcRenderer();
        setHeight(200);
        setColor(new Color(180, 25, 137));
    }

    private void init(List<BedPEFeature> featureList, Genome genome) {

        this.featureMap = new HashMap<>();

        // Sort feature lists by "start" (minimum of start1, start2)
        Collections.sort(featureList, (o1, o2) -> o1.getStart() - o2.getStart());

        for (BedPEFeature f : featureList) {

            String key;
            if (f.chr1.equals(f.chr2)) {
                key = genome == null ? f.chr1 : genome.getCanonicalChrName(f.chr1);
            } else {
                key = "OTHER";
            }

            List<BedPEFeature> features = featureMap.get(key);
            if (features == null) {
                features = new ArrayList<>();
                featureMap.put(key, features);
            }

            features.add(f);
        }


    }

    @Override
    public boolean isReadyToPaint(ReferenceFrame frame) {
        return true;
    }

    @Override
    public void load(ReferenceFrame frame) {
        // Nothing to do, this track is pre-loaded
    }

    @Override
    public void render(RenderContext context, Rectangle rect) {

        Graphics2D g2d = context.getGraphics();
        Rectangle clip = new Rectangle(g2d.getClip().getBounds());
        g2d.setClip(rect.intersection(clip.getBounds()));
        context.clearGraphicsCache();

        try {
            String chr = context.getReferenceFrame().getChrName();
            List<BedPEFeature> features = featureMap.get(chr);

            if (features != null) {
                renderer.render(features, context, rect, this);
            }
            context.clearGraphicsCache();
        } finally {
            g2d.setClip(clip);
        }
    }


    @Override
    public IGVPopupMenu getPopupMenu(TrackClickEvent te) {

        IGVPopupMenu menu = new IGVPopupMenu();

        menu.add(TrackMenuUtils.getTrackRenameItem(Collections.singleton(InteractionTrack.this)));

        JMenuItem item = new JMenuItem("Set Track Color...");
        item.addActionListener(evt -> TrackMenuUtils.changeTrackColor(Collections.singleton(InteractionTrack.this)));
        menu.add(item);

        item = new JMenuItem("Toggle Arc Direction");
        item.addActionListener(evt -> {
            if (renderer.direction == PEArcRenderer.Direction.UP) {
                renderer.direction = PEArcRenderer.Direction.DOWN;
            } else {
                renderer.direction = PEArcRenderer.Direction.UP;
            }
            IGV.getInstance().repaint();
        });
        menu.add(item);

        item = new JMenuItem("Set Line Thickness...");
        item.addActionListener(e -> {
            String t = MessageUtils.showInputDialog("Line thickness", String.valueOf(renderer.lineThickness));
            if (t != null) {
                try {
                    renderer.lineThickness =Integer.parseInt(t);
                    IGV.getInstance().repaint();
                } catch (NumberFormatException e1) {
                    MessageUtils.showErrorMessage("Line thickness must be an integer", e1);
                }
            }
        });
        menu.add(item);

        return menu;
    }
}

@@ -56,29 +56,109 @@
 igv.
-feature.genome.Genome
+Globals;%0Aimport org.broad.igv.feature.genome.Genome;%0Aimport org.broad.igv.feature.sprite.ClusterTrack
 ;%0Aim
@@ -1103,17 +1103,17 @@
 Height(2
-0
+5
 0);%0A    
@@ -1931,24 +1931,997 @@
 %0A        %7D%0A%0A
+        if(featureMap.containsKey(%22OTHER%22)) %7B%0A            featureMap.put(Globals.CHR_ALL, createWGFeatures(featureMap.get(%22OTHER%22), genome));%0A        %7D%0A    %7D%0A%0A    private List%3CBedPEFeature%3E createWGFeatures(List%3CBedPEFeature%3E features, Genome genome) %7B%0A%0A        List%3CBedPEFeature%3E wgFeatures = new ArrayList%3C%3E(features.size());%0A%0A        for (BedPEFeature f : features) %7B%0A%0A            BedPEFeature wgFeature = new BedPEFeature();%0A            wgFeature.chr1 = Globals.CHR_ALL;%0A            wgFeature.chr2 = Globals.CHR_ALL;%0A            wgFeature.name = f.name;%0A            wgFeature.score = f.score;%0A            wgFeature.start1 = genome.getGenomeCoordinate(f.chr1, f.start1);%0A            wgFeature.end1 = genome.getGenomeCoordinate(f.chr1, f.end1);%0A            wgFeature.start2 = genome.getGenomeCoordinate(f.chr1, f.start2);%0A            wgFeature.end2 = genome.getGenomeCoordinate(f.chr1, f.end2);%0A            wgFeatures.add(wgFeature);%0A%0A        %7D%0A        return wgFeatures;
 %0A    %7D%0A%0A    
@@ -4037,24 +4037,221 @@
 uItem item =
+ new JMenuItem(%22Set Track Height...%22);%0A        item.addActionListener(evt -%3E TrackMenuUtils.changeTrackHeight(Collections.singleton(InteractionTrack.this)));%0A        menu.add(item);%0A%0A        item =
  new JMenuIt
@@ -5125,16 +5125,17 @@
 ckness =
+ 
 Integer.

Add track height menu option to InteractionTrack