/*
 * Copyright (c) 2007-2012 The Broad Institute, Inc.
 * SOFTWARE COPYRIGHT NOTICE
 * This software and its documentation are the copyright of the Broad Institute, Inc. All rights are reserved.
 *
 * This software is supplied without any warranty or guaranteed support whatsoever. The Broad Institute is not
 * responsible for its use, misuse, or functionality.
 *
 * 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.
 */

package org.broad.igv.methyl;

import org.broad.igv.Globals;
import org.broad.igv.feature.genome.Genome;
import org.broad.igv.renderer.DataRange;
import org.broad.igv.renderer.GraphicUtils;
import org.broad.igv.renderer.Renderer;
import org.broad.igv.renderer.PointsRenderer;
import org.broad.igv.track.AbstractTrack;
import org.broad.igv.track.RenderContext;
import org.broad.igv.util.LongRunningTask;
import org.broad.igv.util.ResourceLocator;

import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * Experimental class for specific dataset.
 * <p/>
 * if(locator.getPath().contains("RRBS_cpgMethylation") || locator.getPath().contains("")) {
 *
 * @author Jim Robinson
 * @date 4/19/12
 */
public class MethylTrack extends AbstractTrack {

    public static final int ONE_MB = 1000000;
    public static final int TEN_MB = 10000000;
    MethylDataSource dataSource;
    Interval loadedInterval;
    Renderer renderer;
    int resolutionThreshold;

    public MethylTrack(ResourceLocator dataResourceLocator, Genome genome) throws IOException {
        super(dataResourceLocator);
        setHeight(60);
        renderer = new PointsRenderer();

        boolean isWGBS = dataResourceLocator.getPath().contains("BiSeq_cpgMethylation");
        resolutionThreshold = isWGBS ? ONE_MB : TEN_MB;
        dataSource = new CachingMethylSource( new BBMethylDataSource(dataResourceLocator.getPath(), genome), resolutionThreshold);
        loadedInterval = new Interval("", -1, -1, Collections.<MethylScore>emptyList());
        setDataRange(new DataRange(0, 100));
    }

    /**
     * Render the track in the supplied rectangle.  It is the responsibility of the track to draw within the
     * bounds of the rectangle.
     *
     * @param context the render context
     * @param rect    the track bounds, relative to the enclosing DataPanel bounds.
     */
    public void render(final RenderContext context, final Rectangle rect) {

        if (context.getChr().equals(Globals.CHR_ALL) || context.getScale() * rect.width > resolutionThreshold) {
            Graphics2D g = context.getGraphic2DForColor(Color.gray);
            Rectangle textRect = new Rectangle(rect);

            // Keep text near the top of the track rectangle
            textRect.height = Math.min(rect.height, 20);
            textRect.height = Math.min(rect.height, 20);
            String message = context.getChr().equals(Globals.CHR_ALL) ? "Zoom in to see features." :
                    "Zoom in to see features, or right-click to increase Feature Visibility Window.";
            GraphicUtils.drawCenteredText(message, textRect, g);
            return;
        }

        final String chr = context.getChr();
        final int start = (int) context.getOrigin();
        final int end = (int) context.getEndLocation();
        if (loadedInterval.contains(chr, start, end)) {
            renderer.render(loadedInterval.scores, context, rect, this);
        } else {
            Runnable runnable = new Runnable() {
                public void run() {
                    int width = (end - start) / 2;
                    int expandedStart = Math.max(0, start - width);
                    int expandedEnd = end + width;

                    List<MethylScore> scores = new ArrayList<MethylScore>(1000);
                    Iterator<MethylScore> iter = dataSource.query(chr, expandedStart, expandedEnd);
                    while (iter.hasNext()) {
                        scores.add(iter.next());
                    }
                    loadedInterval = new Interval(chr, expandedStart, expandedEnd, scores);
                    context.getPanel().repaint(); //rect);
                }
            };
            LongRunningTask.submit(runnable);
        }
    }

    public Renderer getRenderer() {
        return renderer;  //To change body of implemented methods use File | Settings | File Templates.
    }


    static class Interval {
        String chr;
        int start;
        int end;
        List<MethylScore> scores;

        Interval(String chr, int start, int end, List<MethylScore> scores) {
            this.chr = chr;
            this.end = end;
            this.scores = scores;
            this.start = start;
        }

        boolean contains(String chr, int start, int end) {
            return this.chr.equals(chr) && this.start <= start && this.end >= end;
        }

    }
}

@@ -1488,20 +1488,29 @@
 000000;%0A
+%0A
     
+private 
 MethylDa
@@ -1530,24 +1530,32 @@
 Source;%0A    
+private 
 Interval loa
@@ -1571,16 +1571,24 @@
 al;%0A    
+private 
 Renderer
@@ -1598,24 +1598,32 @@
 nderer;%0A    
+private 
 int resoluti
@@ -1634,16 +1634,53 @@
 reshold;
+%0A    private boolean loading = false;
 %0A%0A    pu
@@ -2060,17 +2060,16 @@
 lSource(
- 
 new BBMe
@@ -3663,16 +3663,80 @@
  else %7B%0A
+            if (!loading) %7B%0A                loading = true;%0A    
         
@@ -3788,24 +3788,28 @@
             
+    
 public void 
@@ -3812,24 +3812,63 @@
 oid run() %7B%0A
+%0A
+                        try %7B%0A        
             
@@ -3906,16 +3906,24 @@
 t) / 2;%0A
+        
         
@@ -3994,32 +3994,40 @@
                 
+  
+      
 int expandedEnd 
@@ -4042,16 +4042,24 @@
 width;%0A%0A
+        
         
@@ -4151,16 +4151,24 @@
         
+      
+  
 Iterator
@@ -4259,16 +4259,24 @@
         
+        
 while (i
@@ -4288,24 +4288,32 @@
 asNext()) %7B%0A
+        
             
@@ -4361,34 +4361,50 @@
                 
+ 
-%7D%0A
+       %7D%0A        
                 
@@ -4499,16 +4499,24 @@
         
+        
 context.
@@ -4566,25 +4566,144 @@
     
-%7D%0A            %7D;%0A
+        %7D finally %7B%0A                            loading = false;%0A                        %7D%0A                    %7D%0A                %7D;%0A    
     
@@ -4744,16 +4744,30 @@
 nable);%0A
+            %7D%0A
         

Update to methylation track -- prevent multiple loadings of same data