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


#include "spiraler.h"
#include "vector2d.h"
#include "ui_list.h"
#include <vector>
#include <fstream>

using namespace std;

extern const float PI_BY_180;
extern const float TWO_PI;
extern const float PI;

spiraler::spiraler () : scr (this, "spiraler.scr", "spiraler_sin.crv", "spiraler_cos.crv", "spiraler_radius.crv", "spiraler_sin.ed", "spiraler_cos.ed", "spiraler_radius.ed") {
  name = "Spiraler";
  center.x = 0.5;
  center.y = 0;
  load_params ();
  scr.cp_rad.div = 1.0f;
}

void spiraler::setup () {

  plugin::setup ();

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

	sp.radius.set ("Radius", 0.01f, -MILLION, MILLION, this, 0);
	sp.radius.set_value (radius);

	sp.turns.set ("Turns", 0.01f, 0.0f, MILLION, this, 0);
	sp.turns.set_value (turns);

	sp.num_points.set ("Points", 1, 0, MILLION, this, 0);
	sp.num_points.set_value (num_points);

  sp.phase.set ("Phase", 1.0f, -MILLION, MILLION, this, 0);
  sp.phase.set_value (phase);

  widget_load ("d_spiraler", ctrls);

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

  render ();

}

spiraler::~spiraler () {
  widget_save ("d_spiraler", ctrls);
  save_params ();
}

void spiraler::load_params () {
  ifstream f (make_fname().c_str(), ios::in);
  string ignore;
  f >> ignore >> radius >> ignore >> turns >> ignore >> num_points >> ignore >> phase;
}

void spiraler::save_params () {
  ofstream f (make_fname().c_str(), ios::out);
  string ignore;
  f << "radius " << radius << endl << "turns " << turns << endl << "num_points " << num_points << endl << "phase " << phase << endl;
}

void spiraler::render () {

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

  radius = sp.radius.f_value;
  turns = sp.turns.f_value;
	num_points = sp.num_points.f_value;
  phase = sp.phase.f_value;
  if (radius == 0 || turns == 0 || num_points < 2) return;

  float theta = phase * PI_BY_180;

  float start = theta;
  float end = theta + turns * TWO_PI;
  float delta = end - start;
  float dtheta = delta / num_points;
	int j = num_points + 1;
  float j_1 = 1. / num_points;
	points.resize (j);
  float current_radius;
  for (int i = 0; i < j; ++i) {
    current_radius = f_radius (i * j_1) * radius;
		point<float>& pi = points[i];
    pi.x = center.x + current_radius * f_cos (theta); 
    pi.y = center.y + current_radius * f_sin (theta);
		theta += dtheta; 
    while (theta > TWO_PI) theta -= TWO_PI;
  }

  ss.str("");
  ss << "spiral_" << turns << "_" << num_points;
	gen_pts ();

}

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

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