-- GWindows Installer
-- (code first generated by GWenerator as a test application)

with GW_Install_Resource_GUI;           use GW_Install_Resource_GUI;

with Zip;                               use Zip;
with UnZip;                             use UnZip;

with GWin_Util;

with GWindows.Application;
with GWindows.Base;
with GWindows.Buttons;                  use GWindows.Buttons;
with GWindows.Constants;                use GWindows.Constants;
with GWindows.Common_Dialogs;           use GWindows.Common_Dialogs;
with GWindows.Static_Controls.Web;      use GWindows.Static_Controls.Web;
with GWindows.Message_Boxes;            use GWindows.Message_Boxes;
with GWindows.Windows;                  use GWindows.Windows;

with Ada.Command_Line;                  use Ada.Command_Line;
with Ada.Directories;                   use Ada.Directories;
with Ada.Exceptions;                    use Ada.Exceptions;
with Ada.Strings.Unbounded;             use Ada.Strings.Unbounded;

with Ada_Directories_Extensions; -- Ada 201X items absent in Ada 2005...

procedure GW_Install is

  Install_dir: Unbounded_String:= To_Unbounded_String("");
  mem_cur_dir: constant String:= Current_Directory & '\';

  type Character_mode is (ANSI, UNICODE);
  Mode: Character_mode:= ANSI;
  Proceed, OK: Boolean;
  With_GWenerator: Boolean:= True;
  No_Parent : Window_Type;

  procedure Main_install_dialog(Success: out Boolean) is
    Main_Dlg  : GW_Install_Resource_GUI.Main_install_dialog_Type;
    Result    : Integer;

    procedure Select_directory( Parent : in out GWindows.Base.Base_Window_Type'Class ) is
    begin
       Main_Dlg.Directory_edit.Text(
         Get_Directory(Parent,
         "Choose a target directory. GWindows, GNATCOM and " & ASCII.LF &
         "GWenerator sub-folders will be created in that directory."
         )
       );
    end Select_directory;

    procedure Get_Data ( dummy : in out GWindows.Base.Base_Window_Type'Class ) is
      pragma Warnings(off, dummy);
    begin
      Install_dir:= To_Unbounded_String(Main_Dlg.Directory_edit.Text);
      if Main_Dlg.ANSI_choice.State = Checked then
        Mode:= ANSI;
      else
        Mode:= UNICODE;
      end if;
       With_GWenerator:= Main_Dlg.GWen_check.State = Checked;
    end Get_Data;

  begin -- Main_install_dialog
    Create_Full_Dialog (Main_Dlg, No_Parent);
    Center(Main_Dlg);
    Small_Icon (Main_Dlg, "AAA_Main_Icon");
    Large_Icon (Main_Dlg, "AAA_Main_Icon");
    Main_Dlg.Directory_select_button.Hide;
    Main_Dlg.Directory_select_button_permanent.Show;
    Main_Dlg.GNATCOM_check.State(Checked);
    if With_GWenerator then
      Main_Dlg.GWen_check.State(Checked);
    end if;
    case Mode is
      when ANSI =>
        Main_Dlg.ANSI_choice.State(Checked);
      when UNICODE =>
        Main_Dlg.UNICODE_choice.State(Checked);
    end case;
    Main_Dlg.Text(Main_Dlg.Text & Version_info.FileVersion);
    Main_Dlg.Setup_title.Text(Main_Dlg.Setup_title.Text & Version_info.FileVersion);
    Main_Dlg.Directory_edit.Text(To_String(Install_dir));
    On_Destroy_Handler (Main_Dlg, Get_Data'Unrestricted_Access);
    On_Click_Handler (
      Main_Dlg.Directory_select_button_permanent,
      Select_directory'Unrestricted_Access
    );
    Result := GWindows.Application.Show_Dialog (Main_Dlg);
    Success:= Result = IDOK;
  end Main_install_dialog;

  procedure Self_extract(Success: out Boolean) is
    zi: Zip_Info;
    n: Natural:= 0;
    pct_old: Natural:= 0;
    No_Parent : Window_Type;
    Unpack_Dlg: GW_Install_Resource_GUI.Unpack_dialog_Type;
    --
    procedure Tell_data
              ( name               : String;
                compressed_bytes   : Zip.File_size_type;
                uncompressed_bytes : Zip.File_size_type;
                method             : Zip.PKZip_method )
    is
    pragma Unreferenced (compressed_bytes, uncompressed_bytes, method);
      pct: Natural;
    begin
      n:= n + 1;
      pct:= (100 * n) / Entries(zi);
      if pct /= pct_old then
        GWindows.Application.Message_Check;
      end if;
      pct_old:= pct;
      Unpack_Dlg.Unpack_progress.Position(pct);
      Unpack_Dlg.File_name.Text(name);
    end Tell_data;
    --
    My_FS_routines: constant UnZip.FS_routines_type:=
      ( Create_Path         => Ada.Directories.Create_Path'Access, -- Ada 2005
        Set_Time_Stamp      => Ada_Directories_Extensions.Set_Modification_Time'Access,
        Compose_File_Name   => null,
        others              => null
      );
    --
    procedure Extract_1_file( name: String ) is
      gwen_dir: constant String:= "gwenerator";
    begin
      if With_GWenerator or
        (name'Length < gwen_dir'Length or else
         name(name'First .. name'First + gwen_dir'Length -1) /= gwen_dir)
      then
        Extract(
          zi, name, null, null, Tell_Data'Unrestricted_Access, null,
          file_system_routines => My_FS_routines
        );
      end if;
    end Extract_1_file;
    --
    procedure Extract_all_files is new Zip.Traverse( Extract_1_file );
    --
  begin
    Success:= False;
    Set_Directory(To_String(Install_dir));
    Create_Full_Dialog (Unpack_Dlg, No_Parent);
    Small_Icon (Unpack_Dlg, "AAA_Main_Icon");
    Large_Icon (Unpack_Dlg, "AAA_Main_Icon");
    Center(Unpack_Dlg);
    Show(Unpack_Dlg);
    Unpack_Dlg.Redraw(Redraw_Now => True); -- otherwise icons don't show up!
    begin
      Load(zi, Command_Name);
      Extract_all_files(zi);
    exception
      when E:others =>
        Message_Box(
          "GWindows installation error",
          "Archive extraction failed - maybe a broken download ?" & ASCII.LF &
          "Archive = " & Command_Name & ASCII.LF &
          Exception_Name(E) & ASCII.LF & Exception_Message(E),
          Icon => Error_Icon
        );
        Set_Directory(mem_cur_dir);
        return;
    end;
    Set_Directory(mem_cur_dir);
    Success:= True;
  end Self_extract;

  procedure Copy_encoding_dependent(base: String) is
    img: constant String:= Character_Mode'Image(Mode);
    pfx1: constant String:= base & "coding\gwindows";
    pfx2: constant String:= base & "gwindows";
  begin
    Copy_File(
      pfx1 & "_" & img & ".ads",
      pfx2 & ".ads"
    );
    Copy_File(
      pfx1 & "-gstrings_" & img & ".adb",
      pfx2 & "-gstrings.adb"
    );
    Copy_File(
      pfx1 & "-gstrings-handling_" & img & ".ads",
      pfx2 & "-gstrings-handling.ads"
    );
    Copy_File(
      pfx1 & "-gstrings-maps_" & img & ".ads",
      pfx2 & "-gstrings-maps.ads"
    );
    Copy_File(
      pfx1 & "-gstrings-maps_constants_" & img & ".ads",
      pfx2 & "-gstrings-maps_constants.ads"
    );
    Copy_File(
      pfx1 & "-gstrings-unbounded_" & img & ".ads",
      pfx2 & "-gstrings-unbounded.ads"
    );
  end Copy_encoding_dependent;

  Result: Message_Box_Result;

  procedure Quit is
    Ciao: Goodbye_dialog_type;
    Ciao_2: Goodbye_dialog_2_type;
    GNAT, GNAVI, GNAVI_SF, GNAVI_Dis, MinGW, ResEdit: URL_Type;
    procedure Get_Data ( dummy : in out GWindows.Base.Base_Window_Type'Class ) is
      pragma Warnings(off, dummy);
      id: constant String:= To_String(Install_dir);
    begin
      if Ciao_2.Open_folder.State = Checked then
        GWin_Util.Start(id & "\gwindows");
      end if;
      if Ciao_2.Open_user_guide.State = Checked then
        GWin_Util.Start(id & "\gwindows\docs\User_Guide.html");
      end if;
      if Ciao_2.Open_gnatcom_folder.State = Checked then
        GWin_Util.Start(id & "\gnatcom");
      end if;
      if Ciao_2.Build_gnatcom.State = Checked then
        Set_Directory(id & "\gnatcom");
        GWin_Util.Start(id & "\gnatcom\build_tools.cmd", Minimized => True);
        Set_Directory(mem_cur_dir);
      end if;
      if With_GWenerator then
        if Ciao_2.Build_gwenerator.State = Checked then
          Set_Directory(id & "\gwenerator");
          GWin_Util.Start(id & "\gwenerator\build.cmd", Minimized => True);
          Set_Directory(mem_cur_dir);
        end if;
        if Ciao_2.Open_gwenerator_folder.State = Checked then
          GWin_Util.Start(id & "\gwenerator");
        end if;
        if Ciao_2.Open_gwenerator_doc.State = Checked then
          GWin_Util.Start(id & "\gwenerator\gwenerator_info.html");
        end if;
      end if;
    end Get_Data;
  begin
    Create_Full_Dialog (Ciao, No_Parent);
    Center(Ciao);
    Small_Icon (Ciao, "AAA_Main_Icon");
    Large_Icon (Ciao, "AAA_Main_Icon");
    Create_and_Swap(GNAT, Ciao.GNAT_URL, Ciao, "http://libre.adacore.com/");
    Create_and_Swap(MinGW, Ciao.MinGW_URL, Ciao, "http://mingw.org/");
    Create_and_Swap(GNAVI, Ciao.GNAVI_URL, Ciao, "http://www.gnavi.org/");
    Create_and_Swap(GNAVI_SF, Ciao.GNAVI_SF_URL, Ciao, "http://www.sourceforge.net/projects/gnavi/");
    Create_and_Swap(GNAVI_Dis, Ciao.GNAVI_Discuss_URL, Ciao, "http://lists.sourceforge.net/lists/listinfo/gnavi-discuss");
    Create_and_Swap(ResEdit, Ciao.ResEdit_URL, Ciao, "http://www.resedit.net/");
    GWindows.Application.Show_Dialog (Ciao);
    --
    Create_Full_Dialog (Ciao_2, No_Parent);
    Center(Ciao_2);
    Small_Icon (Ciao_2, "AAA_Main_Icon");
    Large_Icon (Ciao_2, "AAA_Main_Icon");
    Ciao_2.Open_folder.State(Checked);
    Ciao_2.Open_gnatcom_folder.State(Checked);
    Ciao_2.Build_gnatcom.State(Checked);
    Ciao_2.Open_user_guide.State(Checked);
    if With_GWenerator then
      Ciao_2.Build_gwenerator.State(Checked);
      Ciao_2.Open_gwenerator_folder.State(Checked);
      Ciao_2.Open_gwenerator_doc.State(Checked);
    else
      Ciao_2.Build_gwenerator.Disable;
      Ciao_2.Open_gwenerator_folder.Disable;
      Ciao_2.Open_gwenerator_doc.Disable;
    end if;
    On_Destroy_Handler (Ciao_2, Get_Data'Unrestricted_Access);
    GWindows.Application.Show_Dialog (Ciao_2);
  end Quit;

begin
  if Argument_Count > 0 then
    -- Install_dir
    -- /a = ANSI
    -- /u = UNICODE
    -- /c = command line, no GUI, no question: can be used in a batch file
    --
    null; -- !!
  end if;
  loop
    Main_install_dialog(OK);
    exit when not OK;
    Proceed:= True;
    -- We check: 1) existing version; 2) valid directory
    if Ada.Directories.Exists(To_String(Install_dir) &
       "\gwindows\framework\gwindows.ads")
    then
      -- Conflict
      -- !! nicer box with side-by-side comparison and dates
      Result:=
        Message_Box(
          "GWindows installation - possible version conflict",
          "A version of GWindows is already installed there." & ASCII.LF &
          "Do you want to replace it ?",
          Yes_No_Box,
          Question_Icon
        );
      if Result = No then
        Proceed:= False;
      end if;
    end if;
    if Proceed then
      begin
        Create_Path(To_String(Install_dir));
      exception
        when Name_Error =>
          Proceed:= False;
          Message_Box(
            "Invalid directory for GWindows installation",
            "Directory """ & To_String(Install_dir) & """ cannot be created",
            Icon => Error_Icon
          );
      end;
      if Proceed then
        Self_extract(OK);
        if not OK then
          exit;
        end if;
        Copy_encoding_dependent(To_String(Install_dir) & "\gwindows\framework\");
        Quit;
        exit;
      end if;
    end if;
  end loop;
end GW_Install;
