package p5;
import anar.*;



import java.util.*;

import lsys.Grammar;
import processing.core.PApplet;


public class SimpleStructureTurtleB extends PApplet {

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


  Pts       ptsA = new Pts();


  Face      f;

  Grammar   grammar;

  Obj       faces;
  Obj       lines;

  Transform T;

  Translate t;
  Transform r;
  Scale     s;

  Sliders   mySlider;


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

  void initGrammar(){
    grammar = new Grammar("fg");
    // here define the rules
    // * means any kind of symbol
    // the example rules below are therefore non contextual
    grammar.addRule("*f*","fg[gf][hfh]");
    grammar.addRule("*g*","gg[hif]");
    grammar.addRule("*h*","ghjh");
    grammar.addRule("*j*","[gifh]");
    // this one makes it context dependant
    grammar.addRule("igh","[ghfg]");

    println(grammar);

  }

  void initForm(){
    faces = new Obj();


    Param pvRx = new Param(1.0f,0,3.14f,"rotate X");
    Param pvRy = new Param(2.0f,0,3.14f,"rotate Y");
    Param pvRz = new Param(3.0f,0,3.14f,"rotate Z");
    r = new Transform();
    RotateX rx = new RotateX(pvRx);
    RotateY ry = new RotateY(pvRy);
    RotateZ rz = new RotateZ(pvRz);
    r.add(rx);
    r.add(ry);
    r.add(rz);


    Param pvTx = new Param(00,0,100,"translate");
    Param pvTy = new Param(0,0,10,"translate");
    Param pvTz = new Param(10,0,100,"translate");
    t = new Translate(Anar.Pt(pvTx,pvTy,pvTz));

    Param pvSx = new Param(0.99f,0,10,"scale X");
    Param pvSy = new Param(0.99f,0,10,"scale Y");
    Param pvSz = new Param(0.99f,0,10,"scale Z");
    s = new Scale(Anar.Pt(pvSx,pvSy,pvSz));

    T = new Transform();
    T.add(t);
  }


  void interpretGrammar(){

    faces = new Obj();
    lines = new Obj();

    Face seedFace = new Star(40,50,6);
    Face currentFace = seedFace;

    Pts stackA = new Pts();
    int indexA = 0;
    Pt turtleA = seedFace.pt(indexA);

    ArrayList stackPtsA = new ArrayList();
    Pts ptsCollectorA = new Pts();
    ptsCollectorA.add(turtleA);


    Pts stackB = new Pts();
    int indexB = seedFace.numOfPts()/3;
    Pt turtleB = seedFace.pt(indexB);

    ArrayList stackPtsB = new ArrayList();
    Pts ptsCollectorB = new Pts();
    ptsCollectorB.add(turtleB);


    Pts stackC = new Pts();
    int indexC = (2*seedFace.numOfPts())/3;
    Pt turtleC = seedFace.pt(indexC);

    ArrayList stackPtsC = new ArrayList();
    Pts ptsCollectorC = new Pts();
    ptsCollectorC.add(turtleC);


    Iterator it = grammar.getSentence().iterator();
    while (it.hasNext()){
      String str = (String)it.next();

      switch(str.charAt(0)){
        case 'f':
          // create translated copy from current face
          Pts pts = new Pts();
          Iterator itFace = currentFace.iterator();
          while (itFace.hasNext()){
            pts.add(Anar.Pt((Pt)itFace.next(),t));
          }
          Face f = new Face(pts);
          // TODO (1) add size() method to Face
          // TODO (1) transform the face (missing methods)
          faces.add(f);

          // move the turtle to the next face
          currentFace = f;
          indexA %= currentFace.numOfPts();
          turtleA = currentFace.pt(indexA);

          indexB %= currentFace.numOfPts();
          turtleB = currentFace.pt(indexB);

          indexC %= currentFace.numOfPts();
          turtleC = currentFace.pt(indexC);
        case 'g':
          indexA = (indexA+1)%currentFace.numOfPts();
          turtleA = currentFace.pt(indexA);

          indexB = (indexB+1)%currentFace.numOfPts();
          turtleB = currentFace.pt(indexB);

          indexC = (indexC+1)%currentFace.numOfPts();
          turtleC = currentFace.pt(indexC);
        break;
        case 'h':
          indexA = (indexA+currentFace.numOfPts()-1)%currentFace.numOfPts();
          turtleA = currentFace.pt(indexA);

          indexB = (indexB+currentFace.numOfPts()-1)%currentFace.numOfPts();
          turtleB = currentFace.pt(indexB);

          indexC = (indexC+currentFace.numOfPts()-1)%currentFace.numOfPts();
          turtleC = currentFace.pt(indexC);
        break;
        case 'i':
          indexA = (indexA+2)%currentFace.numOfPts();
          turtleA = currentFace.pt(indexA);

          indexB = (indexB+2)%currentFace.numOfPts();
          turtleB = currentFace.pt(indexB);

          indexC = (indexC+2)%currentFace.numOfPts();
          turtleC = currentFace.pt(indexC);
        break;
        case 'j':
          indexA = (indexA+currentFace.numOfPts()-2)%currentFace.numOfPts();
          turtleA = currentFace.pt(indexA);

          indexB = (indexB+currentFace.numOfPts()-2)%currentFace.numOfPts();
          turtleB = currentFace.pt(indexB);

          indexC = (indexC+currentFace.numOfPts()-2)%currentFace.numOfPts();
          turtleC = currentFace.pt(indexC);
        break;
        case '[':
          stackA.add(turtleA);
          stackPtsA.add(ptsCollectorA);
          ptsCollectorA = new Pts();
          ptsCollectorA.add(turtleA);

          stackB.add(turtleB);
          stackPtsB.add(ptsCollectorB);
          ptsCollectorB = new Pts();
          ptsCollectorB.add(turtleB);

          stackC.add(turtleC);
          stackPtsC.add(ptsCollectorC);
          ptsCollectorC = new Pts();
          ptsCollectorC.add(turtleC);
        break;
        case ']':
          ptsCollectorA.add(turtleA);
          turtleA = stackA.remove(stackA.size()-1);
          lines.add(ptsCollectorA);
          ptsCollectorA = (Pts)stackPtsA.remove(stackPtsA.size()-1);

          ptsCollectorB.add(turtleB);
          turtleB = stackB.remove(stackB.size()-1);
          lines.add(ptsCollectorB);
          ptsCollectorB = (Pts)stackPtsB.remove(stackPtsB.size()-1);

          ptsCollectorC.add(turtleC);
          turtleC = stackC.remove(stackC.size()-1);
          lines.add(ptsCollectorC);
          ptsCollectorC = (Pts)stackPtsC.remove(stackPtsC.size()-1);
        break;
        default:
        break;
      }
    }
    lines.pts.render = new RenderPtsLine(new AColor(128));

    Anar.camTarget(faces);
    mySlider = new Sliders(lines);

  }

  public void draw(){
    if(frameCount%2==0)
      background(155);
    else
      background(153);

    // faces.draw();
    lines.draw();
    mySlider.draw();

  }


  public void keyPressed(){
    if(key=='a'){
      grammar.step();
      println(grammar);
      interpretGrammar();
    }
    if(key=='s'){
      grammar.reset();
      println(grammar);
      interpretGrammar();

    }
  }

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


}

