--
--  D_Bus/Ada - An Ada binding to D-Bus
--
--  Copyright (C) 2011  Reto Buerki <reet@codelabs.ch>
--
--  This program is free software; you can redistribute it and/or
--  modify it under the terms of the GNU General Public License
--  as published by the Free Software Foundation; either version 2
--  of the License, or (at your option) any later version.
--
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with this program; if not, write to the Free Software
--  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
--  USA.
--
--  As a special exception, if other files instantiate generics from this
--  unit,  or  you  link  this  unit  with  other  files  to  produce  an
--  executable   this  unit  does  not  by  itself  cause  the  resulting
--  executable to  be  covered by the  GNU General  Public License.  This
--  exception does  not  however  invalidate  any  other reasons why  the
--  executable file might be covered by the GNU Public License.
--

with Ada.Strings.Unbounded;
with Ada.Environment_Variables;
with Ada.Containers.Ordered_Maps;

with D_Bus.Connection;
with D_Bus.Arguments.Basic;
with D_Bus.Arguments.Containers;

procedure NM_DHCP_Client_Action
is
   use Ada.Strings.Unbounded;
   use D_Bus;
   use type D_Bus.Arguments.Containers.Array_Type;

   Ignored_Args : constant array (1 .. 5) of Unbounded_String
     := (To_Unbounded_String ("PATH"),
         To_Unbounded_String ("SHLVL"),
         To_Unbounded_String ("_"),
         To_Unbounded_String ("PWD"),
         To_Unbounded_String ("dhc_dbus"));
   --  Env args to ignore.

   package Name_Value_Map_Package is new Ada.Containers.Ordered_Maps
     (Key_Type     => Unbounded_String,
      Element_Type => Unbounded_String);

   package NVMP renames Name_Value_Map_Package;

   DHCP_Args : NVMP.Map;

   Conn : constant Connection.Connection_Type
     := Connection.Connect (Bus => Bus_System);
   Args : Arguments.Containers.Array_Type;

   -------------------------------------------------------------------------

   procedure Append_Arg (Position : NVMP.Cursor);
   --  Append dhcp env arg as D-Bus dict entry to array.

   procedure Append_Arg (Position : NVMP.Cursor)
   is
      use D_Bus.Arguments.Containers;
      use D_Bus.Arguments.Basic;

      Value      : constant String := To_String (NVMP.Element (Position));
      Dict       : Dict_Entry_Type;
      Variant    : Variant_Type;
      Byte_Array : Array_Type;
   begin
      for B in Value'Range loop
         Byte_Array.Append (New_Item => +Byte'(Character'Pos (Value (B))));
      end loop;

      Variant := Create (Source => Byte_Array);

      Dict := Create (Key   => +To_String (NVMP.Key (Position)),
                      Value => Variant);
      Args.Append (New_Item => Dict);
   end Append_Arg;

   -------------------------------------------------------------------------

   procedure Filter_Arg (Name, Value : String);
   --  Check if given env arg should be ignored.

   procedure Filter_Arg (Name, Value : String)
   is
   begin
      if Value'Length = 0 then
         return;
      end if;

      for A in Ignored_Args'Range loop
         if Name = To_String (Ignored_Args (A)) then
            return;
         end if;
      end loop;

      DHCP_Args.Insert (Key      => To_Unbounded_String (Name),
                        New_Item => To_Unbounded_String (Value));
   end Filter_Arg;

begin
   Ada.Environment_Variables.Iterate (Process => Filter_Arg'Access);

   DHCP_Args.Iterate (Process => Append_Arg'Access);

   Connection.Request_Name
     (Connection => Conn,
      Name       => "org.freedesktop.nm_dhcp_client");

   Connection.Send_Signal (Connection  => Conn,
                           Object_Name => "/",
                           Iface       => "org.freedesktop.nm_dhcp_client",
                           Name        => "Event",
                           Args        => +Args);
end NM_DHCP_Client_Action;
