import processing.serial.*;

Serial myPort;

float temperature = 0;
float humidity = 0;

float displayTemperature = 0;
float displayHumidity = 0;

String status = "Waiting data...";

void setup() {
  size(600, 420);
  println(Serial.list());

  myPort = new Serial(this, "/dev/cu.usbmodem1101", 115200);
  myPort.bufferUntil('\n');

  textAlign(CENTER, CENTER);
}

void draw() {
  background(245);

  // Smooth animation
  displayTemperature += (temperature - displayTemperature) * 0.08;
  displayHumidity += (humidity - displayHumidity) * 0.08;

  fill(0);
  textSize(24);
  text("Temperature & Humidity Monitor", width / 2, 35);

  // Status indicator moved to avoid thermometer overlap
  drawStatusIndicator(width / 2 - 55, 95);

  fill(80);
  textSize(14);
  text(status, width / 2 + 20, 95);

  drawThermometer(160, 320, displayTemperature);
  drawHumidityGauge(430, 210, displayHumidity);

  fill(0);
  textSize(18);
  text("Temperature: " + nf(temperature, 1, 1) + " °C", 160, 380);
  text("Humidity: " + nf(humidity, 1, 1) + " %", 430, 380);
}

void serialEvent(Serial p) {
  String data = p.readStringUntil('\n');

  if (data != null) {
    data = trim(data);
    println("Received: " + data);

    if (data.startsWith("TEMP:")) {
      try {
        String[] parts = split(data, ',');
        String tempPart = split(parts[0], ':')[1];
        String humPart = split(parts[1], ':')[1];

        temperature = float(tempPart);
        humidity = float(humPart);

        status = "Connected";
      } 
      catch (Exception e) {
        status = "Parse error";
      }
    } else if (data.equals("ERROR")) {
      status = "Sensor error";
    }
  }
}

void drawStatusIndicator(int x, int y) {
  noStroke();

  if (status.equals("Connected")) {
    fill(0, 180, 0);
  } else if (status.equals("Waiting data...")) {
    fill(230, 180, 0);
  } else {
    fill(220, 40, 40);
  }

  ellipse(x, y, 14, 14);
}

color getTemperatureColor(float temp) {
  if (temp < 15) {
    return color(40, 120, 220);
  } else if (temp <= 25) {
    return color(0, 170, 80);
  } else {
    return color(220, 40, 40);
  }
}

color getHumidityColor(float hum) {
  if (hum < 30) {
    return color(180, 110, 40);
  } else if (hum <= 60) {
    return color(0, 170, 80);
  } else {
    return color(40, 120, 220);
  }
}

void drawThermometer(int x, int y, float temp) {
  float tempConstrained = constrain(temp, 0, 50);
  float level = map(tempConstrained, 0, 50, 0, 220);

  color tempColor = getTemperatureColor(temp);

  stroke(0);
  strokeWeight(2);
  fill(255);
  rect(x - 18, y - 260, 36, 220, 18);

  fill(0);
  textSize(12);
  textAlign(LEFT, CENTER);

  for (int t = 0; t <= 50; t += 10) {
    float ty = map(t, 0, 50, y - 40, y - 260);

    stroke(0);
    strokeWeight(1);
    line(x + 22, ty, x + 35, ty);

    noStroke();
    text(t + "°C", x + 42, ty);
  }

  for (int t = 5; t < 50; t += 10) {
    float ty = map(t, 0, 50, y - 40, y - 260);

    stroke(120);
    strokeWeight(1);
    line(x + 22, ty, x + 30, ty);
  }

  noStroke();
  fill(tempColor);
  rect(x - 14, y - 40 - level, 28, level, 14);

  fill(tempColor);
  ellipse(x, y - 25, 65, 65);

  textAlign(CENTER, CENTER);
}

void drawHumidityGauge(int cx, int cy, float hum) {
  float humConstrained = constrain(hum, 0, 100);
  color humColor = getHumidityColor(hum);

  stroke(0);
  strokeWeight(2);
  fill(255);
  ellipse(cx, cy, 190, 190);

  textAlign(CENTER, CENTER);
  textSize(12);
  fill(0);

  for (int h = 0; h <= 100; h += 20) {
    float angle = map(h, 0, 100, PI, TWO_PI);

    float x1 = cx + cos(angle) * 78;
    float y1 = cy + sin(angle) * 78;

    float x2 = cx + cos(angle) * 88;
    float y2 = cy + sin(angle) * 88;

    float tx = cx + cos(angle) * 105;
    float ty = cy + sin(angle) * 105;

    stroke(0);
    strokeWeight(2);
    line(x1, y1, x2, y2);

    noStroke();
    text(h + "%", tx, ty);
  }

  for (int h = 10; h < 100; h += 20) {
    float angle = map(h, 0, 100, PI, TWO_PI);

    float x1 = cx + cos(angle) * 82;
    float y1 = cy + sin(angle) * 82;

    float x2 = cx + cos(angle) * 88;
    float y2 = cy + sin(angle) * 88;

    stroke(120);
    strokeWeight(1);
    line(x1, y1, x2, y2);
  }

  float angle = map(humConstrained, 0, 100, PI, TWO_PI);

  float needleX = cx + cos(angle) * 70;
  float needleY = cy + sin(angle) * 70;

  stroke(humColor);
  strokeWeight(4);
  line(cx, cy, needleX, needleY);

  noStroke();
  fill(0);
  ellipse(cx, cy, 10, 10);

  fill(humColor);
  textSize(22);
  text(nf(hum, 1, 1) + "%", cx, cy + 45);
}
