/*
* curve_library.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 "curve_library.h"
#include "curve_editor.h"
#include "console.h"
#include "utils.h"
#include "solver.h"
#include <algorithm>
#include <fstream>
using namespace std;

extern ofstream dlog;

extern console cons;
extern gotog _gotog;

void curve_library::load (const string& fname) {
  extern string user_data_dir;
  ifstream inf ((user_data_dir + fname).c_str(), ios::in);
  if (inf) {
    string ignore;
    int ncurves; inf >> ignore >> ncurves;
		curves.resize (ncurves);
    for (int i = 0; i < ncurves; ++i) {
      multi_curve& m = curves[i];
      m.load (inf);
      if (has_sustain) {
        float sus; inf >> ignore >> sus;
        sustains.push_back (sus);
      }
    }
    dlog << "+++ loaded " << curves.size () << " curves from: " << fname << " +++" << endl;
  }
  cur = 0;
}

curve_library::curve_library (const string& fname, int hs) {
  cur = 0;
  filename = fname;
  has_sustain = hs;
  load (filename);
}

curve_library::~curve_library () {
  save ();
}

void curve_library::add (const multi_curve& m) {
  curves.push_back (m);
  if (has_sustain) sustains.push_back (_gotog.g);
  cons << "added curve " << num_curves() - 1 << eol;
}

void curve_library::del () {
  curves.erase (curves.begin() + cur);
  if (has_sustain) sustains.erase (sustains.begin() + cur);
  clamp<int> (0, cur, curves.size () - 1);
  cons << "erased curve " << cur << eol;
}

void curve_library::replace (const multi_curve& m) {
  curves[cur] = m;
  if (has_sustain) sustains[cur] = _gotog.g;
  cons << "replaced curve " << cur << eol;
}

void curve_library::insert (const multi_curve& m) {
  curves.insert (curves.begin() + cur, m);
  if (has_sustain) sustains.insert (sustains.begin() + cur, _gotog.g);
  cons << "inserted curve " << cur << eol;
}

const multi_curve& curve_library::prev () {
  int ncurves = curves.size ();
  if (--cur < 0) cur = ncurves - 1;
  if (has_sustain) _gotog.set (sustains[cur]);
  cons << "loaded " << curves[cur].name << " [" << cur + 1 << '/' << ncurves << "]" << eol;
  return curves[cur];
}

const multi_curve& curve_library::next () {
  int ncurves = curves.size ();
  if (++cur >= ncurves) cur = 0;
  if (has_sustain) _gotog.set (sustains[cur]);
  cons << "loaded " << curves[cur].name << " [" << cur + 1 << '/' << ncurves << "]" << eol;
  return curves[cur];
}

void curve_library::move (int i) {

  multi_curve& from = curves [cur];

  cons << "move from: " << cur;

  int j = cur + i;
  int last = curves.size() - 1;
  if (j < 0) j = 0; else if (j > last) j = last;

  multi_curve to = curves[j];
  curves[j] = from;
  from = to;
  cur = j;

  if (has_sustain) swap (sustains[cur], sustains[j]);

  cons << " to: " << cur << eol;

}

void curve_library::save () {
  extern string user_data_dir;
  ofstream outf ((user_data_dir + filename).c_str(), ios::out);
  if (outf) {
    outf << "num_curves " << num_curves () << endl;
    for (int i = 0, j = num_curves(); i < j; ++i) {
      curves[i].save (outf);
      if (has_sustain) outf << "sustain " << sustains[i] << endl;
    }
    dlog << "+++ saved curve library: " << filename << " +++" << endl;
  }
}



