String SCANS = "/Users/matthewmcwilliams9/Desktop/running/shot1-scans";

int dotSize = 16;
File someFolder;
File[] someFolderList;
ArrayList<String> files = new ArrayList<String>();
String currentFile;
int filesCount;
int current = -1;
PImage img;
PImage copy;
int left = 0;
int top = 0;
ArrayList<Point> points = new ArrayList<Point>();
ArrayList<Line> lines = new ArrayList<Line>();

Frame A;
Frame B;
Frame C;
Frame D;

class Point {
  int x = 0;
  int y = 0;
  int xPerc;
  int yPerc;
  int xScaled;
  int yScaled;

  Point(int a, int b, int w, int h) {
    x = a;
    y = b;
    xPerc = round(map(x, 0, w, 0, 1000));
    yPerc = round(map(y, 0, h, 0, 1000));
  }
  void scale (int xMin, int xMax, int yMin, int yMax) {
    xScaled = round(map(xPerc, xMin, xMax, 0, 100));
    yScaled = round(map(yPerc, yMin, yMax, 0, 100));
  }
}

class Line {
  int x1;
  int y1;
  int x2;
  int y2;
  Line (int a, int b, int c, int d) {
    x1 = a;
    y1 = b;
    x2 = c;
    y2 = d;
  }
  void draw () {
    line(x1 + left, y1 + top, x2 + left, y2 + top);
  }
}

class Frame {
  PImage im;
  String which;

  Point leftTop;
  Point rightTop;
  Point leftBottom;
  Point rightBottom;
  
  int W;
  int H;
  
  Frame (String w, PImage a) {
    im = a;
    which = w;
  }
  
  public void try_all (ArrayList<Point> pointsEval) {
    Point p;
    int xMin = 1000000;
    int xMax = 0;
    int yMin = 1000000;
    int yMax = 0;

    float closest = im.width * im.height;
    float dists[] = new float[pointsEval.size()];
    
    int corner = -1;
    Point cornerP;
    
    int cornerShort = -1;
    Point cornerShortP;

    int cornerLong = -1;
    Point cornerLongP;

    int cornerDiag = -1;
    Point cornerDiagP;
    
    for (int i = 0; i < pointsEval.size(); i++) {
      p = pointsEval.get(i);
      if (p.xPerc > xMax) {
         xMax = p.xPerc; 
      }
      if (p.xPerc < xMin) {
        xMin = p.xPerc;
      }
      if (p.yPerc > yMax) {
        yMax = p.yPerc;
      }
      if (p.yPerc < yMin) {
        yMin = p.yPerc;
      }
    }
    
    for (int i = 0; i < pointsEval.size(); i++) {
      p = pointsEval.get(i);
      p.scale(xMin, xMax, yMin, yMax);
      
      if (which.equals("A")) {
        //bottom left
        if (p.xScaled < 2 && p.xScaled > -1 && p.yScaled > 98 && p.yScaled < 101) {
         corner = i;
        }
      } else if (which.equals("B")) {
        //top left
        if (p.xScaled < 2 && p.xScaled > -1 && p.yScaled > -1 && p.yScaled < 2) {
         corner = i;
        }
      } else if (which.equals("C")) {
        //top right
        if (p.xScaled < 101 && p.xScaled > 98 && p.yScaled > -1 && p.yScaled < 2) {
         corner = i;
        }
      } else if (which.equals("D")) {
        //bottom right
        if (p.xScaled < 101 && p.xScaled > 98 && p.yScaled > 98 && p.yScaled < 101) {
         corner = i;
        }        
      }
    }
    
    if (corner == -1) {
      println("Could not find corner");
      exit();
    }
    
    cornerP = pointsEval.get(corner);
    
    for (int i = 0; i < pointsEval.size(); i++) {
      p = pointsEval.get(i);
      if (i == corner) {
        dists[i] = im.width * im.height;
      } else {
        dists[i] = dist(cornerP.x, cornerP.y, p.x, p.y);
      }
    }
    
    for (int i = 0; i < pointsEval.size(); i++) {
      p = pointsEval.get(i);
      if (i != corner 
          && abs(cornerP.xScaled - p.xScaled) > 10
          && dists[i] < closest) {
        closest = dists[i];
        cornerShort = i;
      }
    }
    
    closest = im.width * im.height;
    
    for (int i = 0; i < pointsEval.size(); i++) {
      p = pointsEval.get(i);
      if (i != corner 
          && i != cornerShort 
          && abs(cornerP.xScaled - p.xScaled) < 10
          && dists[i] < closest) {
        closest = dists[i];
        cornerLong = i;
      }
    }
    
    closest = im.width * im.height;
    
    for (int i = 0; i < pointsEval.size(); i++) {
      p = pointsEval.get(i);
      if (i != corner 
          && i != cornerShort 
          && i != cornerLong 
          && abs(cornerP.xScaled - p.xScaled) > 10
          && abs(cornerP.yScaled - p.yScaled) > 10
          && dists[i] < closest) {
        closest = dists[i];
        cornerDiag = i;
      }
    }
    
    cornerShortP = pointsEval.get(cornerShort);
    cornerLongP = pointsEval.get(cornerLong);
    cornerDiagP = pointsEval.get(cornerDiag);

    lines.add(new Line(cornerP.x, cornerP.y, cornerShortP.x, cornerShortP.y));
    lines.add(new Line(cornerP.x, cornerP.y, cornerLongP.x, cornerLongP.y));
    lines.add(new Line(cornerDiagP.x, cornerDiagP.y, cornerShortP.x, cornerShortP.y));
    lines.add(new Line(cornerDiagP.x, cornerDiagP.y, cornerLongP.x, cornerLongP.y));
    
    println(which);
    print(cornerP.xScaled);
    print(",");
    println(cornerP.yScaled);
    
    print(cornerShortP.xScaled);
    print(",");
    println(cornerShortP.yScaled);
    
    print(cornerLongP.xScaled);
    print(",");
    println(cornerDiagP.yScaled);
    
    print(cornerDiagP.xScaled);
    print(",");
    println(cornerDiagP.yScaled);
    
    W = round( ( abs(cornerP.y - cornerLongP.y) + abs(cornerShortP.y - cornerDiagP.y) ) / 2);
    H = round( ( abs(cornerP.x - cornerShortP.x) + abs(cornerLongP.x - cornerDiagP.x) ) / 2);
    print(W);
    print("x");
    println(H);

    delay(5000);
  }
}

