-- Primfakt in Ada, provided by
-- Nicolas Courtel -- courtel@dgac.fr
-- Centre d'Etudes de la Navigation Aerienne

with TEXT_IO; use  TEXT_IO;
with CALENDAR; use  CALENDAR;
 
procedure PRIMFAKT is
 
   MAX_BUFFER_LENGTH : constant := 200; -- Buffer to read from and write to User interface
 
   procedure XUI(REQUEST : in STRING) is
   begin
      PUT_LINE('%' & REQUEST);
   end XUI;
 
   procedure SET_LABEL(WIDGET, LABEL : in STRING) is
   begin
      PUT_LINE("%sV " & WIDGET & " label {" & LABEL & "}");
   end SET_LABEL;
 
begin
   XUI("form top topLevel");
   XUI("asciiText input top editType edit width 200");
   XUI("action input override {<Key>Return: exec(echo [gV input string])}" & ASCII.LF);
   XUI("label result top label {} width 200 fromVert input");
   XUI("command quit top fromVert result callback quit");
   XUI("label info top fromVert result fromHoriz quit label {} borderWidth 0 width 150");
   XUI("realize");
 
   loop
      declare
         type STRING_ACCESS is access STRING;
 
         BUFFER               : STRING(1 .. MAX_BUFFER_LENGTH); -- Input data
         OUTPUT               : STRING_ACCESS;                  -- Result
         NEW_OUTPUT           : BOOLEAN;                        -- Are we starting new output string?
         START_TIME, END_TIME : CALENDAR.TIME;
         TIME_STRING          : STRING_ACCESS;
 
         BUFFER_LENGTH        : NATURAL;                        -- Length of the input string
         VALUE                : INTEGER;                        -- Input value
 
      begin
         GET_LINE(BUFFER, BUFFER_LENGTH);
         VALUE := INTEGER'VALUE(BUFFER(1 .. BUFFER_LENGTH));
         SET_LABEL("info", "thinking...");
         SET_LABEL("result", "");
         NEW_OUTPUT := TRUE;
 
         START_TIME := CLOCK;
         for DIVISOR in 2 .. VALUE loop
            while VALUE mod DIVISOR = 0 loop
               VALUE := VALUE / DIVISOR;
               if NEW_OUTPUT then
                  OUTPUT := new STRING'(INTEGER'IMAGE(DIVISOR));
                  NEW_OUTPUT := FALSE;
               else
                  OUTPUT := new STRING'(OUTPUT.all & " *" & INTEGER'IMAGE(DIVISOR));
               end if;
            end loop;
         end loop;
         END_TIME := CLOCK;
 
         TIME_STRING := new STRING'(INTEGER'IMAGE(INTEGER((END_TIME - START_TIME) * 1000)) & " milliseconds");
         SET_LABEL("info", TIME_STRING.all);
         SET_LABEL("result", OUTPUT.all);
 
      exception
         when CONSTRAINT_ERROR =>
            XUI("sV result label {}");
            XUI("sV info label {invalid input}");
      end;
 
   end loop;
end PRIMFAKT;
