var Engine = Matter.Engine,
    Render = Matter.Render,
    World = Matter.World,
    Body = Matter.Body,
    Bodies = Matter.Bodies,
    Composite = Matter.Composite,
    Composites = Matter.Composites,
    Runner = Matter.Runner,
    Constraint = Matter.Constraint,
    MouseConstraint = Matter.MouseConstraint,
    Mouse = Matter.Mouse,
    Vertices = Matter.Vertices,
    Vector = Matter.Vector,
    Events = Matter.Events,
    Grid = Matter.Grid;
   
var engine;
var world;
var words = [];
var ground, Lwall, Rwall;
var slider;
var slider2;
var button, button2;

var a=0;//input index
var z=0;//slider value index
var x=0;//slider value incrementor

var input = [];
var word;

var smallest, largest;

//var maxFont = 55; //for suicide data
var maxFont = 75 //all others

var paragraph;
var current; // history of slider values

var step = []

var maxArray = [];//keep track of max of each year

var playing = false; //keeps track if time is playing forward

var zoom = 0.5; //zoom
var zMin = 0.25;
var zMax = 2.00;
var sensitivity = 0.0005;

var mouse;

function preload(){
    //load data
    input = loadStrings("text.txt");
    //load font
    times = loadFont('times.otf');

}

//p5 canvas and Matter world setup
function setup() {

    //p5 canvas in 3D
    var c = createCanvas(800,375, WEBGL);
    //c.mousePressed(write);
    

    //create Matter world and add ground
    engine = Engine.create();
    world = engine.world;
    //world.gravity.y = 0.5;
    world.gravity.y = 0;


    rectMode(CENTER);
    
    Engine.run(engine);


    mouse = Mouse.create(c.elt);
    Mouse.setOffset(mouse, {x: -400, y: -187.5});
    mouse.pixelRatio = pixelDensity();
        mouseConstraint = MouseConstraint.create(engine, {
            mouse: mouse,
            constraint: {
                stiffness: 0.1,
           }
        });

    World.add(world, mouseConstraint);

/* Matter js renderer for debugging
    // create renderer
    var render = Render.create({
        element: document.body,
        engine: engine,
        options: {
            width: 600,
            height: 600,
        }
    });



    Render.lookAt(render, {
        min: { x: -300, y: -300 },
        max: { x: 300, y: 300 }
    });

    Render.run(render);

    // create runner
    var runner = Runner.create();
    Runner.run(runner, engine);
*/
    
    //interactive slider
    slider2 = createSlider(0, 43, 0);
    slider2.size(800);


    current = []
    current[z] = slider2.value();
    step[z] = 0;

    paragraph = createP();
    paragraph.elt.style.fontSize = "xx-large";


    //interactive buttons

    button = createButton("add");
    button.mousePressed(write);
    button.position(200, 475);
    button.size(100, 50);
    button.elt.style.fontSize = "xx-large";

    button2 = createButton("reset");
    button2.mousePressed(reset);
    button2.position(325, 475);
    button2.size(120, 50);
    button2.elt.style.fontSize = "xx-large";

    button3 = createButton("play");
    button3.mousePressed(play);
    button3.position(470, 475);
    button3.size(110, 50);
    button3.elt.style.fontSize = "xx-large";

    //instructions on top right of window
    h1 = createP("Instructions: ");
    h2 = createP("- Move the slider to change time points");
    h3 = createP("- Click and drag the words to move them around");
    h4 = createP("- Scroll mouse to zoom in and out");
    h5 = createP("- Add more words using the 'add' button");
    h6 = createP("- Reset the canvas using the 'reset' button");
    h10 = createP("- Watch how words change over time using the 'play' button");


    h7 = createP("LEGEND:")
    h8 = createP("Red = low variance over time");
    h9 = createP("Blue = high variance over time");
    h11 = createP("Purple = somewhere in between, depending on the shade");


    h1.position(850, 0);
    h2.position(850, 50);
    h3.position(850, 70);
    h4.position(850, 90);
    h5.position(850, 110);
    h6.position(850, 130);
    h10.position(850, 150);

    h7.position(850, 180);
    h8.position(850, 200);
    h9.position(850, 220);
    h11.position(850, 240);
    
    h1.elt.style.fontSize = "xx-large";

   Events.on(engine, 'afterUpdate', function(event) {
         
        paragraph.elt.innerText = "SIGGRAPH Yearly Conferences: Paper Titles and Abstracts";

        //calculate and scale words depending on frequency at current point in time
        for (var i = 0; i<words.length; i++){
            var previous = words[i].frequency[current[z-1]];
            if (previous==null){
                previous = words[i].frequency[0];
            }
            var scaling = words[i].frequency[slider2.value()];

            var alpha = 0.865;
            var targetH = (scaling*maxFont)/0.007; // siggraph data
            var newH = words[i].height*alpha + targetH*(1-alpha);
            var scale = newH/words[i].height;

            //var scale = 1;


             if (scaling == 0){
                scale = 0.95;
            }

            //if (scaling == previous){
              //  scale = 1;
            //}


           /* 
            if (target!=0){
                words[i].step[z] += target/100;
                scale = 1 + target;
            }
*/
           

    // SOFT BODY WORDS
    /*
            if ((words[i].r < words[i].maxR && scale > 1) || (words[i].r > words[i].minR && scale < 1)){
                for (var j=0; j<words[i].body.constraints.length; j++){
                    words[i].body.constraints[j].length *= scale;
                }

                Composite.scale(words[i].body, scale, scale, {
                    x: words[i].body.bodies[Math.floor(words[i].body.bodies.length/2)].position.x,
                    y: words[i].body.bodies[Math.floor(words[i].body.bodies.length/2)].position.y
                });
                words[i].r *= scale;
                // words[i].r = words[i].r*alpha + (1-alpha)*target;
            }
    */

    //RIGID BODY WORDS



            if ((words[i].size < words[i].maxSize && scale > 1) || (words[i].size > words[i].minSize && scale < 1)){
                    
                Body.scale(words[i].body, scale, scale);
                words[i].width *= scale;
                words[i].height *= scale;
                words[i].size *= scale*scale;

            }


            if (words[i].body.angle > Math.PI/2) {
                Body.setAngularVelocity(words[i].body, -0.02);
            }
            if (words[i].body.angle < -Math.PI/2){
                Body.setAngularVelocity(words[i].body, 0.02)
            }

        }
        

    });
    
    //increment slider every second when play is on
    setInterval(function(){if (x<slider2.elt.max){ x++;}}, 1000);


    for (var q=0; q<23; q++){
        write();
    }


}


