/*
* capturer.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 "capturer.h"
#include "curve_editor.h"
#include "console.h"

using namespace std;

#define DECLARE_WIDGET_ARRAY_wa widget* wa [] = {&title, &all, &none, &invert, &play, &kill, &fold};
#define NUM_WIDGETS 7
#define NUM_WIDGETS_1 (NUM_WIDGETS - 1)

typedef std::vector<state_button*>::iterator caps_iter;

void capturer_t::setup (curve_editor* ce) {

	ed = ce;

	DECLARE_WIDGET_ARRAY_wa
	const char* texts [] = {"Captures", "All", "None", "Invert"};
	for (int i = 0; i < 4; ++i)  {
		label* l = dynamic_cast<label*>(wa[i]);
		l->set_text (texts[i]);
	}
	for (int i = 1; i < NUM_WIDGETS; ++i) dynamic_cast<button*>(wa[i])->set_listener (this);

	makefam (&title, &wa[1], NUM_WIDGETS_1);

	for (int i = 4; i < 6; ++i) {
		button* wi = dynamic_cast<button*>(wa [i]);
		wi->set_size (16);
	}

	title.set_moveable (1);
	title.movlis = this;

	fold.set_dir (arrow_button::right);
	play.set_dir (arrow_button::right);

	widget_load ("d_capturer", wa, NUM_WIDGETS);

	folded = 1;
	ncaps = 0;
	moved ();

}

capturer_t::capturer_t () {
	++ref;
}

capturer_t::~capturer_t () {

	if (ncaps) {
		for (int i = 0; i < ncaps; ++i) {
			state_button* sb = caps[i];
			delete sb;
		}
	}

	if (--ref == 0) {
		DECLARE_WIDGET_ARRAY_wa
		widget_save ("d_capturer", wa, NUM_WIDGETS);
	}
}

int capturer_t::handle_input () {

	if (folded) {
		if (fold.handle_input()) return 1;
		else return title.handle_input ();
	} else {

		if (ncaps) {
			for (int i = 0; i < ncaps; ++i) {
				state_button* sb = caps[i];
				if (sb->handle_input()) return 1;
			}
		}

		DECLARE_WIDGET_ARRAY_wa
		for (int i = 0; i < NUM_WIDGETS; ++i) {
			widget* wi = wa[i];
			if (wi->handle_input()) return 1;
		}

	}

	return 0;

}

void capturer_t::set (mouse_macro& mm, int x, int y) {
	point<int>& p = sbpt [mm.sb];
	p.x = x; p.y = y;
}

void capturer_t::remove () {
	int p = ncaps;
	for (vector<state_button*>::iterator i = caps.begin (), j = caps.end(); i != j;) {
		state_button* sb = *i;
		if (sb->state) {
			ed->remove_mouse_capture (sb);
			title.remove_child (sb);
			delete sb;
			i = caps.erase (i);
			j = caps.end ();
			--ncaps;
		} else ++i;
	}
	rearrange ();
	cons << GREEN << "Removed " << (p - ncaps) << " mouse captures" << eol;
}

void capturer_t::rearrange () {
	int sx = title.extents.left;
	if (ncaps) {
		for (int i = 0; i < ncaps; ++i) {
			state_button* sb = caps[i];
			sb->set_pos (sx, sby);
			sx += state_button::SIZE2;
		}
	}
	sbx = sx;
}

void capturer_t::on_caps (const item_op& op) {
	if (ncaps) {
		for (int i = 0; i < ncaps; ++i) {
			state_button* sb = caps[i];
			sb->set_state (op (sb->state));
		}
	}
}

void capturer_t::clicked (button& b) {
	if (&b == &kill) {
		remove ();
	} else if (&b == &play) {
		ed->toggle_mouse_capture (caps);
	} else if (&b == &all) {
		on_caps (_sel);
	} else if (&b == &none) {
		on_caps (_desel);
	} else if (&b == &invert) {
		on_caps (_togg);
	} else if (&b == &fold) {
		if (fold.dir == arrow_button::down) {
			title.hide (widget::only_children);
			fold.show ();
			fold.set_dir (arrow_button::right);
			folded = 1;
		} else {
			title.show ();
			fold.set_dir (arrow_button::down);
			folded = 0;
		}
	}
}

void capturer_t::draw () {
	if (folded == 0) {
		DECLARE_WIDGET_ARRAY_wa
		for (int i = 0; i < NUM_WIDGETS; ++i) {
			widget* wi = wa[i];
			if (wi->visible) wi->draw ();
		}
		if (ncaps) {
			for (int i = 0; i < ncaps; ++i) {
				state_button* sb = caps[i];
				sb->draw ();
			}
		}
		glEnable (GL_LINE_STIPPLE);
		glLineStipple (1, 0xf00f);
		if (ncaps) {
			for (int i = 0; i < ncaps; ++i) {
				state_button* sb = caps[i];
				point<int>& p = sbpt [sb];
				glBegin (GL_LINES);
					glVertex2i (p.x, p.y);
					glVertex2i (sb->extents.midx, sb->extents.midy);
				glEnd ();
			}
		}
		glDisable (GL_LINE_STIPPLE);
	} else {
		fold.draw ();
		title.draw ();
	}
}

void capturer_t::moved () {
	sbx = title.extents.left + ncaps * state_button::SIZE2;
	sby = title.extents.bottom - title.extents.height;
}
