
import System
import List
import Maybe
import Text.Printf
import IO


main = do

        [pathToQhull,f] <- getArgs
        s <- readFile f

        let ls = map (spltAll1 ",") $ lines s
        let n = length ls
        let cs = map (unwords . tail ) ls
        let rs = map head ls

-- Write a file suitable for QHull to use:
        writeFile "tmp0.qh" $ 	
		"3" ++"\n"++ show n ++"\n"++ unlines  cs

        vs <- rch pathToQhull 0 cs 
        let rchList = map snd $ sort vs

        putStr $ unlines $ map show rchList 
	
	-- Clean up and exit
        system "rm tmp*"

-- Convert Points to Coordinates
pts2cs cs (p,ps) = (getCs p,map getCs ps)
        where   getCs p = s2c $ cs!!p
                s2c s = l2t $ map asDouble $ words s
                l2t [x,y,z] = (x,y,z)

--------------------------------------------------------------------------------
-- Recursive Convex Hulls

-- lvs == local vertices
-- gvs == global vertices ....
-- h == hull coords

rch pathToQhull i rs = do
        let inf = "tmp"++show i ++".qh"
        let outf = "tmp"++show i ++".off"

        system $ pathToQhull ++ "qhull o TI "++inf++" TO "++outf


-- Parse and process the QHull output ".off" file format
-- Start by reading back in the file that was input to QHull
        a<-readFile inf

        let la = lines a
        let cs = drop 2 la

-- The use this to read and process the QHull output file 
        b<-readFile outf

-- Extract the Vertices from the ".off" file
        let lb = drop (length la) $ lines b
        let lvs = nub
                $ sort
                $ map asInt
                $ words
                $ unlines
                $ map (unwords . tail . words) lb

        let gvs = [ (fromJust $ elemIndex (cs!!v) rs,i) | v <- lvs ]

-- Map the QHull output vertices back to the original Coordinates
        let h = [ cs!!v | v <- lvs ] -- The Hull
-- Find Coordinates NOT in the Hull
        let cs' =  [ c | c <- cs , notElem c h ] 
        let ln = length cs'

-- Write the remaining (non-hull points) to a file of points suitable for QHull to read:
        writeFile ("tmp"++show (i+1)++".qh") 
		$  "3" ++"\n"++ show ln ++"\n"++ unlines cs'

        if ln<4
                then do -- Stop
                        let vs = [ (fromJust $ elemIndex c rs,i+1) | c <- cs' ]
				-- Maximum hull number
                        return $ gvs ++ vs
                else do -- Recurse
                        vs <- rch pathToQhull (i+1) rs
				-- Maximum hull number
                        return $ gvs ++ vs
--------------------------------------------------------------------------------
-- Utils

asDouble s = read s :: Double
asInt s =  read s :: Int

spltAll1 p s -- Split a string on a pattern
        | l==[] = [s]
        | otherwise = l
        where   l = spltAll p s

spltAll p s
        | l==[s] = []
        | otherwise = filter (/=p) l
        where   l = spt  p s

spt p [] = [[]]
spt p s =
        if i==Nothing
        then [s]
        else (take (fromJust i) s) : spt p (drop ((fromJust i)+n) s)
        where   i = findIndex (isPrefixOf p) $ tails s
                n = length p



