PFont font;
data[] data = new data[1024];
void setup() {
  font = loadFont("font2.vlw"); 
  textFont(font, 20);
  size(740, 480);
  //noStroke();
  frameRate(60);
  background(255);
  String[] temp = loadStrings("状態.txt");
  if (temp == null) {
    for (int i = 0; i < 1024; i++) {
      data[i] = new data();
      data[i].x = -10024; 
      data[i].y = -10024; 
      data[i].s = 0;
      data[i].in = false;
    }
  }
  if (temp != null) {
    for (int i = 0; i < 1024; i++) {
      data[i] = new data();
      data[i].x = int(splitTokens(temp[i], ",")[0]); 
      data[i].y = int(splitTokens(temp[i], ",")[1]); 
      data[i].s = int(splitTokens(temp[i], ",")[2]);
      data[i].ver = int(splitTokens(temp[i], ",")[6]);
      String ti = splitTokens(temp[i], ",")[3];
      //if (random(100) < 50)data[i].in = true;
      if (ti.equals("true")) {
        data[i].in = true;
        //println("true");
      }
      if (ti.equals("false")) {
        data[i].in = false;
        //println("false");
      }
      ti = splitTokens(temp[i], ",")[4];
      if (ti.equals("true")) {
        data[i].out = true;
        //println("true");
      }
      if (ti.equals("false")) {
        data[i].out = false;
      }
    }
  }
}
int[] tbox(String t, int x, int y, float s, boolean h) {
  int[] out = {0, 0, 0, 0};
  int ix = int(sin(radians(-s))*30+x);
  int iy = int(cos(radians(-s))*30+y);
  int ox = int(sin(radians(-s+180))*30+x);
  int oy = int(cos(radians(-s+180))*30+y);
  out[0] = ix;
  out[1] = iy;
  out[2] = ox;
  out[3] = oy;
  stroke(0, 64);
  strokeWeight(2);
  noFill();
  beginShape();
  for (int i = 0; i < 4; i++) {
    vertex(40*cos(radians((360*i/4)+45+s))+x, 40*sin(radians((360*i/4)+45+s))+y);
  }
  endShape(CLOSE);
  fill(255, 128, 128, 64);
  ellipse(ix, iy, 8, 8);
  fill(128, 128, 255, 64);
  ellipse(ox, oy, 8, 8);
  noStroke();
  return out;
}
int[] box(String t, int x, int y, float s, boolean h) {
  int[] out = {0, 0, 0, 0};
  int ix = int(sin(radians(-s))*30+x);
  int iy = int(cos(radians(-s))*30+y);
  int ox = int(sin(radians(-s+180))*30+x);
  int oy = int(cos(radians(-s+180))*30+y);
  out[0] = ix;
  out[1] = iy;
  out[2] = ox;
  out[3] = oy;
  stroke(0, 64);
  strokeWeight(2);
  fill(120);
  if (h)fill(255);
  beginShape();
  for (int i = 0; i < 4; i++) {
    vertex(40*cos(radians((360*i/4)+45+s))+x, 40*sin(radians((360*i/4)+45+s))+y);
  }
  endShape(CLOSE);
  fill(255, 128, 128);
  ellipse(ix, iy, 8, 8);
  fill(128, 128, 255);
  ellipse(ox, oy, 8, 8);
  noStroke();
  fill(0);
  text(t, x-21, y+8);
  return out;
}
class data { 
  int x;
  int y;
  float s;
  int ix;
  int iy;
  int ox;
  int oy;
  boolean out;
  boolean in;
  int a;
  int ver;
}
boolean f;
int a;
void draw() {
  background(0xff);
  fill(255, 230, 200);
  rect(640, 0, 100, 480);
  for (int i = 0; i < 1024; i++) {
    if (data[i].x > 740 && data[i].y > 480 && data[i].x < 0 && data[i].y < 0) {
      data[i].x = -1024;  
      data[i].y = -1024;
    }
    if (data[i].x > 0 && data[i].y > 0) {
      if (data[i].ver != 0) {
        data[i].out = data[i].in;
      } else {
        data[i].out = !data[i].in;
      }
      int[] temp = box("NOT", data[i].x, data[i].y, data[i].s, data[i].out);
      if (data[i].ver == 0)temp = box("NOT", data[i].x, data[i].y, data[i].s, data[i].out);
      if (data[i].ver == 1)temp = box(" OR", data[i].x, data[i].y, data[i].s, data[i].out);
      data[i].ix = temp[0];
      data[i].iy = temp[1];
      data[i].ox = temp[2];
      data[i].oy = temp[3];
    }
  }
  for (int f = 0; f < 1024; f++) {
    data[f].a--;
  }
  //println(data[0].a);
  for (int i = 0; i < 1024; i++) {
    for (int f = 0; f < 1024; f++) {
      if (data[i].x > 0 && data[i].y > 0 && data[f].x > 0 && data[f].y > 0) {
        float t = dist(data[i].ix, data[i].iy, data[f].ix, data[f].iy);
        boolean tt = false;
        if (t < 58) {
          stroke(0);
          strokeWeight(2);
          line(data[i].ix, data[i].iy, data[f].ix, data[f].iy);
          noStroke();
          tt = true;
        }
        t = dist(data[i].ox, data[i].oy, data[f].ox, data[f].oy);
        if (t < 58) {
          stroke(0);
          strokeWeight(2);
          line(data[i].ox, data[i].oy, data[f].ox, data[f].oy);
          noStroke();
          tt = true;
        }
        t = dist(data[i].ix, data[i].iy, data[f].ox, data[f].oy);
        if (t < 58) {
          stroke(0);
          strokeWeight(2);
          line(data[i].ix, data[i].iy, data[f].ox, data[f].oy);
          noStroke();
          if (data[f].a <= 0) {
            data[f].in = data[i].out;
            data[f].a = 15;
          }
        }
        t = dist(data[i].x, data[i].y, data[f].x, data[f].y);
        //println(t);
        if (t < 70 && t > 0) {
          float s = atan2(data[i].x-data[f].x, data[i].y-data[f].y)+PI;
          data[f].x += sin(s)*8;   
          data[f].y += cos(s)*8;
          tt = true;
        }
      }
    }
  }
  int notx = 640+50;
  int noty = 50;
  int swix = 640+50;
  int swiy = 50+90;
  box("NOT", notx, noty, 0, true);
  textFont(font, 10);
  text("青が入力赤が出力", notx-40, 15);
  text("反転。", notx-45, noty+40);
  text("出力がオンだと光る", notx-45, noty+40+10);
  textFont(font, 20);
  box(" OR", swix, swiy, 0, true);
  textFont(font, 10);
  text("そのまま出力。", notx-45, swiy+50);
  text("出力がオンだと光る", notx-45, swiy+50+10);
  textFont(font, 20);
  if (mousePressed) {
    if (!f) {
      if (mouseX < notx+30 && mouseX > notx-30) {
        if (mouseY < noty+30 && mouseY > noty-30) {
          for (int i = 0; i < 1024; i++) {
            if (data[i].x < -10) {
              data[i].x = mouseX;
              data[i].y = mouseY;
              data[i].ver = 0;
              f = true;
              break;
            }
          }
        }
      }
      if (mouseX < swix+30 && mouseX > swix-30) {
        if (mouseY < swiy+30 && mouseY > swiy-30) {
          for (int i = 0; i < 1024; i++) {
            if (data[i].x < -10) {
              data[i].x = mouseX;
              data[i].y = mouseY;
              data[i].ver = 1;
              f = true;
              break;
            }
          }
        }
      }
    }
    for (int i = 0; i < 1024; i++) {
      if (mouseX < data[i].x+30 && mouseX > data[i].x-30) {
        if (mouseY < data[i].y+30 && mouseY > data[i].y-30) {
          data[i].x = mouseX;
          data[i].y = mouseY;
          data[i].s = deg;
        }
      }
    }
  } else {
    f = false;
  }
  tbox("", mouseX, mouseY, deg, false);
}
float deg;
void mouseWheel(MouseEvent e ) {
  if ( e.getAmount() < 0 ) {
    //奥に向かって回転させる
    deg = deg - (22.5/2);
  } else {
    //手前に向かって回転させる
    deg = deg + (22.5/2);
  }
}
void dispose() {
  String[] temp = new String[1024];
  /*int x;
   int y;
 c float s;
   int ix;
   int iy;
   int ox;
   int oy;
   boolean out;
   boolean in;
   int a;
   */
  for (int i = 0; i < 1024; i++) {
    temp[i] = nf(data[i].x);
    temp[i] += ",";
    temp[i] += nf(data[i].y);
    temp[i] += ",";
    temp[i] += nf(data[i].s);
    temp[i] += ",";
    temp[i] += nf(data[i].a);
    temp[i] += ",";
    if (data[i].in) {
      temp[i] += "true";
    } else {
      temp[i] += "false";
    }
    temp[i] += ",";
    if (data[i].out) {
      temp[i] += "true";
    } else {
      temp[i] += "false";
    }
    temp[i] += ",";
    temp[i] += nf(data[i].ver);
    temp[i] += ",";
  }
  saveStrings("状態.txt", temp);
}