void listFiles () {
  someFolder = new File(SCANS);
  someFolderList = someFolder.listFiles();
  for (File someFile : someFolderList) {
    if (someFile.isFile()) {
      if (someFile.getName().endsWith(".png")) {
        files.add(someFile.getPath());
      }
    }
  }
}

void updateFile () {
  current++;
  if (current == filesCount) {
    println("files completed");
    exit();
  } else {
    left = 0;
    top = 0;
    currentFile = files.get(current); 
    print("using ");
    println(currentFile);
    img = loadImage(currentFile);
    copy = createImage(img.width, img.height, RGB);
    copy.copy(img, 0, 0, img.width, img.height, 0, 0, img.width, img.height);
    copy.resize(0, height);
    println("loaded");
    println(img.width);
    println(img.height);
  }
}

void processFile () {
  clear();
  image(copy, 0, 0);
  delay(2000);
  A = new Frame("A", img);
  B = new Frame("B", img);
  C = new Frame("C", img);
  D = new Frame("D", img);
  A.try_all(points);
  B.try_all(points);
  C.try_all(points);
  D.try_all(points);
}

void keyPressed () {
  int step = 100;
 if (key == 'w') {
   if (top < 0) {
     top += step;
   }
 } else if (key == 's') {
   if (abs(top) < img.height - height) {
     top -= step;
   }
 } else if (key == 'a') {
   if (left < 0) {
     left += step;
   }
 } else if (key == 'd') {
   if (abs(left) < img.width - width) {
     left -= step;
   }
 } else if (key == 'x') {
  if (points.size() > 0) {
   points.remove(points.size() - 1);
  }
 } else if (keyCode == ENTER) {
  if (points.size() == 16) {
    points = new ArrayList<Point>();
    lines = new ArrayList<Line>();
    updateFile();
  }
 }
}

void mousePressed () {
  int x = mouseX - left;
  int y = mouseY - top;
  print("added ");
  print(x);
  print(",");
  println(y);
  points.add(new Point(x, y, img.width, img.height));
  if (points.size() == 16) {
    println("file marked");
    processFile();
  }
}

void setup () {
  size(800, 600);
  listFiles();
  if (files.size() > 0) {
    filesCount = files.size();
    updateFile();
  } else {
    println("No files"); 
    exit();
  }
}

void draw () {
  Point p;
  Line l;
  fill(255,100,100);
  noStroke();

  image(img, left, top);
  ellipse(mouseX, mouseY, dotSize, dotSize);

  fill(255,0,0);
  for (int i = 0; i < points.size(); i++) {
    p = points.get(i);
    ellipse(p.x + left, p.y + top, dotSize, dotSize);
  }
  strokeWeight(2);
  stroke(255, 0, 0);
  for (int i = 0; i < lines.size(); i++) {
    l = lines.get(i);
    l.draw();
  }
}