/*
* scale_info.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 "scalelist.h"
#include "scale_info.h"
#include "tokenizer.h"
#include "utils.h"
#include "checkbutton.h"
#include "note.h"
#include "settings.h"
#include "ui_list.h"
#include "main.h"
#include <vector>
#include <string>
#include "log.h"

extern string user_data_dir;
extern map<string, float> INTERVALS;
extern int NUM_INTERVALS;
extern vector<string> INTERVAL_NAMES;
extern string SCALE;
extern ui_list uis;
extern char BUFFER [];

int scale_info::set_tonic (float f) {
	nearest_note.freq = f;
	nearest_note.distance = 0;
	western = find_nearest_note (nearest_note.name, nearest_note.freq, nearest_note.distance);
	float d2 = nearest_note.distance * nearest_note.distance;
	if (d2 < 0.01) tonic = nearest_note.freq; else tonic = f; // snap to note
	lo_tonic = tonic / 2.0f;
	hi_tonic = tonic * 2.0f;
	if (scl) scl->tonic_changed ();
  return 1;
}

int scale_info::load_scale (const string& n) {
  name = n;

  ifstream file ((user_data_dir + name).c_str(), ios::in);
  if (!file) return 0;

  string ignore;
	int nn;
  file >> ignore >> nn >> ignore;
	set_num_notes (nn);
	notes.resize (num_notes);
  for (int i = 0; i < num_notes; ++i) file >> notes[i];

	intervals = INTERVALS;

	if (scl) scl->scale_loaded ();

  return 1;

}

int scale_info::save_scale () {

  string fname (user_data_dir + name);

  ofstream file ((user_data_dir + name).c_str(), ios::out);
  if (!file) return 0;

  file << "num_notes " << num_notes << endl;
  file << "notes ";
  for (int i = 0; i < num_notes; ++i) file << notes[i] << spc;
  file << endl;

  dlog << "+++ saved scale into " + fname + " +++" << endl;

	return 1;

}

void scale_info::update (checkbutton* cb_notes) {
  notes.clear ();
  name.clear ();
  for (int i = 0; i < NUM_INTERVALS; ++i) {
    if (cb_notes[i].is_on ()) {
      const string& in = INTERVAL_NAMES[i];
      notes.push_back (in);
      name += in;
    }
  }

	set_num_notes (notes.size ());
	if (scl) scl->scale_changed ();
  SCALE = name;
}

void scale_info::update_settings () {
	sprintf (BUFFER, " nearest note = %s @ %0.3f Hz", nearest_note.name.c_str (), nearest_note.freq);
	uis.settings_scr.ol_nearest_note.option.set_text (BUFFER);
	uis.settings_scr.sp_key.set_value (tonic);
  uis.settings_scr.sn_scale_notes.refresh ();
}

void scale_info::set_num_notes (int n) {
  num_notes = n;
	last_note = num_notes - 1;
	second_last_note = last_note - 1;
	num_ranges = last_note;
	last_range = num_ranges - 1;
}
