module Music.Typesetting.Output.MusicXML.Binding where

import qualified Text.XML.Light as X

type ELEM = [X.Attr] -> [X.Content] -> X.Content
type EMPTY_ELEM = [X.Attr] -> X.Content
type ATTR = String -> X.Attr

-- | Ordinary character data, subject to escaping.
cdata :: String -> X.Content
cdata s = X.Text (X.CData X.CDataText s Nothing)

mk_elem :: String -> ELEM
mk_elem nm z e = X.Elem (X.Element (X.unqual nm) z e Nothing)

mk_empty_elem :: String -> EMPTY_ELEM
mk_empty_elem nm z = X.Elem (X.Element (X.unqual nm) z [] Nothing)

mk_empty_elem_no_attr :: String -> X.Content
mk_empty_elem_no_attr nm = X.Elem (X.Element (X.unqual nm) [] [] Nothing)

mk_attr :: String -> ATTR
mk_attr nm = X.Attr (X.unqual nm)

clef :: ELEM
clef = mk_elem "clef"

type_A,id_A,number,spread,implicit,slash :: ATTR
type_A = mk_attr "type"
id_A = mk_attr "id"
number = mk_attr "number"
spread = mk_attr "spead"
implicit = mk_attr "implicit"
slash = mk_attr "slash"

placement,bracket,show_number,show_type :: ATTR
placement = mk_attr "placement"
bracket = mk_attr "bracket"
show_number = mk_attr "show-number"
show_type = mk_attr "show-type"

direction,direction_type,offset :: ELEM
direction = mk_elem "direction"
direction_type = mk_elem "direction-type"
offset = mk_elem "offset"

wedge :: EMPTY_ELEM
wedge = mk_empty_elem "wedge"

sign :: ELEM
sign = mk_elem "sign"

line :: ELEM
line = mk_elem "line"

clef_octave_change :: ELEM
clef_octave_change = mk_elem "clef-octave-change"

score_partwise :: ELEM
score_partwise = mk_elem "score-partwise"

work,work_number,work_title :: ELEM
work = mk_elem "work"
work_title = mk_elem "work-title"
work_number = mk_elem "work-number"

identification,creator,rights :: ELEM
identification = mk_elem "identification"
creator = mk_elem "creator"
rights = mk_elem "rights"

credit,credit_words :: ELEM
credit = mk_elem "credit"
credit_words = mk_elem "credit-words"

part_list,part_group,score_part :: ELEM
part_list = mk_elem "part-list"
part_group = mk_elem "part-group"
score_part = mk_elem "score-part"

part_name,part_abbreviation,score_instrument :: ELEM
part_name = mk_elem "part-name"
part_abbreviation = mk_elem "part-abbreviation"
score_instrument = mk_elem "score-instrument"

group_name,group_abbreviation,group_symbol,group_barline :: ELEM
group_name = mk_elem "group-name"
group_abbreviation = mk_elem "group-abbreviation"
group_symbol = mk_elem "group-symbol"
group_barline = mk_elem "group-barline"

instrument_name :: ELEM
instrument_name = mk_elem "instrument-name"

part,measure,attributes,divisions :: ELEM
part = mk_elem "part"
measure = mk_elem "measure"
attributes = mk_elem "attributes"
divisions = mk_elem "divisions"

key,fifths,mode :: ELEM
key = mk_elem "key"
fifths = mk_elem "fifths"
mode = mk_elem "mode"

time,beats,beat_type :: ELEM
time = mk_elem "time"
beats = mk_elem "beats"
beat_type = mk_elem "beat-type"

staves :: ELEM
staves = mk_elem "staves"

note,pitch,step,alter,octave,rest,duration,voice,type_E,stem,staff,beam,accidental :: ELEM
note = mk_elem "note"
pitch = mk_elem "pitch"
step = mk_elem "step"
alter = mk_elem "alter"
octave = mk_elem "octave"
rest = mk_elem "rest"
duration = mk_elem "duration"
voice = mk_elem "voice"
type_E = mk_elem "type"
stem = mk_elem "stem"
staff = mk_elem "staff"
beam = mk_elem "beam"
accidental = mk_elem "accidental"

notations,ornaments,technical,dynamics,tremolo :: ELEM
notations = mk_elem "notations"
ornaments = mk_elem "ornaments"
technical = mk_elem "technical"
dynamics = mk_elem "dynamics"
tremolo = mk_elem "tremolo"

arpeggiate,tie,tied,slur :: EMPTY_ELEM
arpeggiate = mk_empty_elem "arpeggiate"
tie = mk_empty_elem "tie"
tied = mk_empty_elem "tied"
slur = mk_empty_elem "slur"

harmonic :: ELEM
harmonic = mk_elem "harmonic"

natural :: EMPTY_ELEM
natural = mk_empty_elem "natural"

forward,backup :: ELEM
forward = mk_elem "forward"
backup = mk_elem "backup"

chord,cue,grace,dot :: EMPTY_ELEM
chord = mk_empty_elem "chord"
cue = mk_empty_elem "cue"
grace = mk_empty_elem "grace"
dot = mk_empty_elem "dot"

time_modification,actual_notes,normal_notes,normal_type,normal_dot :: ELEM
time_modification = mk_elem "time-modification"
actual_notes = mk_elem "actual-notes"
normal_notes = mk_elem "normal-notes"
normal_type = mk_elem "normal-type"
normal_dot = mk_elem "normal-dot"

tuplet,tuplet_actual,tuplet_normal,tuplet_number,tuplet_type :: ELEM
tuplet = mk_elem "tuplet"
tuplet_actual = mk_elem "tuplet-actual"
tuplet_normal = mk_elem "tuplet-normal"
tuplet_number = mk_elem "tuplet-number"
tuplet_type = mk_elem "tuplet-type"

tuplet_dot :: EMPTY_ELEM
tuplet_dot = mk_empty_elem "tuplet-dot"

articulations :: ELEM
articulations = mk_elem "articulations"

accent :: EMPTY_ELEM
accent = mk_empty_elem "accent"

metronome,beat_unit,per_minute :: ELEM
metronome = mk_elem "metronome"
beat_unit = mk_elem "beat-unit"
per_minute = mk_elem "per-minute"

beat_unit_dot :: EMPTY_ELEM
beat_unit_dot = mk_empty_elem "beat-unit-dot"

-- * String constants

musicxml_xml :: String
musicxml_xml = "<?xml version=\"1.0\" standalone=\"no\"?>"

type DocType = String

musicxml_partwise :: DocType
musicxml_partwise = "<!DOCTYPE score-partwise PUBLIC \"-//Recordare//DTD MusicXML 1.0 Partwise//EN\" \"http://www.musicxml.org/dtds/partwise.dtd\">"