/*
 * work in progress
 * milestone demo release no build needed just change the `svgFilename` variable to any svg `path` based image
 * it means path is the only node recognised by the moment for definition another basic shaped are not considered at the moment.
 * position queries are rect-boundingboxes based by default, boundaries precision be added later
 */

import { HandRecogniser } from './hand-recogniser.js'; 
import './filereader.js';
import { log } from './logbar.js';



const { stringify } = JSON;
const { random, floor } = Math;
const doc = document;

const svgFilename = './svg/world.svg'
const fig = doc.querySelector('figure');
const video = doc.querySelector('video');


const svgPalettes = [
    {name: 'dark', fill: 'rgba(01, 10, 12, 0.75)'},
    {name: 'warm-red', fill: 'rgba(225, 78, 69, 0.75)'},
    {name: 'outer-space', fill: 'rgba(31, 40, 83, 0.75)'},
    {name: 'aqua', fill: 'rgba(69, 246, 255, 0.75)'},
    {name: 'sand', fill: 'rgba(255, 171, 69, 0.75)'}
];
let paletteIndex = -1,
    svg
;

function getPalette() {
    paletteIndex +=1 ;
    if(paletteIndex > svgPalettes.length)
        paletteIndex = 0;
    
    return svgPalettes[paletteIndex];
}



const hoverClasses = ['teal', 'orange', 'red', 'blue', 'lilah', 'purple', 'green'];

let boundsRects = Array(),
    paths = Array(),
    svgPath,
    svgPathPrev
;
	
// gesture svg connector, it finds which path is being pointed by hand gesture 
function matchPath(bounds, coord) {
    coord.x *= window.innerWidth
    coord.y *= window.innerHeight
    return _.findKey(bounds, function(item) {
        return item.left < coord.x &&
            coord.x < item.right &&
            item.top < coord.y &&
            coord.y < item.bottom
    })
}

// Remove xml file declaration and comments before append contents to document, like xml heading or unnecessary file comments
function cleanSvg(svgText) {
    const parts = svgText.split('<svg')
    return '<svg' + parts[1]
}

// apply some svg styles
function colorsSvg(svgText) {
    let palette = getPalette()
    return svgText.replace(/(fill=\"(\#[a-z0-9]+)\")/gi, `fill="${palette.fill}"`)
}

// hover/mouseover-mouseout dispatcher, it is called after Pointing_Up gesture is detected 
function dispatchHovering(result) {
    
    // index finger landmark
    // match will be the index in the collection sorted
    let lm = result.landmarks[0][8];
	
    let match = matchPath(boundsRects, lm)
    // to get the path by its originl index
    if (!match) return;
    
    if (svgPathPrev)
        svgPathPrev.dispatchEvent(new MouseEvent('mouseout'))
    
    svgPath = paths[boundsRects[match].svgIndex];
    svgPathPrev = svgPath;
    svgPath.dispatchEvent(new MouseEvent('mouseover', {
        clientX: boundsRects[match].x,
        clientY: boundsRects[match].y,
        view: window,
        bubbles: true,
        cancelable: true
    }))
    
    
}

function panToLeft() {
    svg.style.marginLeft = '-100%'
}

function panToRight() {
    svg.style.marginLeft = 0
}

function toggleColor() {
    
    let svg = fig.querySelector('svg')
    let palette = getPalette()
    log(stringify(palette))
    svg.setAttribute('fill', palette.fill)
    //alert('blink')
}

function swipe(ev) {
    if(ev.swipeX > 0)
        panToLeft()
    else
        panToRight()
    log(stringify(ev))
}

function setSvg(svgAsText) {
	
	const svgPlain = colorsSvg(cleanSvg(svgAsText));
    // Hopefuly transform goes in the browser
    fig.innerHTML = svgPlain
    
    // stored sorted paths in memory to query which one is being pointed
    svg = fig.querySelector('svg')
    paths = fig.querySelectorAll('path');
    paths.forEach((item, svgIndex) => {
        let bound = item.getBoundingClientRect()
        let fillHoverClass = hoverClasses[floor(hoverClasses.length * random())];
        bound.svgIndex = svgIndex
        boundsRects.push(bound);
        item.addEventListener('mouseover', (ev) => {
            ev.target.classList.add(fillHoverClass)
        })
        item.addEventListener('mouseout', (ev) => {
            ev.target.classList.remove(fillHoverClass)
        })
    })
    boundsRects = _.sortBy(boundsRects, ['left'])
}

/*
 * anon module start
 * fetches and appends svg file contents
 * stores `<path />` references in memory
 * attaches hovering listeners
 */
export default (async () => {
	
	// start with a default remote svg
    const res = await fetch(svgFilename);
    setSvg(await res.text())
	
    try {
		// Start the recogniser module with the Pointing_Up gesture, it can be used with another gestures like open palm, index finger is being referenced
		let handRecon = await HandRecogniser(video, { gesture: 'pointing_up', onrecognised: dispatchHovering, onswipe: swipe, onpantoleft: panToLeft, onpantoright: panToRight, onhandblink: toggleColor});
		handRecon.startCamera();
		
		// attach a file reader instance to change svg as desired by user
		FileReader.mount(setSvg)
	
    }catch(e) { log(e.message)}
})();


// yakko.js nov 2025