//PCS 6th - (Hicks & Wood) Your job is to fill it the reflected points to complete the pattern

void draw() {
  background(255);
  drawCoordinateSystem();

  //These are the starting points
  int[] points = {
    75, 75, 
    125, 0, 
    205, 35, 
    95, 95, 
    35, 205, 
    0, 125
  };

  //These should be the points reflected vertically - they are wrong!
  //TODO: Fill them in with the correct points and the pattern will be complete!
  //be sure to include the commas
  int[] points_vertical = {
    10, -10,
    20, -20 ,
    30, -30,
    40, -40,
    50, -50, 
    60, -0
  };

  //These should be the points reflected horizontally - they are wrong!
  //TODO: Fill them in with the correct points and the pattern will be complete!
  //be sure to include the commas
  int[] points_horizontal = {
   -20, 30,
    -40, 40 ,
    -60, 100,
    -80, 80,
    -90, 100, 
    -60, 0
  };


  //Leave this here!
  drawObjects(points, points_vertical, points_horizontal);


}

ArrayList<Point> arrayListFromArray(int[] points) {
  ArrayList<Point> p = new ArrayList<Point>();
  for (int i = 0; i + 1 < points.length; i += 2) {
    p.add(new Point(points[i], points[i + 1]));
  }
  return p;
}

void translateReflections(int x, int y, int[] points, int[] points_v, int[] points_h) {
  translateReflections(x, y, points, points_v, points_h, 100);
}

void translateReflections(int x, int y, int[] points, int[] points_v, int[] points_h, int alpha) {

  ArrayList<Point> p = arrayListFromArray(points);
  ArrayList<Point> p_h = arrayListFromArray(points_h);
  ArrayList<Point> p_v = arrayListFromArray(points_v);

  boolean isCorrect = check(p, p_h, p_v, false);
  if (!isCorrect) {
    check(p, p_h, p_v, true);
  } else {
    fill(255, 0, 0, alpha);

    drawObject(p, x, y);

    fill(0, 255, 0, alpha);
    drawObject(p_h, x, y);

    fill(0, 0, 255, alpha);
    drawObject(p_v, x, y);

    fill(255, 255, 0, alpha);
    drawObject(verticalReflection(p_h), x, y);
  }
}

void drawObjects(int[] points, int[] points_v, int[] points_h) {
  ArrayList<Point> p = arrayListFromArray(points);
  ArrayList<Point> p_h = arrayListFromArray(points_h);
  ArrayList<Point> p_v = arrayListFromArray(points_v);

  // Draw the expected reflections
  boolean isCorrect = check(p, p_h, p_v, true);
}

boolean checkPoints(ArrayList<Point> p, ArrayList<Point> p_correct, 
  boolean isHorizontal) {
  if (p.size() != p_correct.size()) {
    return false;
  }

  boolean isCorrect = true;

  for (int i = 0; i < p.size(); i++) {
    Point p1 = p.get(i);
    Point p2 = p_correct.get(i);
    if (p1.x != p2.x || p1.y != p2.y) {
      isCorrect = false;
    }
  }

  return isCorrect;
}

boolean check(ArrayList<Point> p, ArrayList<Point> p_h, ArrayList<Point> p_v, 
  boolean shouldDraw) {
  ArrayList<Point> p_v_correct = verticalReflection(p);
  ArrayList<Point> p_h_correct = horizontalReflection(p);

  boolean correctH = checkPoints(p_h, p_h_correct, true);
  boolean correctV = checkPoints(p_v, p_v_correct, false);


  // Draw the original
  if (shouldDraw) {

    fill(255, 0, 0, 200);
    drawObject(p, 0, 0);

    if (!correctH) {
      noFill();
      strokeWeight(3.0);
      stroke(255, 0, 0);
      drawObject(p_h, 0, 0);
      noStroke();

      fill(0, 255, 0);
      drawObject(p_h_correct, 0, 0);
    } else {
      fill(0, 255, 0);
      drawObject(p_h, 0, 0);
    }

    if (!correctV) {
      noFill();
      strokeWeight(3);
      stroke(255, 0, 0, 255);
      drawObject(p_v, 0, 0);
      noStroke();

      fill(0, 0, 255, 100);
      drawObject(p_v_correct, 0, 0);
    } else {
      fill(0, 0, 255, 200);
      drawObject(p_v, 0, 0);
    }

    if (correctH && correctV) {
      fill(255, 255, 0, 200);
      drawObject(verticalReflection(p_h_correct), 0, 0);
    }
  }

  return correctV && correctH;
}

