<script setup lang="ts">
import { chunks } from '~/helpers';
import * as d3 from "d3";

const point_array = useState<number[][] | undefined>('point_array', () => undefined)
const chunk_size = useState<number>('chunk_size', () => 8)
const threshold = useState<number>('threshold', () => 20)
const grid_redraw = useState<boolean>('grid_redraw', () => false)
const active_point = useState<{ x: number, y: number } | undefined>('active_point', () => undefined)
const target_points = useState<{ x: number, y: number, type: string }[]>('target_points', () => [])

const paths_array = ref<{ path: string, unwalkable: boolean, x: number, y: number }[]>()
const props = defineProps(['cw', 'ch'])
const d3svg = ref()

const setActivePoint = (item: { x: number, y: number }) => {
    active_point.value = { x: item.x, y: item.y }
}

const sampling_data = () => {
    grid_redraw.value = true
    const points = point_array.value
    const chunk = chunk_size.value
    if (!points) return
    const prepared_array = [...chunks(points, chunk)].map(line => {
        const line_data = [] as any[][]
        line.map((item: any) => [...chunks(item, chunk)]).map((item) => {
            item.map((one_line, k) => {
                if (!line_data[k]) line_data[k] = []
                line_data[k].push(...one_line)
            })
        })
        return line_data.map(el => {
            return el.filter(e => e > 0).length > threshold.value ? 1 : 0
        })
    });

    const res: any[] = []
    prepared_array.forEach((line, indexY) => {
        line.forEach((point, indexX) => {
            const targetX = indexX * chunk
            const targetY = indexY * chunk
            res.push({
                path: `M${targetX} ${targetY} ${targetX + chunk} ${targetY} ${targetX + chunk} ${targetY + chunk} ${targetX} ${targetY + chunk}Z`,
                unwalkable: !!point,
                x: indexX,
                y: indexY,
            })
        })
    })
    paths_array.value = res

    console.time('redraw D3')
    const svg = d3.select('#d3svg')
    // svg.selectAll("path").remove();
    const path_elements = svg.selectAll("path")

    paths_array.value.forEach(async (element, i) => {
        let _class = '';
        if (element.unwalkable) {
            _class += ' unwalkable'
        } else {
            _class += ' walkable'
        }
        if (target_points.value.find(el => el.x == element.x && el.y === element.y)) {
            _class += ' active'
        }
        const clickFunk = () => setActivePoint({ x: element.x, y: element.y })
        if (path_elements.nodes()[i]) {
            // console.log(`update ${i}`)
            d3.select(path_elements.nodes()[i])
                // .transition()
                // .duration(300)
                .attr('d', element.path)
                .attr('class', _class)
                .on('click', clickFunk)
        } else {
            // console.log(`add${i}`)
            svg.append("path")
                .attr('d', element.path)
                .attr('class', _class)
                .on('click', clickFunk)
        }
    });
    console.timeEnd('redraw D3')
    grid_redraw.value = false
}
watch(point_array, () => {
    sampling_data()
}, { deep: true })
watch(target_points, () => {
    sampling_data()
}, { deep: true })
watch(chunk_size, () => {
    sampling_data()
})
watch(threshold, () => {
    sampling_data()
})
onMounted(() => {
    sampling_data()
})
</script>
<template>
    <div>
        <svg :width="props.cw" :height="props.ch" ref="d3svg" id="d3svg"></svg>
    </div>
</template>

<style>
svg path {
    fill: transparent;
    stroke: rgba(70, 70, 0, 0.1);
}

svg path.unwalkable {
    fill: rgba(70, 70, 0, 0.5);
}

svg path.endPoint {
    fill: blue;
}

svg path.active {
    fill: lawngreen;
}

svg path.active {
    /* fill: gold; */
}


svg path:hover {
    fill: rgba(255, 0, 0, 0.5);
}
</style>