function play(){

    if (playing == false){
        button3.elt.innerHTML = "pause";
        playing = true;
        x = current[z];
    }
    else{
        button3.elt.innerHTML = "play";
        playing = false;
        x = slider2.elt.max;

    }

}


//add bodies to world
function write(){
    //add words 
    words.push(new wordBox(Math.random()*(800)-400, 0, input[a], maxFont  + "px impact", maxFont));


    var limit = 44;
    for (var i=0; i<limit; i++){
        maxArray[i] = 0;
        for (var j=0; j<words.length; j++){
            if (words[j].frequency[i] > maxArray[i]){
                maxArray[i] = words[j].frequency[i];
            }
        }
    }

    a++;
}

//reset world
function reset(){
    for (var i=0; i<words.length; i++){
        words[i].graphics.clear();
        World.remove(world, words[i].body);
    }
   
    words = [];
    a=0;
    x=0;

    playing = false;
}


//loops this function over and over, draws onto canvas
function draw(){

    if (playing == true){
        slider2.value(x);
     }
    
    background(255);
    scale(zoom);


    for (var i = 0; i<words.length; i++){
        words[i].show(); 
    }
    
    var beta = -4*zoom*zoom*zoom + 15*zoom*zoom - 17.5*zoom + 6.5;

    Mouse.setOffset(mouse, {x: -400 + (mouse.position.x*zoom)*beta, y: -187.5 + (mouse.position.y*zoom)*beta});


    textFont(times);
    fill(0);
    textSize(100/zoom);
    var number = slider2.value()+1974;
    text(number, 200/zoom,175/zoom);
    text(number, 200/zoom,175/zoom);

    
    
}

function mouseWheel(event) {
  zoom += sensitivity * event.delta;
  zoom = constrain(zoom, zMin, zMax);
  //uncomment to block page scrolling
  return false;
}




