// Change ITEMS for amount of bars.
let ITEMS = 100;
// Grab canvas and context.
let canvas = document.getElementById('display');
let context = canvas.getContext('2d');
// Declare array to be ITEMS long.
let list;
// Flags used to determine if bg or bars need redrawn.
let updateBG = true;
let updateBars = true;

function keyPressed(event){
  //console.log(event);
  if(event.keyCode==40){
    sortDelay-=10;
    if(sortDelay<=0) 
      sortDelay=0;
    console.log("down "+sortDelay);
  }
  if(event.keyCode==38){
    sortDelay+=10;
    console.log("up "+sortDelay);
  }
  if(event.keyCode==37){
    console.log("left");
  }
  if(event.keyCode==39){
    console.log("right");
  }
}

// Setup event listeners for window.
function setupCanvas() {
    // Setup event listeners for load and window resize.
  window.addEventListener('load', canvasResize);
  window.addEventListener('resize', canvasResize);
  window.addEventListener('keypress', keyPressed);
}

// Initializes the list of 100 random numbers.
function initList() {
  list = new Array(ITEMS);
  for (let i = 0; i < ITEMS; i++)
    list[i] = Math.round(Math.random() * 100);
}

// This function grabs the width and height of the window
// and resizes the canvas  in the event of loading or resizing.
function canvasResize() {
  canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    // removed the following two lines to make printing text work properly (not inverted)
  //context.translate(0, canvas.height);
  //  context.scale(1, -1);
  updateBG = true;
  updateBars = true;
}

// Finds the largest number in the list.
function max() {
  let maximum = list[0];
  for (let i = 1; i < ITEMS; i++)
    maximum = list[i] > maximum ? list[i] : maximum;
  return maximum;
}

// Comparing indicators to draw in different colors.
let cmp1 = 0;
let cmp2 = 0;

// Plot each index of list[].
function plotBars() {

  let length = list.length;
  let barWidth = canvas.width / length;
  let barScale = canvas.height / max();
  for (let i = 0; i < ITEMS; i++) {
    let x = i * barWidth;
    let h = list[i] * barScale;
    let y = canvas.height - h;
    
    context.save();
    if (i == cmp1 || i == cmp2)
      context.fillStyle = 'white';
    else if (i == -cmp1 || i == -cmp2)
      context.fillStyle = 'yellow';
    else
      context.fillStyle = 'orange';
    context.fillRect(x+1, y, barWidth-2, h);
    context.restore();
  }
}

let comparison_count=0;
let swap_count=0;
let gap = ITEMS
// Draws the black background.
function drawBackground() {
  // Save context to stack.
  context.save();
  context.fillStyle = 'black';
  context.fillRect(0, 0, canvas.width, canvas.height);
  // Pops most recently saved canvas state off stack.
  context.restore();

    context.fillStyle = 'grey';
    context.font = "30px Ariel";
    context.fillText("Shell Sort, " + ITEMS + " numbers", 30, 25);
    
    context.fillStyle = 'white';
    context.fillText('bars being compared - white', 30, 50);
    context.fillStyle = 'yellow';
    context.fillText('bars being swapped - yellow', 30, 75);
    
    context.fillStyle = 'grey';
    context.fillText('# comparisons so far - ' + comparison_count, 30, 100);
    context.fillText('# swaps so far - ' + swap_count, 30, 125);
    context.fillText('Current Gap - ' + gap, 30, 150);
    context.fillText('Current sortDelay - ' + sortDelay, 30, 175);
}


// These are some variables that flag and alter various parts 
// of the sort. You may need to add/remove/modify your own 
// depending on the  complexity of your sorting method.
let sortStarted = false;
let sortFinished = false;
// Delay between sorting simulations.
let restartDelay = 5000;
// Delay between comparasins.
let sortDelay = 0;
let sortIndex = 0;
let check=ITEMS;
let lastSwap=ITEMS;
let ran=0

// Sorting function. This example uses bubble sort.
function sortStart() {
  comparison_count=0;
  swap_count=0;
  gap=ITEMS;
  check=ITEMS;
  // Finished is used to mark when no swaps were done in a sort loop.
  // Think of it as finishing one sorting loop.
  let finished = false;
  // tmp is used as a temporary value when swapping.
  let tmp;  
  // Flip the sortStarted flag.
  sortStarted = true;
  
  gap = Math.floor(gap / 2)
  if (gap <= 1) {
      // for gap=1, keep track of if there were any swaps
      gap = 1
      finished = true
  }

  
  // setInterval() runs once every <sortDelay>
  let sortLoop = setInterval(function() {
      // If left > right, swap
      comparison_count++;
      cmp1 = sortIndex
      cmp2 = sortIndex + gap;
      
      if (cmp2 < ITEMS &&
          list[cmp1] > list[cmp2]) {
          
      // Keep setting finished just to be safe.
      finished = false;
      swap_count++;
      lastSwap=cmp2;
      // ol-switcharoo
      tmp = list[cmp2];
      list[cmp2] = list[cmp1];
      list[cmp1] = tmp;
          cmp1 *= -1; // flags that a swap is being done
          cmp2 *= -1; // flags that a swap is being done
      
    }
      // Flag that the background and bars need updating.
      updateBG = true;
      updateBars = true;
      
    sortIndex++;
    
    // Reached end of list.
    // If list has been scanned once with no swaps, 
    // sortFinish will be set and sort will end.
    // Otherwise start over from 1.
    let r = true;
    finished=true;
    for(let i=1;i<ITEMS;i++){
       if(list[i]<list[i-1]){
         finished=false;
         r=false;
       }
    }
    
    if (sortIndex + gap >= check || r) {
        if (finished) {
            lastSwap=ITEMS
            ran=0;
            sortFinished = true;
            clearInterval(sortLoop);
        } 
        sortIndex = 0;

        gap = Math.floor(gap / 2)
        if (gap <= 1) {
            if(ran==2){
              check=lastSwap;
            }
            else ran++
            //console.log(check)
            gap = 1;
            finished = true;
        }
    }
      // Repeat once every <sortDelay>.
  }, sortDelay);


}



// Setup initializes the canvas as well as the list of random nums.
function setup() {
  setupCanvas();
  initList();
}

// loopBlock is briefly enabled when sorting has finished to give a view of the finished sort.
let loopBlock = false;
function loop() {
  if (!loopBlock) {
    // If background needs updated, redraw background.
    if (updateBG) {
      updateBG = false; 
      drawBackground();
    }
    // If bars need updated, replot.
    if (updateBars) {
      updateBars = false;
      plotBars();
    }
    
    // Starts the sort if it isn't looping already.
    if (!sortStarted)
      sortStart();
    // Checks if sort has completed. Briefly blocks looping while re-initializing the list, sortStarted, and sortFinished variables.
    if (sortFinished) {
      loopBlock = true;
      setTimeout(function() {
        initList();
        sortStarted = false;
        sortFinished = false;
        loopBlock = false;
      }, restartDelay);
    }
  }
}

// Main function which runs the setup and holds the main infinite loop.
(function main() {
  // Setup the canvas and list.
  ITEMS=prompt("How many items would you like to sort","100")
  setup();
  (function mainLoop() {
    loop();
    // requestAnimationFrame calls mainLoop infinitely
    requestAnimationFrame(mainLoop);
  })();
})();