import sk.uniba.fmph.pocprak.simplegraphics.GrGraphics;

public class Beam {
  /**
   * bod do ktoreho v danom okamihu luc dospel
   */
  point p;
  /**
   * jednodtkovy vektor v smere sirenia luca. Tento vektor moze byt aj nulovy vektor
   * to vtedy, ak bul luc pohltgeny nejakym povrchom a dalej sa uz nemoze sirit.
   * formalne sa sice siri dalej, ale kedze vektor sirenia je nulov, jeho bod
   * p sa uz dalej neposuva
   */
  vector dir;
  /**
   * cislo optivckeho povrchu do ktoreho ma luc narazit
   */
  int OptSurfId;
  public Beam(point p, vector dir, int OptSurfId) {
    //toto je poznamke pre profesionalov:
    // pre istotu vyrobime kopie, aby sme spatne neovplyvnovali parametre
    // v buducnosti, ked sa bude menit this.p aj this.dir
    // ide vlastne o to ze chceme volat parametre hodnotou nie menom
    // preto pouzivame "copy constructor"
    this.p = new point(p.x,p.y);
    this.dir = new vector(dir.x,dir.y);
    this.OptSurfId= OptSurfId;
  }

  public Beam(point p1, point p2, int OptSurfId){
    this.p = new point(p1.x,p1.y);
    this.dir = (new vector(p2,p1)).unit();
    this.OptSurfId = OptSurfId;
  }
  public void move(double dt, OpticalSystem o){
    //procedura posunie beam o maly kusok v parametri t, ale pre urychlenie 
      //simulacie sa predpoklada, ze v celom priestore x<-5 nie su ziadne lamave
      //plochy, preto ak sa ma beam posunut z bodu, pre ktory beam.p,x<-5, 
      //ignoruje sa zadane dt a urobi sa velky skok az do suradnice x = -5, aby sme mohli
      //pracovat aj so startovacimi bodmi v "minus nekonecne".
    if(dir.x <0 ){
        System.out.println("opacny smer sirena luca, stop");
        System.exit(-1);
    }
    if(dir.x==0&&dir.y==0) return;
    //test ci sa ma urobit velky skok daleko pred optickou sustavou
    if(this.p.x<-5.){
        //urobime velky skok
        double tjump = (-5. - this.p.x)/this.dir.x;
        this.p.x += tjump*this.dir.x;
        this.p.y += tjump*this.dir.y;
    }
    //teraz sa skontroluje, ci to nenarazilo do tubusu
    o.tbs.tubusEffect(this);
    if(dir.x==0&&dir.y==0)
        //tu sa sirenie luca zastavilo, teda narazilo to do tubusu
        return;
    //teraz otestujeme, ci to uz narazilo na lamavu plochu
    if(o.os[this.OptSurfId].movesTowards(this)){
      //tu to zatial nenarazilo, posunie sa to kusok dopredu  
      this.p.x += dt*this.dir.x;
      this.p.y += dt*this.dir.y;
    }
    else{
      //prave sa nachadza na optickej ploche (alebo tesnucko za nou), 
      // treba vyvolat efekt plochy, ktora zmeni smer sirenia
      o.os[this.OptSurfId].SurfaceEffect(this);
      move(dt,o);  //rekurzia
    }
  }
  public void draw(point oldpoint,GrGraphics gr){
    gr.drawLine2D(oldpoint.x, oldpoint.y,this.p.x,this.p.y);
  }
}
