//AUTHOR: William Ye
//TITLE: Midterm

int sw, sh;
PFont font;
int numberOfStars = 100;
Star[] stars;
Tree tree;
Moon moon;
boolean day; //checks whether its day or nite
Sun sun;
Button dayButton; //these two toggle between day/nite
Button niteButton;
Button quitButton; //quits
Button restartButton; //restarts bird/witch
Witch witch;
Bird bird;
Jellyfish jellyfish;

void setup() {
  sw = displayWidth;
  sh = displayHeight;
  
  size(sw, sh);
  
  rectMode(CENTER);
  textAlign(CENTER, CENTER);
  noStroke();
  strokeWeight(10);
  
  font = createFont("Segoe UI Light", 10);
  textFont(font);
  
  stars = new Star[numberOfStars];
  randomizeStarPosition();
  
  tree = new Tree(sw/2 - 200, sh/2);
  moon = new Moon(0, sh/4);
  sun = new Sun(0, sh/4);
  
  dayButton = new Button(sw - 500, sh - 300, "DAY");
  niteButton = new Button(sw - 250, sh - 300, "NITE");
  quitButton = new Button(sw - 500, sh - 150, "QUIT");
  restartButton = new Button(sw - 250, sh - 150, "WITCH");
  
  day = false;
  
  witch = new Witch();
  bird = new Bird();
  jellyfish = new Jellyfish();
}

void randomizeStarPosition() {
  for (int i = 0; i < stars.length; i++) {
    stars[i] = new Star(random(sw), random(sh));
  }
}

void draw() {
  clearBackground();
  drawBackground();
  drawSeaEntities();
  drawOcean();
  drawFlyingEntities();
  drawBorder();
  drawButtons();
  drawInfo();
}

void drawSeaEntities() {
  jellyfish.update();
  jellyfish.draw();
}

void drawOcean() {
  fill(0, 255, 255, 100);
  rect(sw/2, sh - 100, sw, 200);
}

void clearBackground() {
  if (!day) {
    background(200, 155, 200);
  } else {
    background(94, 234, 255);
  }
}

void drawFlyingEntities() {
  if (!day) {
    witch.update();
    witch.draw();
  } else {
    bird.update();
    bird.draw();
  }
}

void drawInfo() { //displays what this abomination is, and who made it
  fill(255, 255, 255);
  textSize(50);
  text("CST 112 Midterm", sw/2, 100);
  textSize(20);
  text("Author: William Ye", 100, sh - 30);
}

void drawButtons() {
  //changes restart button based on day/night
  if (!day) {
    restartButton.text = "WITCH";
  } else {
    restartButton.text = "BIRD";
  }
  restartButton.draw();
  dayButton.draw();
  niteButton.draw();
  quitButton.draw();
}

void drawBorder() {
  stroke(0, 0, 0);
  
  //horizontal border
  for (int i = 0; i < sw; i += 100) {
    fill(255, 145, 0);
    ellipse(i, 0, 100, 100);
    ellipse(i, sh, 100, 100);
  }
  
  //vertical border
  for (int i = 0; i < sh; i += 100) {
    fill(255, 145, 0);
    ellipse(0, i, 100, 100);
    ellipse(sw, i, 100, 100);
  }
  
  noStroke();
}

void drawBackground() {
  if (!day) {
    //moon
    moon.update();
    moon.draw();
    
    //stars
    for (Star s : stars) {
      s.update();
      s.draw();
    }
  } else {
    sun.update();
    sun.draw();
  }
  
  //hills
  fill(138, 89, 216);
  ellipse(sw/4, sh, 1000, 1000);
  
  colorizeShadow();
  ellipse(sw*2/3 - 10, sh, 700, 700);
  fill(138, 89, 216);
  ellipse(sw*2/3, sh, 700, 700);
  
  //tree
  tree.draw();

}

class Jellyfish {
  float x, y, sx, sy, angle;
  boolean rising;
  float animationTimer;
  boolean swingLeft;
  
  Jellyfish() {
    x = random(sw);
    y = sh - 100;
    newAngle();
    rising = true;
    swingLeft = true;
    animationTimer = 25;
  }
  
  void newAngle() { //creates a new direction to travel
    angle = random(-PI/2 - 0.5, -PI/2 + 0.5); 
    sx = cos(angle) * 3;
    sy = sin(angle) * 1;
  }
  
  void update() {
    x += sx;
    y += sy;
    
    if (x <= 0 || x >= sw) { //prevents it from traveling outside the screen
      sx*=-1;
    }
    
    if (y <= sh - 200) { //makes the jelly fish bob up and down
      sy *= -1;
      rising = false;
    }
    if (y >= sh) {
      newAngle();
      rising = true;
    }
    
    animationTimer--; //handles the jellyfish animation
    if (animationTimer <= 0) {
      animationTimer = 25;
      if (swingLeft) {
        swingLeft = false; //swing left as in tentacles swinging left
      } else {
        swingLeft = true;
      }
    }
  }
  
  void draw() {
    fill(255, 0, 255);
    
    //head
    ellipse(x, y, 30, 30);
    //body
    rect(x, y + 15, 30, 30);
    //tentacles
    stroke(255, 0, 255);
    strokeWeight(1);
    for (float i = x - 15; i <= x + 15; i += 30/8) {
      if (rising) { //if it's rising move the tentacles
        if (!swingLeft) { 
          line(i, y + 30, i + 5, y + 50);
        } else {
          line(i ,y + 30, i - 5, y + 50);
        }
      } else { //if its not stay stationary
        line(i, y + 30, i, y + 50);
      }
    }
    strokeWeight(10);
    noStroke();
    
    
  }
}