void mouseClicked() {
  int x = mouseX;
  x = x - gWidth/2;
 
  int y = mouseY;
  y = -1 * (y - gHeight/2);
 
  System.out.println(x + ", " + y);
}

void drawObject(ArrayList<Point> vertices, int translateX, int translateY) {
  beginShape();
  for (int i = 0; i < vertices.size(); i++) {
    vertex(centeredX(vertices.get(i).x + translateX), 
      centeredY(vertices.get(i).y + translateY));
  }
  vertex(centeredX(vertices.get(0).x + translateX), 
    centeredY(vertices.get(0).y + translateY));
  endShape();
}

ArrayList<Point> verticalReflection(ArrayList<Point> p) {
  ArrayList<Point> p_v = new ArrayList<Point>();
  for (int i = 0; i < p.size(); i++) {
    p_v.add(new Point(p.get(i).x, -1 * p.get(i).y));
  }
  return p_v;
}

ArrayList<Point> horizontalReflection(ArrayList<Point> p) {
  ArrayList<Point> p_v = new ArrayList<Point>();
  for (int i = 0; i < p.size(); i++) {
    p_v.add(new Point(-1 * p.get(i).x, p.get(i).y));
  }
  return p_v;
}

float centeredX(float x) {
  return x + gWidth/2.0;
}

float centeredY(float y) {
  // inverted y
  return -1 * y + gHeight/2.0;
}

void drawCoordinateSystem() {
  stroke(0);
  strokeWeight(1);
  int lineLength;

  int tickMark = 0;
  for (int x = (int) 0; x < (int)gWidth / 2; x += 10, tickMark++) {
    lineLength = 2;
    if (tickMark == 5) {
      lineLength = 5;
      tickMark = 0;
    }
    if (gWidth/2 - x > 0) {
      line(gWidth/2 - x, gHeight/2 - lineLength, gWidth/2 - x, gHeight/2 + lineLength);
    }
    if (gWidth/2 + x < gWidth) {
      line(gWidth/2 + x, gHeight/2 - lineLength, gWidth/2 + x, gHeight/2 + lineLength);
    }
  }

  tickMark = 0;
  for (int y = (int) 0; y < (int)gHeight / 2; y += 10, tickMark++) {
    lineLength = 2;
    if (tickMark == 5) {
      lineLength = 5;
      tickMark = 0;
    }
    if (gHeight/2 - y > 0) {
      line(gWidth/2 - lineLength, gHeight/2 - y, gWidth/2 + lineLength, gHeight/2 - y);
    }
    if (gHeight/2 + y < gHeight) {
      line(gWidth/2 - lineLength, gHeight/2 + y, gWidth/2 + lineLength, gHeight/2 + y);
    }
  }

  line(0, gHeight/2.0, gWidth, gHeight/2.0);
  line(gWidth/2.0, 0, gWidth/2.0, gHeight);
  noStroke();
}

public class Point {
  int x;
  int y;
  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }

  Point(float x, float y) {
    this.x = (int) x;
    this.y = (int) y;
  }
}

void setup() {
  size(500, 800);
  noStroke();
  noLoop();

  if (true) {
    gHeight = height;
    gWidth = width;
  } else {
    gHeight = screen.height;
    gWidth = screen.width;
  }
}

int gWidth, gHeight;