with Ada.Text_IO;         use Ada.Text_IO;
with Dash_Board;

package body Clock is

   -------------
   -- Display --
   -------------

   procedure Display (C : access Clock) is
   begin
      InDash.Instrument_Reference (C).Display;
      Put (Character'Val (Character'Pos ('0') + C.Hours / 10));
      Put (Character'Val (Character'Pos ('0') + C.Hours mod 10));
      Put (":");
      Put (Character'Val (Character'Pos ('0') + C.Minutes / 10));
      Put (Character'Val (Character'Pos ('0') + C.Minutes mod 10));
      Put (":");
      Put (Character'Val (Character'Pos ('0') + C.Seconds / 10));
      Put (Character'Val (Character'Pos ('0') + C.Seconds mod 10));
   end Display;

   ------------
   -- Update --
   ------------

   procedure Update (C : access Clock; Millisec : Integer) is
      nInc : Integer := Millisec / 1000;
   begin
      C.Seconds := (C.Seconds + nInc) mod 60;
      nInc := (C.Seconds + nInc) / 60;
      C.Minutes := (C.Minutes + nInc) mod 60;
      nInc := (C.Minutes + nInc) / 60;
      C.Hours := (C.Hours + nInc) mod 24;
   end Update;

   -------------
   -- Display --
   -------------

   procedure Display (C : access Chronometer) is
     V : Integer;
   begin
      InDash.Instrument_Reference (C).Display;

      V :=  C.Seconds + C.Minutes * 60 + C.Hours * 3600;

      Put ("<<");
      Put (Character'Val (Character'Pos ('0') + (V / 1000) mod 10));
      Put (Character'Val (Character'Pos ('0') + (V / 100) mod 10));
      Put (Character'Val (Character'Pos ('0') + (V / 10) mod 10));
      Put (Character'Val (Character'Pos ('0') + V mod 10));
      Put (">>");
   end Display;

   -------------
   -- Display --
   -------------

   procedure Display (C : access Accurate_Clock) is
   begin
      Clock_Reference (C).Display;
      Put (":");
      Put (Character'Val (Character'Pos ('0') + (C.MilliSec / 100) mod 10));
      Put (Character'Val (Character'Pos ('0') + (C.MilliSec / 10) mod 10));
      Put (Character'Val (Character'Pos ('0') + C.MilliSec mod 10));
   end Display;

   ------------
   -- Update --
   ------------

   procedure Update (C : access Accurate_Clock; Millisec : Integer) is
   begin
      Clock_Reference (C).Update (Millisec + C.Millisec);
      C.MilliSec := (C.MilliSec + Millisec) mod 1000;
   end Update;

   ----------
   -- Make --
   ----------

   function Make_Clock
     (Name : String;
      Hours, Minutes, Seconds : Integer)
      return Clock_Reference
   is
      Result : Clock_Reference;
   begin
      Result := new Clock;
      Result.Set_Name (Name);
      Result.Hours   := Hours;
      Result.Minutes := Minutes;
      Result.Seconds := Seconds;
      return Result;
   end Make_Clock;

   ----------
   -- Make --
   ----------

   function Make_Chronometer
     (Name : String;
      Hours, Minutes, Seconds : Integer)
      return Chronometer_Reference
   is
      Result : Chronometer_Reference;
   begin
      Result := new Chronometer;
      Result.Set_Name (Name);
      Result.Hours   := Hours;
      Result.Minutes := Minutes;
      Result.Seconds := Seconds;
      return Result;
   end Make_Chronometer;

   ----------
   -- Make --
   ----------

   function Make_Accurate_Clock
     (Name : String;
      Hours, Minutes, Seconds, Millisec : Integer)
      return Accurate_Clock_Reference
   is
      Result : Accurate_Clock_Reference;
   begin
      Result := new Accurate_Clock;
      Result.Set_Name (Name);
      Result.Hours   := Hours;
      Result.Minutes := Minutes;
      Result.Seconds := Seconds;
      Result.Millisec := Millisec;
      return Result;
   end Make_Accurate_Clock;


   use InDash;
begin
   Dash_Board.Register
     (Any_Instrument (Make_Clock          ("New York",  12, 15, 0   )));
   Dash_Board.Register
     (Any_Instrument (Make_Chronometer    ("Stopwatch",  0,  0, 0   )));
   Dash_Board.Register
     (Any_Instrument (Make_Accurate_Clock ("Paris",      6, 15, 0, 0)));
end Clock;
