http://www.adaconcept.com/programs/ontozorendszeres_szimulacio/szimulacio-ontozorendszer-elemek.adb
with Ada.Text_IO;

with Ada.Tags;                                                                                     -- Nagyon fontos csomag!
with System.Address_Image;

with Hiba_Kezelo;

with Szimulacio.Ontozorendszer.Csovezetek_Modell;

with Szimulacio.Ontozorendszer.Elemek.Vizforras;
with Szimulacio.Ontozorendszer.Elemek.Cso;
with Szimulacio.Ontozorendszer.Elemek.Szorofej;

with Szimulacio.Ontozorendszer.Megjelenito.Muveletek;

package body Szimulacio.Ontozorendszer.Elemek is

   package Modell                renames Szimulacio.Ontozorendszer.Csovezetek_Modell;
   package Megjelenito_Muveletek renames Szimulacio.Ontozorendszer.Megjelenito.Muveletek;


   procedure Inicializal(Objektum : in out Frissitheto_Absztrakt_Tipus) is
      pragma Unreferenced(Objektum);  -- ilyet latunk meg :)
   begin
      -- Ada.Text_IO.Put_Line("A Frissitheto_Absztrakt_Tipus Inicializal eljarasa. (Az inicializalas nem lett felulirva a konkret objektumoknal.)");  -- sokszor fut majd
      null;                                                                                        -- csak ez lenne a torzs, vagy hibajelzes...
   end Inicializal;


   Ontozorendszer_Elemek : Ontozorendszer_Elemek_Tomb_Tipus;                                       -- nem fernek kozza a gyerekcsomagok sem

   Ontozorendszer_Elemek_Mutato : Ontozorendszer_Elemek_Tomb_Index_Tipus := Ontozorendszer_Elemek'First;

   akt : Ontozorendszer_Elemek_Tomb_Index_Tipus := 1;                                              -- az aktualisan frissitendo elem "mutatoja" (kulso iterator helyett...) figyelem, veszelyes igy valtozot hasznalni, mert "barki" modosithatja az erteket a csomag torzseben veletlenul


   procedure Regisztral(Uj_Elem : Frissitheto_Absztrakt_Ontozorendszer_Elem_Osztaly_Mutato_Tipus) is
   begin
      Ontozorendszer_Elemek(Ontozorendszer_Elemek_Mutato) := Uj_Elem;
      Ontozorendszer_Elemek_Mutato := Ontozorendszer_Elemek_Mutato + 1;

      if Uj_Elem.all in Szimulacio.Ontozorendszer.Elemek.Szorofej.Szorofej_Tipus'Class then        -- feltetel egy tipusoszalyhoz tartozashoz
         Ada.Text_IO.Put_Line("Egy szorofej regisztralva. (a mutato cime)  "       & System.Address_Image(Uj_Elem'Address));
         Ada.Text_IO.Put_Line("Egy szorofej regisztralva. (a mutatott elem cime) " & System.Address_Image(Uj_Elem.all'Address));
      end if;
   end Regisztral;


   procedure Csovet_Regisztral(Reszletpont_Azonosito : Terv.Reszletpont_Azonosito_Tipus; Vizforrastol_Mert_Tavolsag : Natural; Csatlakozasok : Terv.Cso_Csatlakozasok_Tomb_Tipus) is
   begin

      -- itt nem egyszeru sorok jonnek... :)
      -- attol fuggoen, hogy hany masik elemhez csatlakozik egy cso, cso tipusokat hozunk letre es regisztralunk
      case Csatlakozasok'Length is
         when 0 =>
            null;

         when 1 =>
            Ontozorendszer_Elemek(Ontozorendszer_Elemek_Mutato) :=
              new Ontozorendszer.Elemek.Cso.Cso_Tipus'(Frissitheto_Absztrakt_Tipus with
                                                       Azonosito => Reszletpont_Azonosito,
                                                       Vizforrastol_Mert_Tavolsag => Vizforrastol_Mert_Tavolsag,
                                                       Eleje => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Reszletpont_Azonosito))'Access,
                                                       Vege  => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(1)))'Access);
            Ontozorendszer_Elemek_Mutato := Ontozorendszer_Elemek_Mutato + 1;

         when 2 =>
            Ontozorendszer_Elemek(Ontozorendszer_Elemek_Mutato) :=
              new Ontozorendszer.Elemek.Cso.Ketagu_Eloszto_Cso_Tipus'(Frissitheto_Absztrakt_Tipus with
                                                                      Azonosito => Reszletpont_Azonosito,
                                                                      Vizforrastol_Mert_Tavolsag => Vizforrastol_Mert_Tavolsag,
                                                                      Eleje => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Reszletpont_Azonosito))'Access ,
                                                                      Ag1   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(1)))'Access ,
                                                                      Ag2   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(2)))'Access);
            Ontozorendszer_Elemek_Mutato := Ontozorendszer_Elemek_Mutato + 1;

         when 3 =>
            Ontozorendszer_Elemek(Ontozorendszer_Elemek_Mutato) :=
              new Ontozorendszer.Elemek.Cso.Haromagu_Eloszto_Cso_Tipus'(Frissitheto_Absztrakt_Tipus with
                                                                        Azonosito => Reszletpont_Azonosito,
                                                                        Vizforrastol_Mert_Tavolsag => Vizforrastol_Mert_Tavolsag,
                                                                        Eleje => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Reszletpont_Azonosito))'Access,
                                                                        Ag1   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(1)))'Access ,
                                                                        Ag2   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(2)))'Access,
                                                                        Ag3   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(3)))'Access);
            Ontozorendszer_Elemek_Mutato := Ontozorendszer_Elemek_Mutato + 1;

         when 4 =>
            Ontozorendszer_Elemek(Ontozorendszer_Elemek_Mutato) :=
              new Ontozorendszer.Elemek.Cso.Negyagu_Eloszto_Cso_Tipus'(Frissitheto_Absztrakt_Tipus with
                                                                       Azonosito => Reszletpont_Azonosito,
                                                                       Vizforrastol_Mert_Tavolsag => Vizforrastol_Mert_Tavolsag,
                                                                       Eleje => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Reszletpont_Azonosito))'Access,
                                                                       Ag1   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(1)))'Access ,
                                                                       Ag2   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(2)))'Access,
                                                                       Ag3   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(3)))'Access,
                                                                       Ag4   => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Csatlakozasok(4)))'Access);
            Ontozorendszer_Elemek_Mutato := Ontozorendszer_Elemek_Mutato + 1;

         when others =>
            Hiba_Kezelo.Program_Leallitas("Tervezesi hiba!!!");
      end case;


   end Csovet_Regisztral;


   procedure Vizforrast_Regisztral(Reszletpont_Azonosito : Terv.Reszletpont_Azonosito_Tipus) is
   begin
      -- a vizforras (egyke) inicializalasa es "lekerese" es regisztralasa
      Szimulacio.Ontozorendszer.Elemek.Vizforras.Inicializal(Azonosito       => Reszletpont_Azonosito,
                                                             Csovezetek_Elem => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(Reszletpont_Azonosito))'Access);

      Ontozorendszer_Elemek(Ontozorendszer_Elemek_Mutato) := Szimulacio.Ontozorendszer.Elemek.Vizforras.Vizforras;
      Ontozorendszer_Elemek_Mutato := Ontozorendszer_Elemek_Mutato + 1;
   end Vizforrast_Regisztral;


   function Vizforrastol_Mert_Tavolsag(Objektum : Frissitheto_Absztrakt_Ontozorendszer_Elem_Tipus) return Natural is
   begin
      return Objektum.Vizforrastol_Mert_Tavolsag;
   end Vizforrastol_Mert_Tavolsag;


   function Megjelenit(Objektum : Megjelenitheto_Absztrakt_Tipus) return Megjelenito.String_Tomb_Tipus is
      pragma Unreferenced(Objektum);                                                               -- ha nem szeretnenk, hogy a warning uzenet megjelenjen a nem hasznalt parameter miatt (ugyanakkor jelezzuk a kod olvasojanak, hogy tudatosan nem hasznaljuk a parametert)
   begin
      return Megjelenito.Ures_String_Tomb_Ertek;                                                   -- "extremalis" ertek
   end Megjelenit;


   function Megjelenit_Hivas_Dinamikus_Kotessel(Objektum : Megjelenitheto_Absztrakt_Tipus'Class) return Megjelenito.String_Tomb_Tipus is
   begin
      return Megjelenit(Objektum);                                                                 -- dinamikus kotes, figyeljuk meg, hogy az aktualis parameter osztalyszintu a formalis pedig konkret...
   end Megjelenit_Hivas_Dinamikus_Kotessel;



   procedure Frissit_Hivas_Dinamikus_Kotessel(Objektum : Frissitheto_Absztrakt_Ontozorendszer_Elem_Osztaly_Mutato_Tipus) is
   begin
      Frissit(Objektum.all);                                                                       -- dinamikus kotes  (az aktualis parameter tipusa osztalyszintu, a formalis specializalt)
   end;



   Ontozorendszer_Elemek_Letrehozva : Boolean := False;                                            -- azert, hogy a Letrehozas eljarast csak egyszer lehessen meghivni

   procedure Letrehozas is

      Csatlakozasok : constant Terv.Terv_Tipus := Terv.Cso_Csatlakozasok;

      procedure Csovezetek_Elemek_Osszeallitasa is
         use type Szimulacio.Kert.Terv_Elemek_Tipus;

      begin

         for t in Csatlakozasok'Range loop
            declare
               Csatlakozasok : constant Terv.Cso_Csatlakozasok_Tomb_Tipus := Terv.Cso_Csatlakozasok(t);  -- figyelem, elfedjuk a Csatlakozasok valtozot!
            begin

               -- peldak regisztraciokra

               if Terv.Vizforrastol_Mert_Tavolsag(t) = 0 then
                  Vizforrast_Regisztral(t);
               end if;

               Csovet_Regisztral(t, Terv.Vizforrastol_Mert_Tavolsag(t), Csatlakozasok);

               if Reszletpontok(t).Tipus = Kert.Szorofej then
                  Regisztral(new Ontozorendszer.Elemek.Szorofej.Szorofej_Tipus'(
                    Ontozorendszer.Elemek.Szorofej.Beallit(Azonosito => t,
                                                           Vizforrastol_Mert_Tavolsag => Ontozorendszer.Terv.Vizforrastol_Mert_Tavolsag(t),
                                                           Csovezetek_Elem => Modell.Csovezetek_Modell(Modell.Csovezetek_Modell_Tomb_Index_Tipus(t))'Access)
                                                           ));
               end if;

            end;
         end loop;


         Ada.Text_IO.Put_Line("Regisztralt ontozorendszer elemek szama: " & Ontozorendszer_Elemek_Tomb_Index_Tipus'Image(Ontozorendszer_Elemek_Mutato - 1) );

      end Csovezetek_Elemek_Osszeallitasa;


      procedure Csovezetek_Elemek_Rendezese_Vizforrastol_Mert_Tavolsag_Szerint is
         T : Frissitheto_Absztrakt_Ontozorendszer_Elem_Osztaly_Mutato_Tipus;
      begin
         for i in Ontozorendszer_Elemek'First .. Ontozorendszer_Elemek_Mutato-2 loop
            for j in i+1..Ontozorendszer_Elemek_Mutato - 1 loop
               if Vizforrastol_Mert_Tavolsag(Ontozorendszer_Elemek(i).all) > Vizforrastol_Mert_Tavolsag(Ontozorendszer_Elemek(j).all) then
                  T := Ontozorendszer_Elemek(i);
                  Ontozorendszer_Elemek(i) := Ontozorendszer_Elemek(j);
                  Ontozorendszer_Elemek(j) := T;
               end if;
            end loop;
         end loop;
      end Csovezetek_Elemek_Rendezese_Vizforrastol_Mert_Tavolsag_Szerint;

   begin

      if not Ontozorendszer_Elemek_Letrehozva then
         Ontozorendszer_Elemek_Letrehozva := True;
      else
         Hiba_Kezelo.Program_Leallitas("A Szimulacio.Ontozorendszer.Elemek.Letrehozas csak egyszer hivhato meg!");
      end if;


      Csovezetek_Elemek_Osszeallitasa;
      Csovezetek_Elemek_Rendezese_Vizforrastol_Mert_Tavolsag_Szerint;                                        -- az objektumok sorrendje befolyasolja a program mukodeset (probald ki mi tortenik, ha ezt a sort elhagyod)

   end Letrehozas;


   type Ontozorendszer_Allapot_Informacio_Tipus is new Megjelenitheto_Absztrakt_Tipus with null record;      -- ennek a modszernek a segitsegevel a Megjelenito -nek nem szukseges kozvetlenul hozzafernie a belso valtozokhoz

   -- overriding
   function Megjelenit(Objektum : Ontozorendszer_Allapot_Informacio_Tipus) return Megjelenito.String_Tomb_Tipus is
      pragma Unreferenced(Objektum);

      use type Kert.Terv_Elemek_Tipus;
      use type Modell.Cso_Allapot_Tipus;
      use type Modell.Csovezetek_Modell_Tomb_Index_Tipus;
      use type Megjelenito.String_Tomb_Tipus;

      Modell_Index : Modell.Csovezetek_Modell_Tomb_Index_Tipus := Modell.Csovezetek_Modell_Tomb_Index_Tipus'First;

      Ontozorendszer_Kep : Megjelenito.String_Tomb_Tipus(Kert.Terv'Range(1)) := (others => (others => Megjelenito.Ures_Hely_Karakter));
      most_frissulo : Natural := 0;
   begin


      for i in Kert.Terv'Range(1) loop
         for j in Kert.Terv'Range(2) loop

            if Kert.Terv(i,j) = Kert.Fu then
               Ontozorendszer_Kep(i)(j) := '.';
            else
               most_frissulo := most_frissulo + 1;

               if Modell.Csovezetek_Modell(Modell_Index) = Modell.Van_Benne_Viz then
                  Ontozorendszer_Kep(i)(j) := '1';
               else
                  Ontozorendszer_Kep(i)(j) := '0';
               end if;

               if most_frissulo = Ontozorendszer_Elemek(akt).all.Azonosito  then
                  Ontozorendszer_Kep(i)(j) := 'X';
               end if;

               if Modell_Index < Modell.Csovezetek_Modell_Tomb_Index_Tipus'Last then
                  Modell_Index := Modell.Csovezetek_Modell_Tomb_Index_Tipus'Succ(Modell_Index);
               end if;
            end if;

         end loop;
      end loop;


      return Ontozorendszer_Kep &
             Megjelenito_Muveletek.Stringbe_Masol("A kovetkezo frissulo elem tipusa:") &
             Megjelenito_Muveletek.Stringbe_Masol(Ada.Tags.Expanded_Name(Ontozorendszer_Elemek(akt).all'Tag)) &   -- informaciok lekerese az aktualis jelolt tipusrol
             Megjelenito_Muveletek.Stringbe_Masol("");
   end Megjelenit;


   Ontozorendszer_Allapot_Informacio : aliased Ontozorendszer_Allapot_Informacio_Tipus;


   -- Az inicializalasnak tobb fajtaja van.
   -- van, hogy az objektum inicializalja onmagat, es van, hogy kivulrol megadott ertekekkel inicializaljuk az objektumot...
   -- es persze ezek keveredhetnek
   procedure Inicializalas is
   begin

      Megjelenito_Muveletek.Regisztral("Ontozorendszer Allapot Informacio", Megjelenitheto_Absztrakt_Tipus(Ontozorendszer_Allapot_Informacio)'Access);

      for i in 1 .. Ontozorendszer_Elemek_Mutato - 1 loop
         Inicializal(Ontozorendszer_Elemek(i).all);
      end loop;

      Ada.Text_IO.Put_Line("Az inicializalas vegetert.");
      delay 2.0;
   end Inicializalas;


   procedure Frissites is
      use type Modell.Cso_Allapot_Tipus;

      function Kovetkezo(Elem_Index : Ontozorendszer_Elemek_Tomb_Index_Tipus) return Ontozorendszer_Elemek_Tomb_Index_Tipus is
      begin
         if Elem_Index < Ontozorendszer_Elemek_Mutato - 1 then
            return Elem_Index + 1;
         else
            return 1;
         end if;
      end Kovetkezo;

   begin
      Frissit_Hivas_Dinamikus_Kotessel(Ontozorendszer_Elemek(akt));
      akt := Kovetkezo(akt);
   end Frissites;


end Szimulacio.Ontozorendszer.Elemek;