module GraphTools(randomGraph, readGraph, mkUGraphFast) where

import FGL
import Graph
import GraphData

import List
import Random

randomGraph :: Int -> Int -> Int -> UGraph
randomGraph numNodes numEdges seed =
    mkUGraphFast [1..numNodes] (take numEdges randomEdges)
    --mkUGraph [1..numNodes] (take numEdges randomEdges)
    where randomEdges = randomEdgesHelp (randomRs (1,numNodes) (mkStdGen seed))
          randomEdgesHelp (x:y:rest) = (x,y) : (randomEdgesHelp rest)

readGraph :: IO UGraph
readGraph = do
    {
        numNodes <- readNum;
        numEdges <- readNum;
        edges <- readEdges numEdges;
        return (mkUGraphFast [1..numNodes] edges)
    }

readNum :: IO Int
readNum = do { line <- getLine; readIO line }

readEdges :: Int -> IO [Edge]
readEdges numEdges
    | numEdges==0 = do { return [] }
    | otherwise   = do { 
                         from <- readNum;
                         to <- readNum; 
                         edges <- readEdges (numEdges-1);
                         return ((from,to):edges);
                       }

grab :: Node -> [Edge] -> ([Node], [Edge])
grab u [] = ([], [])
grab u es@((v,w):more_es)
    | v==u = 
        let
            (rest_vs, next_es) = grab u more_es
        in (w:rest_vs, next_es)
    | otherwise = ([],es)

mkUGraphFast :: [Node] -> [Edge] -> UGraph
mkUGraphFast nodes edges = extend nodes pre suc empty
    where
        extend [] curPre curSuc g =
            g
        extend (v:vs) curPre curSuc g =
            let (theContext, nextPre, nextSuc)=contextFor v curPre curSuc
            in extend vs nextPre nextSuc (embed theContext g)
        contextFor v curPre curSuc = 
            let (myPre, nextPre) = grab v curPre
                (mySuc, nextSuc) = grab v curSuc
            in  ((labUAdj myPre, v, (), labUAdj mySuc), nextPre, nextSuc)
        suc = sort [(v,w) | (v,w) <- edges, v>=w]
        pre = sort [(w,v) | (v,w) <- edges, v<w]
