/*
 *                            COPYRIGHT
 *
 *  pcb-rnd, interactive printed circuit board design - Rubber Band Stretch Router
 *  Copyright (C) 2024 Tibor 'Igor2' Palinkas
 *  (Supported by NLnet NGI0 Entrust in 2024)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *  Contact:
 *    Project page: http://repo.hu/projects/pcb-rnd
 *    lead developer: http://repo.hu/projects/pcb-rnd/contact.html
 *    mailing list: pcb-rnd (at) list.repo.hu (send "subscribe")
 */

#include "config.h"

#include "conf_core.h"
#include <librnd/core/rnd_conf.h>

#include "board.h"
#include "crosshair.h"
#include "data.h"
#include "draw.h"
#include "draw_wireframe.h"
#include "tool_logic.h"

#include "map.h"
#include "stretch.h"
#include "stretch.c"

#include "tool_stretch.h"

static rbsr_stretch_t stretch;

void pcb_tool_stretch_init(void)
{
	rnd_hid_notify_crosshair_change(&PCB->hidlib, rnd_false);
	/* tool activated */
	pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST;
	rnd_hid_notify_crosshair_change(&PCB->hidlib, rnd_true);
}

/* click: creates next point of the route */
void pcb_tool_stretch_notify_mode(rnd_design_t *hl)
{
	pcb_board_t *pcb = (pcb_board_t *)hl;

	switch(pcb_crosshair.AttachedLine.State) {
		case PCB_CH_STATE_FIRST:
			if (pcb->RatDraw)
				return; /* do not route rats */

			if (rbsr_stretch_any_begin(&stretch, pcb, pcb_crosshair.X, pcb_crosshair.Y) == 0)
				pcb_crosshair.AttachedLine.State = PCB_CH_STATE_SECOND;
			break;

		case PCB_CH_STATE_SECOND:
			if (rbsr_stretch_accept(&stretch))
				pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST;
			rnd_gui->invalidate_all(rnd_gui);
			break;
	}
}

void pcb_tool_stretch_adjust_attached_objects(rnd_design_t *hl)
{
	if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_SECOND)
		return;

	if (rbsr_stretch_to_coords(&stretch) > 0)
		rnd_gui->invalidate_all(rnd_gui);
}

void pcb_tool_stretch_draw_attached(rnd_design_t *hl)
{
	if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_SECOND)
		return;

	/* jump over mode */
	if (!stretch.acceptable) {
		/* indicate point-not-found stretch with two thin lines from the ends of
		   the original line*/
		rnd_render->draw_line(pcb_crosshair.GC, stretch.fromx, stretch.fromy, pcb_crosshair.X, pcb_crosshair.Y);
		rnd_render->draw_line(pcb_crosshair.GC, stretch.tox, stretch.toy, pcb_crosshair.X, pcb_crosshair.Y);
	}
}

void pcb_tool_stretch_escape(rnd_design_t *hl)
{
	if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_SECOND) {
		rbsr_stretch_cancel(&stretch);
		pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST;
		rnd_gui->invalidate_all(rnd_gui);
	}
	else
		rnd_tool_select_by_name(hl, "arrow");
}

rnd_bool pcb_tool_stretch_undo_act(rnd_design_t *hl)
{
	if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_SECOND)
		return rnd_true;

	/* since we are doing only one proposal at a time there's nothing to undo
	   (use esc to abort the tool mode) */

	return rnd_false;
}

void pcb_tool_stretch_uninit(void)
{
	rnd_hid_notify_crosshair_change(&PCB->hidlib, rnd_false);
	pcb_tool_stretch_escape(&PCB->hidlib);
	rnd_hid_notify_crosshair_change(&PCB->hidlib, rnd_true);
}



/* XPM */
static const char *stretch_icon[] = {
/* columns rows colors chars-per-pixel */
"21 21 4 1",
"  c #000000",
". c #7A8584",
"X c #6EA5D7",
"O c None",
/* pixels */
"OOOOOOOOOOOOOOOOOOOOO",
"OOOOOO.OOOOOOOOOOOOOO",
"OOOOO.X.OOOOOOOOOOOOO",
"OOOOOO.XOOOOOOOOOOOOO",
"OOOOOOOOXOOOOOOOOXOOO",
"OOOOOO.OOXOOOOOOOXXOO",
"OOOOO...OOXOOXXXXXXXO",
"OOOOOO.OOXOOOOOOOXXOO",
"OO.OOOOXXOOOOOOOOXOOO",
"O.XXXXXOOOOOOOOOOOOOO",
"OO.OOOOOOOOOOOOOOOOOO",
"OOOOOOOOOOOOOOOOOOOOO",
"   OOO   O     O   OO",
" OO O OOOOOO OOO OO O",
" OO O OOOOOO OOO OO O",
" OO O OOOOOO OOO OO O",
"   OOO  OOOO OOO   OO",
" OO OOOO OOO OOO OO O",
" OO OOOO OOO OOO OO O",
" OO O   OOOO OOO OO O",
"OOOOOOOOOOOOOOOOOOOOO "
};


rnd_tool_t pcb_tool_stretch = {
	"rbsr_stretch", "rubber band stretch route: stretch an existing trace",
	NULL, 1100, stretch_icon, RND_TOOL_CURSOR_NAMED("pencil"), 1,
	pcb_tool_stretch_init,
	pcb_tool_stretch_uninit,
	pcb_tool_stretch_notify_mode,
	NULL,
	pcb_tool_stretch_adjust_attached_objects,
	pcb_tool_stretch_draw_attached,
	pcb_tool_stretch_undo_act,
	NULL, /*pcb_tool_stretch_redo_act,*/
	pcb_tool_stretch_escape,

	PCB_TLF_RAT
};
