-- $Date: 2004/02/14 09:46:15 $
-- $Revision: 1.12 $
-- $Author: jcrocholl $

with Readers; use Readers;
with Token_Readers; use Token_Readers;

with Parts; use Parts;
with Parts.MusicXML; use Parts.MusicXML;
with Works.MusicXML; use Works.MusicXML;
with Identifications.MusicXML; use Identifications.MusicXML;

package body Scores.MusicXML is

   procedure Read_Part_List
     (XML  : access XML_Reader-- Use this XML reader.
      This : access Score) is   -- Add parts to this score.
   begin
      while Descend(XML) loop
         if Found(XML, "score-part") then
            Add_Part(This, Read_Score_Part(XML));
         else
            XML_Expect_Error(XML, "/part-list", "score-part");
         end if;
      end loop;
      Exit_Tag(XML);
   end Read_Part_List;

   -- Write a part-list to an XML writer.
   procedure Write_Part_List
     (XML  : access XML_Writer-- Use this XML writer.
      This : access Part_List)  -- Write this part-list.
   is
      use Scores.Part_Lists;
      Part : Part_Access;
   begin
      Start_Element(XML, "part-list");

      Reset(This);
      while Next(This) loop
         Part := Current(This);
         Write_Score_Part(XML, Part);
      end loop;

      Close_Element(XML, "part-list");
   end Write_Part_List;

   -- Read a score header from an XML reader.
   procedure Read_Score_Header
     (XML  : access XML_Reader-- Use this XML reader.
      This : access Score) is   -- Add information to this score.
   begin
      while Descend(XML) loop
         Exit_Tag(XML);

         if Found(XML, "work") then
            Set_Work(This, Read_Work(XML));
         elsif Found(XML, "movement-number") then
            Set_Movement_Number(This, Read_Data(XML));
         elsif Found(XML, "movement-title") then
            Set_Movement_Title(This, Read_Data(XML));
         elsif Found(XML, "identification") then
            Set_Identification(This, Read_Identification(XML));
         elsif Found(XML, "part-list") then
            Read_Part_List(XML, This);
            exit;
         else
            XML_Expect_Error(XML, "/score-header",
              "work" / "movement-number" / "movement-title" /
              "identification" / "part-list");
         end if;

         if not Context_Is(XML, "score-partwise")
           and not Context_Is(XML, "score-timewise")
         then
            Exit_Element(XML);
         end if;
      end loop;
   end Read_Score_Header;

   -- Write a score header to an XML writer.
   procedure Write_Score_Header
     (XML  : access XML_Writer-- Use this XML writer.
      This : access Score)      -- Write the header for this score.
   is
   begin
      if Get_Work(This) /= null then
         Write_Work(XML, Get_Work(This));
      end if;
      if Get_Movement_Title(This) /= "" then
         Write_Element(XML, "movement-title", Get_Movement_Title(This));
      end if;
      if Get_Identification(This) /= null then
         Write_Identification(XML, Get_Identification(This));
      end if;
      Write_Part_List(XML, Get_Parts(This));
   end Write_Score_Header;

   procedure Read_Parts
     (XML  : access XML_Reader-- Use this XML reader.
      This : access Score)      -- Read parts of this score.
   is
      use Part_Lists;
      Parts : Part_List_Access := Get_Parts(This);
      Part  : Part_Access;
   begin
      Reset(Parts);
      while Next(Parts) loop
         Part := Current(Parts);
         Read_Part(XML, Part);
      end loop;
   end Read_Parts;

   -- Write parts from a part list to an XML writer.
   procedure Write_Parts
     (XML  : access XML_Writer-- Use this XML writer.
      This : access Part_List)  -- Write these parts.
   is
      use Scores.Part_Lists;
      Part : Part_Access;
   begin
      Reset(This);
      while Next(This) loop
         Part := Current(This);
         Write_Part(XML, Part);
      end loop;
   end Write_Parts;

   -----------------------
   -- Partwise or timewise
   -----------------------

   -- Read a partwise score from an XML reader.
   function Read_Score_Partwise
     (XML : access XML_Reader-- Use this XML reader.
     return Score_Access       -- The newly created score.
   is
      Result : Score_Access := Create;
   begin
      Exit_Tag(XML);
      Read_Score_Header(XML, Result);
      Read_Parts(XML, Result);
      return Result;
   end Read_Score_Partwise;

   -- Write a partwise score to an XML writer.
   procedure Write_Score_Partwise
     (XML  : access XML_Writer-- Use this XML writer.
      This : access Score) is   -- Write this score.
   begin
      Start_Element(XML, "score-partwise");
      Write_Score_Header(XML, This);
      Write_Parts(XML, Get_Parts(This));
      Close_Element(XML, "score-partwise");
   end Write_Score_Partwise;

   -- Read a timewise score from an XML reader.
   function Read_Score_Timewise
     (XML : access XML_Reader-- Use this XML reader.
     return Score_Access       -- The newly created score.
   is
      Result : Score_Access := null;
   begin
      Error(XML, "Timewise scores are not yet supported.");
      return Result;
   end Read_Score_Timewise;

   -- Write a partwise score to an XML writer.
   procedure Write_Score_Timewise
     (XML  : access XML_Writer-- Use this XML writer.
      This : access Score) is   -- Write this score.
   begin
      Start_Element(XML, "score-timewise");
      Write_Part_List(XML, Get_Parts(This));
      Write_Parts(XML, Get_Parts(This));
      Close_Element(XML, "score-timewise");
   end Write_Score_Timewise;

   -- Read score data from an XML reader.
   function Read_Score
     (XML : access XML_Reader-- Use this XML reader.
     return Score_Access is    -- The newly created score.
   begin
      if not Descend(XML) then
         XML_Expect_Error(XML, "",
           "score-partwise" / "score-timewise");
         return null;
      end if;

      if Found(XML, "score-partwise") then
         return Read_Score_Partwise(XML);
      elsif Found(XML, "score-timewise") then
         return Read_Score_Timewise(XML);
      else
         XML_Expect_Error(XML, "",
           "score-partwise" / "score-timewise");
         return null;
      end if;
   end Read_Score;

end Scores.MusicXML;