package gui;

import javafx.geometry.VPos;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;

/**
 * Created by Jasper van Tilburg on 15-6-2017.
 * The minimap class controls a small bar in the screen the shows where in the DNA sequence you are.
 */
public class Minimap {

    public static final int MINIMAP_Y = 100;
    public static final int MINIMAP_HEIGHT = 20;
    public static final int TEXT_Y = 40;
    public static final int TEXT_END_Y = 5;
    public static final int TEXT_SIZE = 10;
    public static final int DIVISION_LINE_HEIGHT = 15;
    public static final int CHAR_WIDTH = 3;

    private static Minimap minimap = new Minimap();

    private int size;
    private int stepSize;
    private double amountVisible;
    private double width;
    private double value;

    private Minimap() {

    }

    /**
     * Getter for the singleton Minimap.
     * @return the minimap
     */
    public static Minimap getInstance() {
        return minimap;
    }

    /**
     * Initialize the minimap.
     * @param sizeVal Size of the whole graph in number of nodes
     */
    public void initialize(int sizeVal) {
        value = 0;
        amountVisible = 0;
        size = sizeVal;
        stepSize = computeDivisions();
        width = Math.log10(size) * 100;

    }

    /**
     * Draw the minimap on screen.
     * @param gc The GraphicsContext object needed to draw the minimap
     */
    public void draw(GraphicsContext gc) {
        gc.setStroke(Color.BLACK);
        gc.setLineWidth(1);
        gc.setFont(new Font("Arial", TEXT_SIZE));

        drawMapBox(gc);
        drawDivisionLines(gc);
        drawViewBox(gc);
    }

    /**
     * Draw the small box that represents the sequence.
     * @param gc The GraphicsContext object needed to draw the minimap
     */
    private void drawMapBox(GraphicsContext gc) {
        double x = gc.getCanvas().getWidth() / 2 - width / 2;
        double y = gc.getCanvas().getHeight() - MINIMAP_Y;
        gc.strokeRect(x, y, width, MINIMAP_HEIGHT);
        gc.strokeText("0", x, y + TEXT_Y);
        gc.strokeText(size + "", x + width - Integer.toString(size).length() * CHAR_WIDTH, y - TEXT_END_Y);
    }

    /**
     * Draw the interval lines.
     * @param gc The GraphicsContext object needed to draw the minimap
     */
    private void drawDivisionLines(GraphicsContext gc) {
        double x = gc.getCanvas().getWidth() / 2 - width / 2;
        double y = gc.getCanvas().getHeight() - MINIMAP_Y;
        for (int i = stepSize; i < size; i += stepSize) {
            double division = x + valueToXCoordinate(i);
            gc.strokeLine(division, y + DIVISION_LINE_HEIGHT, division, y + MINIMAP_HEIGHT);
            gc.strokeText(i + "", division - Integer.toString(i).length() * CHAR_WIDTH, y + TEXT_Y);
        }
    }

    /**
     * Draw the box that represents the part of the sequence that is in view of the screen.
     * @param gc The GraphicsContext object needed to draw the minimap
     */
    private void drawViewBox(GraphicsContext gc) {
        double x = gc.getCanvas().getWidth() / 2 - width / 2;
        double y = gc.getCanvas().getHeight() - MINIMAP_Y;
        gc.setStroke(Color.RED);
        gc.strokeRect(x + valueToXCoordinate(value), y, valueToXCoordinate(amountVisible), MINIMAP_HEIGHT);
    }

    /**
     * Convert a node to it's corresponding x coordinate in the minimap.
     * @param value Node id
     * @return X coordinate of the value
     */
    private double valueToXCoordinate(double value) {
        return (value / (double) size) * width;
    }

    /**
     * Compute the stepsize of the intervals.
     * @return Interval stepsize
     */
    private int computeDivisions() {
        String sizeStr = Integer.toString(size);
        int firstDigit = Integer.parseInt(sizeStr.substring(0, 1));
        int step = firstDigit >= 5 ? 1 : 5;
        int zeros = sizeStr.substring(1, sizeStr.length() - 1).length();
        return (int) (step * Math.pow(10, zeros));
    }

    /**
     * Setter for the amount of nodes visible.
     * @param amountVisible Amount of nodes visible
     */
    public void setAmountVisible(double amountVisible) {
        this.amountVisible = amountVisible;
    }

    /**
     * Setter for the value of the first node in screen, i.e. left side of the screen.
     * @param value ID of the first node
     */
    public void setValue(double value) {
        this.value = value;
    }
}

@@ -365,17 +365,17 @@
 MAP_Y = 
-1
+7
 00;%0A    
@@ -456,16 +456,17 @@
 EXT_Y = 
+7
 40;%0A    
@@ -502,16 +502,18 @@
 END_Y = 
+69
 5;%0A    p
@@ -602,16 +602,17 @@
 EIGHT = 
+7
 15;%0A    
@@ -1332,17 +1332,16 @@
  * 100;%0A
-%0A
     %7D%0A%0A 
@@ -1972,85 +1972,34 @@
     
-double y = gc.getCanvas().getHeight() - MINIMAP_Y;%0A        gc.strokeRect(x, y
+gc.strokeRect(x, MINIMAP_Y
 , wi
@@ -2049,20 +2049,16 @@
 (%220%22, x,
- y +
  TEXT_Y)
@@ -2153,12 +2153,8 @@
 DTH,
- y -
  TEX
@@ -2412,67 +2412,8 @@
  2;%0A
-        double y = gc.getCanvas().getHeight() - MINIMAP_Y;%0A
     
@@ -2558,20 +2558,16 @@
 ivision,
- y +
  DIVISIO
@@ -2591,17 +2591,25 @@
 vision, 
-y
+MINIMAP_Y
  + MINIM
@@ -2711,12 +2711,8 @@
 DTH,
- y +
  TEX
@@ -3030,67 +3030,8 @@
  2;%0A
-        double y = gc.getCanvas().getHeight() - MINIMAP_Y;%0A
     
@@ -3112,17 +3112,25 @@
 value), 
-y
+MINIMAP_Y
 , valueT

Revert "Relative minimap location"