> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.dX18wXzqkhn/rev.3399
 * 
 * authors: 
 *   Juergen Kleinowitz
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



// Pressing Control-R will render this sketch.

HashMap elements;
int[] values;
ArrayList queue;

int offsetY = 80;
int offsetX = 20;
int eWidth = 40;
Color borderCol = color(151,190,13);
Color fillCol = color(0);
Element e;
ArrayList moveCommands;
int eSideLength = 40;
int UP = 1;
int DOWN = -1;


void setup() {  // this is run once.   
    elements = new HashMap();
    queue = new ArrayList();
    moveCommands = new ArrayList();
    values = {5,4,2,1,3,6};
    //values = {3,2,1};
    setupElements();

    // set the background color
    background(255);
    
    // canvas size (Variable aren't evaluated. Integers only, please.)
    size(600, 480); 
      
    // smooth edges
    smooth();
    
    // limit the number of frames per second
    frameRate(30);
    
    // set the width of the line. 
    strokeWeight(12);
    sortElements();
    
    //createCommandsForSwitch(queue.get(0));
    for (Move elemSwitch: queue) {
        createCommandsForSwitch(elemSwitch);
    }
} 
void sortElements() {
    bubbleSort();
}

void setupElements() {
    for (int i=0;i<values.length;i++) {
        int x = offsetX + (eWidth*1.5) * i
        e = new Element(x,offsetY,borderCol  , fillCol, values[i]);
        elements.put(values[i], e)
    }   
}
void draw() {  // this is run repeatedly.  
    background(255);
    for (Element e : elements.values()) {
        e.display();
    }
    if (moveCommands != null && moveCommands.size() > 5) {
        
        //Please rework me
        if (moveCommands.get(0).execute()) {
            if(moveCommands.get(1).execute()) {
                if(moveCommands.get(2).execute()) {
                    //All commands execute
                }                       
            }
        }                
        if (moveCommands.get(3).execute()) {
            if(moveCommands.get(4).execute()) {
                if(moveCommands.get(5).execute()) {
                    //Remove the first 6 elements
                    moveCommands.remove(0);
                    moveCommands.remove(0);
                    moveCommands.remove(0);
                    moveCommands.remove(0);
                    moveCommands.remove(0);
                    moveCommands.remove(0);
                }                       
            }
        }
        
    }
}

//HelperMethods
void createCommandsForSwitch(Move elemSwitch ) {
    Element a = elements.get(elemSwitch.valueA);
    Element b = elements.get(elemSwitch.valueB);
    moveCommands.addAll(switchElements(elements.get(elemSwitch.valueA), elements.get(elemSwitch.valueB)));
}

ArrayList switchElements(Element elemA, Element elemB) {
    ArrayList commands = new ArrayList();

    commands.addAll(createRectMoveCommands(elemA, elemA.newX, elemB.newX, UP));
    commands.addAll(createRectMoveCommands(elemB, elemB.newX, elemA.newX, DOWN));
    
    int tempBx = elemB.newX;
    elemB.newX = elemA.newX;
    elemA.newX = tempBx;    
    
    return commands;
}

ArrayList createRectMoveCommands(Element e, int startX, int targetX, int direction) {
    ArrayList commands = new ArrayList();
    
       
    int startY = offsetY;
    int targetY = offsetY-eSideLength*1.5*direction;
    
    commands.add(new MoveCommand(startX, 0, startX, targetY, e));
    commands.add(new MoveCommand(startX, startY, targetX, targetY, e));
    commands.add(new MoveCommand(targetX, 0, targetX, startY, e));
    return commands;
}


void printList(ArrayList list) {
    String text = "";
    for (Object obj : list) {
      text = text + "  | " + obj.toString();
    }
    println(text);
}

//Element
class Element {
  
    String content;
    float posX;
    float posY;
    float newX;
    float newY;
    color borderColor;
    color fillColor;
    float speed;
    int elementWidth = eSideLength ;
    int elementHeight = eSideLength ;
    String direction = "right";
    
    Element(float posX, float posY, color borderColor, color fillColor, String content) {
        this.posX = posX;
        this.posY = posY;
        this.borderColor = borderColor;
        this.fillColor = fillColor;
        this.content = content;
        contentWidth = textWidth(content);
        this.newX = posX;
    }
    
    void display() {
        strokeWeight(4);
        stroke(borderColor);
        noFill();
        rect(posX, posY, elementWidth, elementHeight);
        fill(0);
        textSize(20);
        contentWidth = textWidth(content);
        text(content, posX + elementWidth / 2 - contentWidth / 2, posY + 27);
    }
    
    void moveTo(int targetX, int targetY) {
        int offsetX = targetX - posX;
        int offsetY = targetY - posY;
        posX = offsetX / 8 + posX;
        posY = offsetY / 8 + posY;
    }
    
}


// MoveCommand
class MoveCommand {
    Element eToMove;
    int startX;
    int startY;
    int targetX;
    int targetY;
    boolean executed = false;
    
    MoveCommand(int startX, int startY, int targetX, int targetY, eToMove) {
        this.startX = startX;
        this.startY = startY;
        this.targetX = targetX;
        this.targetY = targetY;
        this.eToMove = eToMove;
    }
    boolean execute() {
        if (!executed) {
            if (Math.round(eToMove.posX) == targetX && Math.round(eToMove.posY) == targetY) {
                executed = true;
            } else {
                eToMove.moveTo(targetX, targetY);
            }
        }        
        return executed;
    }    
}





//Bubblesort
void bubbleSort() {
    int N = values.length;
    
    for (int j = N-1;j > 0;j--) {
        for (int i = 0; i<j;i++) {
            if (compare(values[i+1], values [i])) {
                exchange(i+1,i);
            }
        }
    }
}

boolean compare(int a, int b) {
    if (a<b) {
        return true;
    } else {
    return false;
    }
}
void exchange(int posA, int posB) {
    Move mov = new Move(posA, values[posA], posB, values[posB]);
    queue.add(mov);
    
    int tmpA = values[posA];
    int tmpB = values[posB];
    values[posA] = values[posB]
    values[posB] = tmpA;

}

//Quicksort

//Move
class Move {
    public int indexA;
    public int indexB;
    public int valueA;
    public int valueB;
    
    public Move(int indexA, int valueA, int indexB, valueB) {
        this.indexA = indexA;
        this.indexB = indexB;
        this.valueA = valueA;
        this.valueB = valueB;
    }
    public String toString() {
        return "A: " + indexA+"/"+ valueA + ", B: " + indexB + "/" +valueB ;
    }
}