package p5;
import anar.*;



import processing.core.PApplet;

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

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


  Obj     towerCore         = new Obj();
  Obj     contourLines      = new Obj();
  Obj     verticalLines     = new Obj();
  Obj     windows           = new Obj();
  Obj     structure         = new Obj();
  Obj     rooms             = new Obj();

  Obj     export            = new Obj();

  Sliders mySliders;

  boolean calculateWindows  = true;
  boolean calculateVertical = true;

  String  cadSoftware, ext;
  boolean record            = false;


  public void setup(){
    size(640*2,480*2,OPENGL);
    Anar.init(this);

    // Setup DEFAULT rendering of our scene
    Pts.globalRender = new RenderPtsLine();
    Anar.drawAxis(true);
    // Scene.lights = false;
    CSpline.globalRender.splineRes.set(5);
    // anar.defaultScene = false;

    initForm();
  }


  void initForm(){

    // //////////////////////////////////////////
    // //////////////////////////////////////////
    // Initial SHAPE

    // Here, we create an arbitrary shape
    Face iShape;
    iShape = new Star(100,50,5);


    // //////////////////////////////////////////
    // //////////////////////////////////////////
    // LEVEL

    // The initial shape is duplicated Applying always the same predefined
    // Transformation

    Param numOfSubDivisionsOnEachSides = new Param(6);

    Transform combo = new Transform();
    combo.translate(0,0,5);
    combo.scale(0.92f,0.945f,1.04f);
    combo.rotateZ(.06f);

    for (int i = 0; i<24; i++){
      Face floorShape = new Face(iShape,combo);
      towerCore.add(floorShape);
      iShape = floorShape;
    }

    // //////////////////////////////////////////
    // //////////////////////////////////////////
    // VERTICALES

    if(calculateVertical){
      for (int i = 0; i<towerCore.numOfFaces(); i++){
        Face shape = towerCore.face(i);

        Pts contour;
        Pts tmpPtList = new Pts();

        for (int j = 0; j<shape.size(); j++){
          int jj = (j+1)%shape.size();
          contour = new PtsMid(shape.pt(j),shape.pt(jj),numOfSubDivisionsOnEachSides);
          contour.remove(contour.size()-1); // Remove the last one from the set
          tmpPtList.addPointsFrom(contour);
        }

        contourLines.add(tmpPtList);
      }


      int nodesPerLevel = contourLines.line(0).size();

      for (int j = 0; j<nodesPerLevel; j++){
        if(j%3!=0){
          Pts tmpPtList = new Pts();
          for (int i = 0; i<contourLines.numOfLines(); i++){
            Pts a = contourLines.getLine(i);
            tmpPtList.add(a.pt( (j+1*i)%nodesPerLevel));
          }
          verticalLines.add(tmpPtList);
        }
      }
    }

    // //////////////////////////////////////////
    // //////////////////////////////////////////
    // WINDOWS

    Param offset1 = new Param(.05f);
    Param offset2 = new Param(.5f);
    Param ratioI = new Param(8);

    if(calculateWindows)
      for (int i = 1; i<verticalLines.numOfLines(); i += 2){
        Pts a = verticalLines.line(i);
        Pts b = verticalLines.line( (i+1)%verticalLines.numOfLines());

        for (int j = 0; j<a.size()-1; j++){
          Pts k = new PtsMid(a.pt(j),a.pt(j+1),ratioI);
          Pts l = new PtsMid(b.pt(j),b.pt(j+1),ratioI);

          Pt aa = k.pt(1);
          Pt bb = a.pt(j+1);
          Pt cc = b.pt(j+1);
          Pt dd = l.pt(1);

          PtNormal nn = new PtNormal(aa,bb,cc,offset1);
          PtNormal kk = new PtNormal(bb,cc,dd,offset2);
          PtNormal mm = new PtNormal(cc,dd,aa,offset2);
          PtNormal ll = new PtNormal(dd,aa,bb,offset1);

          Pts c;

          c = new Pts();
          c.add(bb);
          c.add(nn);
          // windows.add(c);

          c = new Pts();
          c.add(dd);
          c.add(mm);
          // windows.add(c);

          Face f = new Face();
          f.add(nn);
          f.add(kk);
          f.add(mm);
          f.add(ll);
          windows.add(f);
        }
      }


    // //////////////////////////////////////////
    // //////////////////////////////////////////
    // STRUCTURE

    Obj pointsOnFloors = new Obj();

    for (int i = 0; i<towerCore.numOfFaces(); i++){
      Pts structurePts = new Pts();
      Face shape = towerCore.face(i);
      // structurePts.add(p);

      for (int j = 0; j<shape.numOfPts(); j++){
        float[] w;
        PtBary q;

        w = new float[shape.size()];
        w[j] = 3.5f;
        w[ (j+1)%shape.numOfPts()] = .2f;
        q = new PtBary(shape,w).normalizeWeight();
        structurePts.add(q);

        w = new float[shape.size()];
        w[j] = 3.5f;
        w[ (j-1+shape.numOfPts())%shape.numOfPts()] = .2f;
        q = new PtBary(shape,w).normalizeWeight();
        structurePts.add(q);

        w = new float[shape.size()];
        w[j] = 2.3f;
        w[ (j-1+shape.numOfPts())%shape.numOfPts()] = .15f;
        q = new PtBary(shape,w).normalizeWeight();
        structurePts.add(q);

        w = new float[shape.size()];
        w[j] = 2.3f;
        w[ (j+1)%shape.numOfPts()] = .15f;
        q = new PtBary(shape,w).normalizeWeight();
        structurePts.add(q);
      }

      pointsOnFloors.add(structurePts);
    }


    for (int i = 0; i<pointsOnFloors.numOfLines()-1; i++){
      Pts q = pointsOnFloors.line(i);
      Pts r = pointsOnFloors.line(i+1);
      for (int j = 0; j<q.size(); j += 4){
        Face p;

        for (int k = 0; k<4; k++){
          p = new Face();
          p.add(q.pt(j+k));
          p.add(r.pt(j+k));
          p.add(r.pt( (j+ (k+1)%4)));
          p.add(q.pt( (j+ (k+1)%4)));
          structure.add(p);
        }
      }
    }


    // //////////////////////////////////////////
    // //////////////////////////////////////////
    // Rooms

    RenderFaceDefault fRender = new RenderFaceDefault(new AColor(255,0,0,100));

    pointsOnFloors = new Obj();

    for (int i = 0; i<towerCore.numOfFaces(); i++){
      Pts structurePts = new Pts();
      Face shape = towerCore.face(i);

      for (int j = 0; j<shape.numOfPts(); j++){
        float[] w = new float[shape.size()];
        w[j] = 0.8f;
        PtBary q = new PtBary(shape,w);
        structurePts.add(q);
      }

      pointsOnFloors.add(structurePts);
    }


    for (int i = 0; i<pointsOnFloors.numOfLines()-1; i += 2){
      Pts q = pointsOnFloors.line(i);
      Pts r = pointsOnFloors.line(i+1);
      for (int j = 0; j<q.size(); j++){
        Face p;

        p = new Face();
        p.add(q.pt(j));
        p.add(r.pt(j));
        p.add(r.pt( ( (j+1)%q.size())));
        p.add(q.pt( ( (j+1)%q.size())));
        p.render = fRender;

        rooms.add(p);


      }
    }


    // //////////////////////////////////////////
    // HIRARCHY

    Anar.camTarget(towerCore);
    mySliders = new Sliders(structure);

    structure.fill(255,255,0,200);

    // Store All objects in one group
    export.add(towerCore);
    // export.add(verticalLines);
    export.add(windows);
    export.add(structure);
    export.add(rooms);

  }


  public void draw(){
    background(200);


    // You call the renderer like:
    // superCAD.AutoLISP --> .lsp
    // superCAD.PovRAY --> .pov
    // superCAD.Rhino --> .rvb
    // superCAD.SketchUP --> .rb
    if(record)
      beginRaw("superCAD."+cadSoftware,"output."+ext);


    towerCore.draw();
    // verticalLines.draw();
    // contourLines.draw();
    // windows.draw();
    structure.draw();
    rooms.draw();


    if(record){
      endRaw();
      record = false;
    }

    mySliders.draw();
  }


  public void keyPressed(){

    switch(key){
      case 'a':
        Autolisp.export(export,this);
      break;
      case 'r':
        RhinoScript.export(export,this);
      break;
      case 's':
        SketchUpRuby.export(export,this);
      break;
      case 'm':
        // PovRay.export(allObjects,this);
      break;
      case ' ':
        initForm();
      break;
      case 'f':
        saveFrame("line-####.tif");
      break;


      case 'z':
        cadSoftware = "Rhino";
        ext = "rvb";
        record = true;
      break;
      case 'x':
        cadSoftware = "SketchUP";
        ext = "rb";
        record = true;
      break;
      case 'c':
        cadSoftware = "AutoLISP";
        ext = "lsp";
        record = true;
      break;
      case 'v':
        cadSoftware = "PovRAY";
        ext = "pov";
        record = true;
      break;
      case 'b':
        cadSoftware = "Maya";
        ext = "mel";
        record = true;
      break;

    }
  }


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

}

