module PostscriptLines where

import qualified Harmony
import qualified Melody
import Pitch
import Duration
import Data.Ratio

import HarmonyParser (parseHarmony)

styles = [" [] 0 setdash "
         ," [2 2] 0 setdash "
         ," [3 1] 0 setdash "
         ," [1 3] 0 setdash "
         ]

pointsPerOctave = 24

centsToPoints cents = cents * pointsPerOctave / 1200
pitchToPoints pitch = centsToPoints (toCents pitch)

durationToPoints duration = fromRational (6*duration)

grid = " gsave 0.1 setlinewidth 0.5 setgray"++
       concat [" newpath "++
               moveto 20 (400+pitchToPoints pitch) ++
               rlineto (durationToPoints (4*16)) 0 ++
               " stroke "
                   | octave <- [-1,0,1,2]
                   , pitch <- map ((2%1)^^octave*) [1%1, 4%3]
              ]
       ++ " grestore "
bars = " gsave 0.1 setlinewidth 0.5 setgray"++
       concat [" newpath "++
               moveto (20+durationToPoints duration) (400+pitchToPoints ((4%1) * (4%3))) ++
               rlineto 0 (pitchToPoints ((1%8)*(3%4))) ++
               " stroke "
                   | duration <- map (4*) [0..16]
              ]
       ++ " grestore "

harmonyToPs (Harmony.Harmony voices) =
    grid ++ bars ++
    flip concatMap (zip styles voices)
             (\(style,(chan,prog,pan,Melody.Melody melody)) ->
                  " newpath "++ style ++ " 20 400 moveto " ++ melodyToPs melody ++ " stroke ")


melodyToPs [] = ""
melodyToPs ((duration,Melody.Rest):thenWhat) =
    rmoveto (durationToPoints duration) 0 ++ melodyToPs thenWhat
melodyToPs ((duration,Melody.Note pitch _):thenWhat) =
    let ypos = pitchToPoints pitch
        xlen = durationToPoints duration in
    rmoveto 0 ypos ++ rlineto (xlen*0.9) 0 ++ rmoveto (xlen*0.1) (negate ypos) ++ melodyToPs thenWhat

showDouble f = show (f :: Double)

xycommand cmd x y = showDouble x ++ " " ++ showDouble y ++ " " ++ cmd ++ " "

moveto = xycommand "moveto"
rmoveto = xycommand "rmoveto"
rlineto = xycommand "rlineto"

test = do f <- readFile "song4.txt"
          let Right song = parseHarmony f
              ps = harmonyToPs song
          writeFile "song4.ps" ps
          putStrLn ps