package com.correx.core.transitions.analysis.canonicalization

import com.correx.core.transitions.analysis.DetectedCycle

internal object CycleCanonicalizer {
    fun canonicalize(
        cycles: List<DetectedCycle>
    ): List<DetectedCycle> {
        val normalized = cycles.map { cycle ->

            if (cycle.nodes.isEmpty()) return@map cycle

            val open = cycle.nodes.dropLast(1)

            val minIndex = open
                .withIndex()
                .minBy { it.value.value }
                .index

            val rotatedNodes = open.drop(minIndex) + open.take(minIndex)
            val rotatedEdges = cycle.edges.drop(minIndex) + cycle.edges.take(minIndex)

            val closed = rotatedNodes + rotatedNodes.first()

            DetectedCycle(closed, rotatedEdges)
        }

        return normalized
            .distinctBy { cycle ->
                val nodeKey = cycle.nodes.joinToString("->") { it.value }
                val edgeKey = cycle.edges.joinToString("->") { it.id.value }
                "$nodeKey|$edgeKey"
            }
            .sortedBy { it.nodes.first().value }
    }
}
