/*
* scale_notes.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 "scale_notes.h"
#include "main.h"
#include "ui.h"
#include "instrument.h"

#include <fstream>
using namespace std;

extern int NOTATION;
extern const char* WESTERN_FLAT [];
extern map<std::string, int> NOTE_POS;  
extern int NUM_INTERVALS;

extern ofstream dlog;

void scale_notes::setup () {

  lbl.set_text ("Scale = ");
  lbl.children.clear ();
	for (int i = 0; i < NUM_INTERVALS; ++i) {
		checkbutton& cbi = cb_notes[i];
		cbi.set_listener (0);
		cbi.turn_off ();
	}

  // label notes
  if (NOTATION == WESTERN) {
    for (int i = 0, j = NUM_INTERVALS, k = get_current_instrument()->scaleinfo.western; i < j; ++i) {
      cb_notes[i].set_text (WESTERN_FLAT[k++]);
      k = k % 12;
    }
  } else if (NOTATION == NUMERIC) {
    for (int i = 0, j = NUM_INTERVALS; i < j; ++i) {
      cb_notes[i].set_text (INTERVAL_NAMES[i]);
    }
  } else {
    extern map<string, string> INT2IND;
    for (int i = 0, j = NUM_INTERVALS; i < j; ++i) {
      cb_notes[i].set_text (INT2IND[INTERVAL_NAMES[i]]);
    }
  }

  // mark notes of the scale
	scale_info& scaleinfo = get_current_instrument ()->scaleinfo;
  for (int i = 0; i < scaleinfo.num_notes; ++i) {
    int p = NOTE_POS [scaleinfo.notes[i]];
    cb_notes[p].turn_on ();
  }

  for (int i = 0, j = NUM_INTERVALS; i < j; ++i) {
    lbl.add_child (&cb_notes[i]);
    cb_notes[i].set_listener (this);
  }

}

void scale_notes::set_pos (int x, int y) {
  widget::set_pos (x, y);
  lbl.set_pos (x, y);
  advance_right (x, lbl);
  for (int i = 0; i < NUM_INTERVALS; ++i) {
    checkbutton& cb = cb_notes[i];
    cb.set_pos (x, y);
    advance_right (x, cb);
  }
}

int scale_notes::handle_input () {
  int r = lbl.handle_input ();
  for (size_t i = 1, j = NUM_INTERVALS - 1; i < j; ++i) { // dont let editing of tonic
    r |= cb_notes[i].handle_input ();
  }
  return r;
}

void scale_notes::draw () {
  lbl.draw ();
  for (size_t i = 0, j = NUM_INTERVALS; i < j; ++i) cb_notes[i].draw ();
}

void scale_notes::update () {
  lbl.update ();
  for (int i = 0; i < NUM_INTERVALS; ++i) cb_notes[i].set_text (cb_notes[i].text);
  set_pos (posx, posy);
}

void scale_notes::refresh () {
  setup ();
  update ();
}

void scale_notes::changed (checkbutton& cb) {
  get_current_instrument()->scaleinfo.update (cb_notes);
}

