let serial;
let data;
let brushColor;
let prevX, prevY;
let drawingStyle = 0;
let started = false;
let startButton;
let saveButton;
let clearButton;
let backgroundImage;

// Moving average filter variables
const filterSize = 5;
const gxValues = new Array(filterSize).fill(0);
const gyValues = new Array(filterSize).fill(0);
const gzValues = new Array(filterSize).fill(0);
let filterIndex = 0;

function preload() {
  backgroundImage = loadImage('drawingprojectbackground.png');
}

function movingAverage(newVal, values) {
  values[filterIndex] = newVal;
  filterIndex = (filterIndex + 1) % filterSize;
  let avg = values.reduce((a, b) => a + b) / filterSize;
  return avg;
}

function setup() {
  createCanvas(windowWidth, windowHeight);
  colorMode(RGB, 255);
  background(255);

  startButton = createButton('Start');
  startButton.position(width / 2 - startButton.width / 2, height / 2 + 50);
  startButton.mousePressed(startDrawing);

  serial = new p5.SerialPort();
  // serial.list();
  serial.open("/dev/tty.usbmodem11101");
  serial.on("connected", serverConnected);
  serial.on("list", gotList);
  serial.on("data", gotData);
  serial.on("error", gotError);
  serial.on("open", gotOpen);
  serial.on("close", gotClose);
}

function serverConnected() {
  print("Connected to Server");
}

function gotList(thelist) {
  print("List of Serial Ports:");

  for (let i = 0; i < thelist.length; i++) {
    print(i + " " + thelist[i]);
  }
}

function gotError(theerror) {
  print(theerror);
}

function gotOpen() {
  print("Serial Port is Open");
}

function gotClose() {
  print("Serial Port is Closed");
  latestData = "Serial Port is Closed";
}

function gotData() {
  let incomingData = serial.readLine();
  if (incomingData) {
    print("Incoming data: " + incomingData);
    let dataParts = incomingData.split(",");
    if (dataParts.length === 3) {
      data = {
        gx: movingAverage(parseInt(dataParts[0]), gxValues),
        gy: movingAverage(parseInt(dataParts[1]), gyValues),
        gz: movingAverage(parseInt(dataParts[2]), gzValues),
      };

      // Update the brush color based on the gyroscope data
      let r = map(data.gx, -32768, 32767, 0, 255);
      let g = map(data.gy, -32768, 32767, 0, 255);
      let b = map(data.gz, -32768, 32767, 0, 255);
      brushColor = color(r, g, b);
      print("Brush color: " + brushColor);
    }
  }
}

function drawWelcomeScreen() {
  image(backgroundImage, 0, 0, width, height);
  textSize(32);
  textAlign(CENTER, CENTER);
  text("Welcome to the Embodied Interactions Drawing Project", width / 2, height / 2 - 50);
  textSize(24);
  text("Put on your glove, then press the button below to start.", width / 2, height / 2);
}

function startDrawing() {
  started = true;
  background(255);
  startButton.hide();
 
  // Create drawing style buttons
    let style1Button = createButton("Drawing Style 1");
  style1Button.position(20, 20);
  style1Button.mousePressed(() => {
    drawingStyle = 0;
  });

  let style2Button = createButton("Drawing Style 2");
  style2Button.position(20, 60);
  style2Button.mousePressed(() => {
    drawingStyle = 1;
  });
  
   let style3Button = createButton("Drawing Style 3");
  style3Button.position(20, 140);
  style3Button.mousePressed(() => {
    drawingStyle = 2;
  });

  // Create the save button
  saveButton = createButton("Save");
  saveButton.position(width - saveButton.width - 20, 20);
  saveButton.mousePressed(saveDrawing);
  
    clearButton = createButton("Clear");
clearButton.position(20, 100);
clearButton.mousePressed(clearDrawing);
}

function draw() {
  if (!started) {
    drawWelcomeScreen();
  } else {
    if (brushColor) {
      // Map gyroscope values to canvas coordinates
      let x = map(data.gx, -32768, 32767, 0, width);
      let y = map(data.gy, -32768, 32767, 0, height);
      let brushSize = map(data.gz, -32768, 32767, 5, 50);

      if (prevX !== undefined && prevY !== undefined) {
        if (drawingStyle === 0) {
          drawStyle1(x, y);
        } else if (drawingStyle === 1) {
          drawStyle2(x, y, brushColor, brushSize);
      }

    else if (drawingStyle === 2) {
          drawStyle3(x, y, brushColor, brushSize);
        }
      }
      // Update the previous position
      prevX = x;
      prevY = y;
    }
  }
}
function drawStyle1(x, y) {
  let brushSize = map(data.gz, -32768, 32767, 5, 50);
  let numParticles = map(data.gz, -32768, 32767, 5, 30);
  let diff = brushSize / 2;

  // Draw particles with different sizes, colors, and opacities
  for (let i = 0; i < numParticles; ++i) {
    let r = red(brushColor);
    let g = green(brushColor);
    let b = blue(brushColor);
    let a = random(10, 150); // Adjust the opacity

    let offsetX = random(-diff, diff);
    let offsetY = random(-diff, diff);
    let weight = random(brushSize * 0.3, brushSize * 0.8);

    let angle = random(TWO_PI);
    let distance = random(brushSize * 0.2, brushSize * 1.5);

    let particleX = x + offsetX + cos(angle) * distance;
    let particleY = y + offsetY + sin(angle) * distance;

    noStroke();
    fill(color(r, g, b, a));
    ellipse(particleX, particleY, weight, weight);
  }
}

function drawStyle2(x, y, brushColor, brushSize) {
  let numLayers = map(brushSize, 5, 50, 3, 10);
  let layerAlpha = 30;
  let layerSpread = brushSize / 2;

  for (let i = 0; i < numLayers; ++i) {
    let offsetX = random(-layerSpread, layerSpread);
    let offsetY = random(-layerSpread, layerSpread);
    let layerColor = color(red(brushColor), green(brushColor), blue(brushColor), layerAlpha);
    
    noStroke();
    fill(layerColor);

    let layerWidth = random(brushSize * 0.5, brushSize * 1.5);
    let layerHeight = random(brushSize * 0.5, brushSize * 1.5);
    let layerRotation = random(0, TWO_PI);
    
    push();
    translate(x + offsetX, y + offsetY);
    rotate(layerRotation);
    ellipse(0, 0, layerWidth, layerHeight);
    pop();
  }
}

function drawStyle3(x, y) {
  let numLines = map(data.gz, -32768, 32767, 5, 30);
  let brushSize = map(data.gz, -32768, 32767, 1, 10);
  let lineLength = map(data.gz, -32768, 32767, 5, 50);

  for (let i = 0; i < numLines; ++i) {
    let angle = random(TWO_PI);
    let startX = x + cos(angle) * brushSize;
    let startY = y + sin(angle) * brushSize;
    let endX = startX + cos(angle) * lineLength;
    let endY = startY + sin(angle) * lineLength;

    stroke(brushColor);
    strokeWeight(brushSize);
    line(startX, startY, endX, endY);
  }
}

function clearDrawing() {
  background(255);
}

function saveDrawing() {
  saveCanvas("myDrawing", "png");
}