/*
* circler.cc
* DIN Is Noise is copyright (c) 2006-2024 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/

#include "circler.h"
#include "vector2d.h"
#include "ui_list.h"
#include "console.h"
#include <vector>
#include <fstream>
using namespace std;
extern ofstream dlog;
extern ui_list uis;
extern string user_data_dir;
extern const float PI_BY_180;
extern const float TWO_PI;
extern curve_library sin_lib, cos_lib;

circler::circler () : scr (this, "circler.scr", "circler_sin.crv", "circler_cos.crv", "circler_radius.crv", "circler_sin.ed", "circler_cos.ed", "circler_radius.ed", 1) {
  name = "Circler";
  center.x = 0.5;
  center.y = 0;
  load_params ();
}

circler::~circler () {
  widget_save ("d_circler", ctrls);
  save_params ();
}

void circler::load_params () {
  string ignore;
  ifstream f (make_fname().c_str(), ios::in);
  f >> ignore >> radius >> ignore >> startangle >> ignore >> endangle >> ignore >> num_points;
}

void circler::save_params () {
  ofstream f (make_fname().c_str(), ios::out);
  f << "radius " << radius << endl;
  f << "startangle " << startangle << endl;
  f << "endangle " << endangle << endl;
  f << "num_points " << num_points << endl;
}

void circler::setup () {

  plugin::setup ();

  widget* _ctrls [] = {&sp.radius, &sp.startangle, &sp.endangle, &sp.num_points, &scr};
  for (int i = 0; i < 5; ++i) ctrls.push_back (_ctrls[i]); 

  /*for (int i = 0; i < 7; ++i) {
    ctrls[i]->set_moveable(1);
  }*/

  num_ctrls = ctrls.size ();

  sp.startangle.set ("Start angle", 1.0f, -MILLION, MILLION, this, 0);
  sp.startangle.set_value (startangle);
  sp.endangle.set ("End angle", 1.0f, -MILLION, MILLION, this, 0);
  sp.endangle.set_value (endangle);
  sp.num_points.set ("Points", 1, 1, MILLION, this, 0);
  sp.num_points.set_value (num_points);
	sp.radius.set ("Radius", 0.01f, -MILLION, MILLION, this, 0);
	sp.radius.set_value (1.0f);

  widget_load ("d_circler", ctrls);

  scr.setup ();
  scr.set_pos (cb_auto_apply.posx, cb_auto_apply.posy);
  sin_cos_radius_optioned ();

}

void circler::render () {

  funktion& f_radius = *scr.pf_radius;
  funktion& f_sin = *scr.pf_sin;
  funktion& f_cos = *scr.pf_cos;

  radius = sp.radius.f_value;
  startangle = sp.startangle.f_value;
  endangle = sp.endangle.f_value;

  num_points = sp.num_points.f_value;

  theta = startangle * PI_BY_180;
  dtheta = (endangle - startangle) / num_points * PI_BY_180;

  int j = num_points + 1;
  points.resize (j);

  for (int i = 0; i < j; ++i) {
		point<float>& p = points[i];
    p.x = center.x + f_radius (theta) * radius * f_cos (theta);
    p.y = center.y + f_radius (theta) * radius * f_sin (theta);
    theta += dtheta;
    if (theta > TWO_PI) theta -= TWO_PI; // esp for custom periodics behind f_sin, f_cos & f_radius too
  }

	gen_pts ();

  ss.str("");
  ss << "circle_" << num_points;


}

void circler::sin_cos_radius_edited () {
  do_render ();
}

void circler::sin_cos_radius_optioned () {
  do_render ();
}

void circler::changed (field& f) {
  if (&f == &sp.startangle.f_value) {
    startangle = float(sp.startangle.f_value);
  }
  plugin::changed (f);
}

/*void circler::write () {
  extern string user_data_dir;
  string fname (user_data_dir + "circler.pts");
  ofstream fout (fname.c_str(), ios::out);
  if (fout) {
    fout << "center 0.5 0" << endl;
    fout << "num_points " << num_points << endl;
    for (int i = 0, n = points.size () - 1; i < n; ++i) {
      point<float>& pti = points[i];
      fout << pti.x << ' ' << pti.y << endl;
    }
  }
}*/
