package p5;
import anar.*;



import java.util.ArrayList;

import processing.core.PApplet;

/**
 * @author goo
 */
public class RecursivQuad00aMoucharabieh extends PApplet {

  /*
   * Example for Anar library by Guillaume LaBelle + Julien Nembrini
   * http://anar.ch
   */


  Sliders parameters;

  Pt      a, b, c, d;

  Obj     obj;

  int     nIteration = 0;

  public void setup(){
    size(800,400,OPENGL);
    Anar.init(this);

    Scene.autoSeek = false;

    obj = new Obj();

    initForm();

    Pts.globalRender = new RenderPtsAll();

  }


  void reset(){
    obj.faces.clear();
    obj.pts.ptList.clear();

    Pts facePts = new Pts();
    facePts.add(a);
    facePts.add(b);
    facePts.add(c);
    facePts.add(d);
    Face f = new Face(facePts);

    obj.add(f);

    nIteration = 0;

    addFourth = false;
  }

  void initForm(){

    a = Anar.Pt( -60, -60);
    b = Anar.Pt(60, -60);
    c = Anar.Pt(60,60);
    d = Anar.Pt( -60,60);

    Pts facePts = new Pts();
    facePts.add(a);
    facePts.add(b);
    facePts.add(c);
    facePts.add(d);
    Face f = new Face(facePts);

    obj.add(f);

    parameters = new Sliders(a);
    // println(parameters);

  }


  void weavingIteration(){

    nIteration++;
    println(nIteration);

    float z = 2f;

    ArrayList newFaces = new ArrayList();

    for (int k = 0; k<obj.numOfFaces(); k++){
      Face f = obj.face(k);

      // float param;
      // if (positive) param = z / (nIteration * nIteration) ;
      // else param = - z / (nIteration * nIteration) ;

      float param = z;

      Pts pp = new Pts();
      Pts subdiv = new Pts();

      // layout of pp in quad
      // 3 6 7 2
      //			 
      //			 
      // 0 4 5 1

      // get the vertices of the triangle
      pp.add(f.pt(0));
      pp.add(f.pt(1));
      pp.add(f.pt(2));
      pp.add(f.pt(3));

      // get the middle points
      Pts AB = new PtsMid(pp.pt(0),pp.pt(1),3);
      Pts BC = new PtsMid(pp.pt(1),pp.pt(2),3);
      Pts CD = new PtsMid(pp.pt(2),pp.pt(3),3);
      Pts DA = new PtsMid(pp.pt(3),pp.pt(0),3);

      pp.add(Anar.Pt(AB.pt(1)));
      pp.add(Anar.Pt(AB.pt(2)));

      pp.add(Anar.Pt(CD.pt(2)));
      pp.add(Anar.Pt(CD.pt(1)));

      // interior points
      Pts AB1CD2 = new PtsMid(pp.pt(4),pp.pt(6),3);
      Pts AB2CD1 = new PtsMid(pp.pt(5),pp.pt(7),3);

      // layout of the quad subdivision in subdiv
      // up down
      // 0 1 2 3
      // 4 5 6 7 16 17 18 19
      // 8 9 10 11 20 21 22 23
      // 12 13 14 15

      // 1st horizontal
      // 3 6 7 2
      subdiv.add(pp.pt(3));
      subdiv.add(pp.pt(6));
      subdiv.add(pp.pt(7));
      subdiv.add(pp.pt(2));

      // 2nd horizontal
      subdiv.add(Anar.Pt(DA.pt(1)));

      subdiv.add(Anar.Pt(AB1CD2.pt(2)));
      subdiv.add(Anar.Pt(AB2CD1.pt(2)));

      subdiv.add(Anar.Pt(BC.pt(2)));

      // 3rd horizontal
      subdiv.add(Anar.Pt(DA.pt(2)));

      subdiv.add(Anar.Pt(AB1CD2.pt(1)));
      subdiv.add(Anar.Pt(AB2CD1.pt(1)));

      subdiv.add(Anar.Pt(BC.pt(1)));


      // 4th horizontal
      // 0 4 5 1
      subdiv.add(pp.pt(0));
      subdiv.add(pp.pt(4));
      subdiv.add(pp.pt(5));
      subdiv.add(pp.pt(1));


      // duplicate points
      // 2nd horizontal
      subdiv.add(Anar.Pt(DA.pt(1)));

      subdiv.add(Anar.Pt(AB1CD2.pt(2)));
      subdiv.add(Anar.Pt(AB2CD1.pt(2)));

      subdiv.add(Anar.Pt(BC.pt(2)));

      // 3rd horizontal
      subdiv.add(Anar.Pt(DA.pt(2)));

      subdiv.add(Anar.Pt(AB1CD2.pt(1)));
      subdiv.add(Anar.Pt(AB2CD1.pt(1)));

      subdiv.add(Anar.Pt(BC.pt(1)));


      // up
      for (int i = 4; i<12; i++){
        Pt p = subdiv.pt(i);
        p.translate(0f,0f,param);
      }

      // down
      for (int i = 16; i<24; i++){
        Pt p = subdiv.pt(i);
        p.translate(0f,0f, -param);
      }

      // add first batch (regular ones)
      int[] angle = {0, 2, 5, 8, 10, 16, 18};
      // int[] angle = {0, 2, 5, 8, 10};
      for (int i = 0; i<angle.length; i++){
        Pts fps = new Pts();
        fps.add(subdiv.pt(angle[i]+4));
        fps.add(subdiv.pt(angle[i]+5));
        fps.add(subdiv.pt(angle[i]+1));
        fps.add(subdiv.pt(angle[i]));
        newFaces.add(new Face(fps));
      }

      // add second batch (irregular ones)
      Pts fps = new Pts();
      fps.add(subdiv.pt(17));
      fps.add(subdiv.pt(18));
      fps.add(subdiv.pt(2));
      fps.add(subdiv.pt(1));
      newFaces.add(new Face(fps));

      fps = new Pts();
      fps.add(subdiv.pt(13));
      fps.add(subdiv.pt(14));
      fps.add(subdiv.pt(22));
      fps.add(subdiv.pt(21));
      newFaces.add(new Face(fps));


    }

    obj = new Obj();

    for (int i = 0; i<newFaces.size(); i++)
      obj.add((Face)newFaces.get(i));

    Anar.camTarget(obj);

  }


  public void draw(){
    background(153);

    // ParametricValue v = parameters.get(0);
    // v.set(v.get()+ random(10)-5);

    obj.draw();
  }

  public static void main(String[] args){
    PApplet.main(new String[]{RecursivQuad00aMoucharabieh.class.getName()});
  }


  boolean addFourth = false;
  boolean positive  = false;

  public void keyPressed(){

    switch(key){
      case 'q':
        weavingIteration();
      break;
      case 'w':
        addFourth = !addFourth;
      break;
      case 'e':
        reset();
      break;
      case 'r':
        positive = !positive;
        ;
      break;


      case 'a':
        TextIO.write( ((Object)this).getClass().getName()+".lsp",obj.toAutocad());
      break;


    }


  }

}