class Witch extends FlyingEntity {
  
  Witch() {
    super();
  }
  
  void draw() {
    //leg 1
    stroke(0, 255, 0);
    line(x - 10, y + 45, x - 15, y + 85);
    noStroke();
    //body
    fill(128, 36, 0);
    rect(x , y, 70, 100); 
    //head
    fill(255, 0, 0);
    ellipse(x, y - 70, 50, 50);
    //hat
    fill(30, 30, 30);
    rect(x, y - 90, 60, 15);
    triangle(x - 20, y - 90, x - 10, y - 110, x + 20, y - 90);
    //broom handle
    stroke(82, 41, 0);
    line(x - 80, y + 50, x + 100, y + 50);
    line(x - 80, y + 20, x - 80, y + 80);
    //bristles
    for (int i = 20; i <= 80; i += 20) {
      line(x - 80, y + i, x - 110, y + i);
    }
    //leg 2
    stroke(0, 255, 0);
    line(x + 10, y + 45, x + 25, y + 90);
    noStroke();
  }
}

class Bird extends FlyingEntity {
  Bird() {
    super();
  }
  
  void draw() {
    fill(183, 0, 255);
    triangle(x, y, x + 60, y - 10, x, y - 20); //makes the bird
    triangle(x, y + 20, x + 40, y - 10, x, y - 40);
  }
}

class FlyingEntity {
  float x, y, sx, sy, angle;
  
  FlyingEntity() {
    reset();
  }
  
  void reset() {
    x = -200;
    y = random(sh);
    angle = random(-0.5, 0.5); //finds a random angle to travel at
    sx = cos(angle)*5;
    sy = sin(angle)*5;
  }
  
  void update() {
    x += sx;
    y += sy;
    
    if (x > sw + 200) {
      reset();
    }
  }
}

void mousePressed() {
  //checks if buttons are pressed
  if (quitButton.selected()) {
    exit();
  } else if (dayButton.selected()) {
    day = true;
  } else if (niteButton.selected()) {
    day = false;
  } else { //restart button
    witch.reset();
    bird.reset();
  }
}

class Button {
  float x, y, w, h;
  String text;
  
  Button(float x, float y, String text) {
    this.x = x;
    this.y = y;
    this.text = text;
    w = 200;
    h = 100;
  }
  
  
  void draw() {
    if (selected()) { //gives the button a blue-ish tinge when selected
      fill(0, 0, 255, 100);
    } else {
      fill(0, 0, 0, 150);
    }
    rect(x, y, w, h);
    textSize(30);
    fill(255, 255, 255);
    text(text, x, y);
  }
  
  boolean selected() { //checks if it's currently being selected
    if (mouseX > x - w/2 && mouseX < x + w/2 && mouseY > y - h/2 && mouseY < y + h/2) {
      return true;
    } else {
      return false;
    }
  }
}

class Tree {
  float x, y;
  
  Tree(float x, float y) {
    this.x = x;
    this.y = y;
  }
  
  void draw() {
    fill(125, 48, 0);
    //roots
    triangle(x - 30, y + 50, x, y + 30, x, y); 
    triangle(x + 20, y + 50, x, y + 30, x, y);
    triangle(x + 50, y + 40, x, y + 30, x, y);
    
    //trunk
    quad(x - 10, y + 30, x + 10, y + 20, x + 7, y - 190, x - 12, y - 170);  
    
    //branches
    quad(x, y - 90, x - 80, y - 140, x - 70, y - 140, x, y - 120);
    quad(x, y - 90, x + 80, y - 140, x + 70, y - 140, x, y - 120);
    
    fill(20, 156, 45);
    ellipse(x, y - 230, 300, 200);
  }
}

class Moon extends CelestialBody {
  Moon(float x, float y) {
    super(x, y);
  }
  
  void draw() {
    fill(255, 255, 255); //a white circle with a little bit cut out so it's crescent shaped
    ellipse(x, y, 100, 100);
    fill(200, 155, 200);
    ellipse(x- 50, y, 100, 100);
  }
}

class Sun extends CelestialBody {
  Sun(float x, float y) {
    super(x, y);
  }
  
  void draw() {
    fill(255, 255, 0); //little yellow orb
    ellipse(x, y, 70, 70);
  }
}

class CelestialBody { //sun, moon etc
  float x, y, sx;
  
  CelestialBody(float x, float y) {
    this.x = x;
    this.y = y;
    sx = 1;
  }
  
  void update() {
    x += sx;
    if (x - 50 > sw) { //resets it back to the left
      x = -50;
    }
  }

}

class Star {
  float x, y, diameter, ds; //ds = diameter speed
  
  Star(float x, float y) {
    this.x = x;
    this.y = y;
    diameter = (int)random(5);
    ds = 0.1;
  }
  
  void draw() {
    fill(255, 255, 255);
    ellipse(x, y, diameter, diameter);
  }
  
  void update() { //makes the star pulse
    diameter += ds;
    if (diameter >= 5 || diameter <= 0) {
      ds*=-1;
    }
  }
}

void colorizeShadow() {
  fill(0, 0, 0, 100);
}


boolean sketchFullScreen () {
  return true;
}