import { SVG, G } from "./svg.js/src/main.js"
export default { toDot, addAnchors, makeDraw, digraph_select }

var linking = false // variables de contrôle pour la fabrication de liens
var link_tmp = {node1: null, node2: null}
var line_tmp = null
var initial_h = 1.0 // hauteur initiale du viewbox

var  draw= null // variable pour accéder à tout le dessin

/**
 * traduit les mouvements de souris par un segment si linking est vrai
 **/
function move_linking(ev){
    if (linking){
	if (line_tmp){
	    line_tmp.remove()
	    line_tmp = null
	}
	var bcr = $("svg")[0].getBoundingClientRect()
	var vb = draw.viewbox()
	// l'échelle courante est calculée :
	var echelle = vb.w / bcr.width
	var b = link_tmp.node1.bbox()
	// un certain décalage fixe est dû à la commande "dot -T svg"
	var decalage = {x : 4, y : 4}
	// cette commande fabrique une graphe qui prend toute la largeur
	// d'où une formule simple pour x1
	var x1 = b.x2 - decalage.x
	// la commande décale verticalement le graphe, et ce décalage doit être
	// noté au moment où on n'a encore jamais zoomé,
	// d'où l'usage de initial_h
	var y1 = initial_h + b.cy - decalage.y
	// une transformation linéaire simple permet de passer de la géométrie
	// des évènements de souris (à l'écran) vers les coordonnées dans la
	// figure SVG
	var x2 = vb.x + (ev.clientX - bcr.x) * echelle
	// là, c'est un peu plus compliqué à cause du décalage vertical
	// automatique qui place la figure SVG sous le milieu de la zone
	// d'affichage
	var y2 = vb.cy  + (ev.clientY - bcr.y - bcr.height/2) * echelle
	line_tmp = draw.line(
	    x1, y1,
	    // on évite d'aller jusque sous le point chaud de la souris
	    // sinon les évènements de survol et de clic ne descendent pas
	    // sous la ligne ligne_tmp
	    0.01 * x1 + 0.99 * x2, 0.01 * y1 + 0.99 * y2
	).stroke({color:"grey", width: 2}).attr("z-axis", -10)
    }
}

/**
 * Création du dessin
 * @param svg_code une chaîne qui contient le code sans entête d'un dessin SVG
 * @param selector un code CSS où le graphique sera ajouté
 * @param height hauteur en px
 * @return le dessin (instance de SVG)
 **/
export function makeDraw(svg_code, selector, height){
    draw = SVG(svg_code)
    initial_h = draw.viewbox().h
    draw.addTo(selector).size("100%", height)
    draw.panZoom({
	zoomFactor: 0.1,
    })
    draw.mousemove(move_linking)
    return draw
}

/**
 * exporte les nœuds et les liens vers une chaîne au format dot
 **/
export function toDot(){
    var debug = $("#debug")
    var text = "digraph mon_graphe {\n"
    $("svg .edge").each( function (i,e){
	var title = $(e).find("title").text()
	var re = /(.*)->(.*)/
	text += title.replace(re, '"$1" -> "$2"\n')
    })
    text += "}\n"
    debug.text(text)
}

function make_link(ev){
    if (! linking){
	linking = true
	link_tmp.node1 = this.parent
	$("#linking").show();
	$("#not_linking").hide();
    } else {
	linking = false
	link_tmp.node2 = this.parent
	$("#linking").hide();
	$("#not_linking").show();
	line_tmp.remove()
	line_tmp = null
	new Link(draw, link_tmp.node1, link_tmp.node2)
    }
}

/**
 * ajoute à un élément <g> un cercle
 * (à droite) pour les interactions de création de lien entre deux nœuds
 * @param g un élément <g> d'un dessin SVG, de classe "node"
 */
export function addAnchors(g){
    var b = g.bbox()
    var d = 20 // diamètre du cercle de l'ancre
    var anchor = g.circle(d)
	.move(b.x2 - d/2, b.cy - d/2)
	.fill("cyan")
	.stroke("black")
	.attr({
	    cursor: "pointer",
	    title: "créer un lien",
	})
    anchor.parent = g
    anchor
	.mouseover(function(){
	    anchor.fill("red")
	})
	.mouseout(function(){
	    anchor.fill("cyan")
	})
	.click(make_link)
}

/**
 * traitement de l'évènment lié au choix d'une instance de Digraph_select
 * dans la page /digraph_select
 **/
export function digraph_select(){
    var sel = $("#sel :selected")
    $.post("update_digraphs", {
	select_id: sel.data("selectid"),
	digraph_ids: sel.data("digraphids"),
	csrfmiddlewaretoken: getCookie('csrftoken'),
    }, function (data){
	$("#digraphs").html(data.html)
	$("#new-name").val(sel.text().trim())
	// économise deux clics sur les boutons de test des sélecteurs
	test_selector("left", "l", false)
	test_selector("right", "r", false)
    })
}
