-- Topal: GPG/GnuPG and Alpine/Pine integration
-- Copyright (C) 2001--2022  Phillip J. Brooke
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License version 3 as
-- published by the Free Software Foundation.
--
-- 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, see <http://www.gnu.org/licenses/>.

with Ada.Text_IO;
with Command_Line_Wrapper; use Command_Line_Wrapper;
with Externals.Mail;
with Externals.Simple;
with Misc;                 use Misc;

package body Invocation is

   procedure Parse_Options (Parse_All : Boolean) is
   begin
      loop exit when not More;
         if Match(UBS_Array'(1 => ToUBS("-debug"),
                             2 => ToUBS("-d"),
                             3 => ToUBS("--debug"),
                             4 => ToUBS("--d"))) then
            Config.Boolean_Opts(Debug) := True;
         elsif Match("--simple") then
            Config.Boolean_Opts(FE_Simple) := True;
         elsif Match("--rewrite") then
            Config.Boolean_Opts(FE_Simple) := False;
         elsif Match("--no-clear") then
            Config.Boolean_Opts(No_Clean) := True;
         elsif Match("--read-from") then
            -- The user had better set _INCLUDEALLHDRS_...
            Config.Boolean_Opts(All_Headers) := True;
            Config.Boolean_Opts(Read_From) := True;
         elsif Match("--ask-charset") then
            Config.Boolean_Opts(Ask_Charset) := True;
         else
            -- We haven't got an options match.
            if Parse_All then
               Error("Option `" & Current & "' not recognised.");
            else
               -- Don't care.
               exit;
            end if;
         end if;
      end loop;
   end Parse_Options;

   procedure Parse_Command_Line is
   begin
      -- Sort out the command-line.
      Debug("Examining command-line options...");
      -- Eat up some options.
      Parse_Options(Parse_All => False);
      if not More then
         Run_Mode := Help_Text;
      else
         if Match(UBS_Array'(1 => ToUBS("-help"),
                             2 => ToUBS("-h"),
                             3 => ToUBS("--help"),
                             4 => ToUBS("--h"),
                             5 => ToUBS("-?"),
                             6 => ToUBS("--?"))) then
            Run_Mode := Help_Text;
            Parse_Options(Parse_All => True);
         elsif Match(UBS_Array'(1 => ToUBS("-display"),
                                2 => ToUBS("-decrypt"),
                                3 => ToUBS("-verify"))) then
           -- -decrypt and -verify are legacy for release 0.4.5 to 0.5.0.
            if not More(Needed => 2) then
               Error("-display, -decrypt and -verify need two arguments: _TMPFILE_ _RESULTFILE_");
            else
               Run_Mode := Inline_Display;
               Tmpfile := Eat;
               Resultfile := Eat;
            end if;
         elsif Match("-pd") then
            declare
               Stdin : constant String := Temp_File_Name("pdin");
               PDCT : constant String := Temp_File_Name("pdct");
               PDCT2 : constant String := Temp_File_Name("pdct2");
            begin
               Run_Mode := Pipe_Display;
               Infile := ToUBS(Stdin);
               Externals.Simple.Cat_Stdin_Out(Stdin);
               Externals.Mail.Extract_Content_Type_From_Header(Stdin,
                                                               PDCT,
                                                               Ignore_Missing => True,
                                                               Substitute => True);
               Externals.Simple.Sed_InOut("s/^.*: //; s/\;.*//", PDCT, PDCT2);
               Content_Type := Read_Fold(PDCT2);
            end;
	 elsif Match("-raw") then
	    Run_Mode := Raw_Input;
         elsif Match("-mime") then
            if not More(Needed => 2) then
               Error("-mime needs two arguments: INFILE CONTENT-TYPE");
            else
               Run_Mode := Mime_Display;
               Infile := Eat;
               Content_Type := Eat;
            end if;
         elsif Match("-mimeapgp") then
            if not More(Needed => 2) then
               Error("-mimeapgp needs two arguments: INFILE CONTENT-TYPE");
            else
               Run_Mode := Old_Mime_Display;
               Infile := Eat;
               Content_Type := Eat;
            end if;
         elsif Match("-send") then
            if not More(Needed => 2) then
               Error("-send needs at least two arguments: _TMPFILE_ _RESULTFILE_"
                     & ", then _RECIPIENTS_");
            else
               Run_Mode := Inline_Send;
               Tmpfile := Eat;
               Resultfile := Eat;
               Recipients := Eat_Remaining_Arguments;
            end if;
         elsif Match("-sendmime") then
            if not More(Needed => 3) then
               Error("-sendmime needs at least three arguments: _TMPFILE_ _RESULTFILE_ _MIMETYPE_"
                     & ", then _RECIPIENTS_");
            else
               Run_Mode := Mime_Send;
               Tmpfile := Eat;
               Resultfile := Eat;
               Mimefile := Eat;
               Recipients := Eat_Remaining_Arguments;
            end if;
         elsif Match("-asend") then
	    Run_Mode := Actual_Send;
	    Remaining := Eat_Remaining_Arguments;
         elsif Match("-remotesend") then
            if not More(Needed => 3) then
               Error("-remotesend needs at least three arguments: _TMPFILE_ _RESULTFILE_ _RVFILE_"
                     & ", then _RECIPIENTS_");
            else
               Run_Mode := Remote_Send;
               Tmpfile := Eat;
               Resultfile := Eat;
               RVfile     := Eat;
               Recipients := Eat_Remaining_Arguments;
            end if;
         elsif Match("-remotesendmime") then
            if not More(Needed => 4) then
               Error("-remotesendmime needs at least four arguments: _TMPFILE_ _RESULTFILE_ _RVFILE_ _MIMETYPE_"
                     & ", then _RECIPIENTS_");
            else
               Run_Mode := Remote_Mime_Send;
               Tmpfile := Eat;
               Resultfile := Eat;
               RVfile := Eat;
               Mimefile := Eat;
               Recipients := Eat_Remaining_Arguments;
            end if;
         elsif Match("-remotedecrypt") then
            if not More(Needed => 1) then
               Error("-remotedecrypt needs at least one argument: _INFILE_");
            else
               Run_Mode := Remote_Decrypt;
               Infile := Eat;
            end if;
         elsif Match("-remotemimedecrypt") then
            if not More(Needed => 2) then
               Error("-remotemimedecrypt needs at least one argument: _INFILE_ _CONTENT_TYPE_");
            else
               Run_Mode := Remote_MIME_Decrypt;
               Infile := Eat;
               Content_Type := Eat;
            end if;
         elsif Match("-server") then
            Run_Mode := Server;
         elsif Match("-clear") then
            Run_Mode := Clear_Temp;
         elsif Match("-clearc") then
            Run_Mode := Clear_Cache;
         elsif Match("-clearall") then
            Run_Mode := Clear_All;
         elsif Match("-default") then
            Run_Mode := Dump_Default_Config;
         elsif Match("-dump") then
            Run_Mode := Dump_Current_Config;
         elsif Match("-config") then
            Run_Mode := Interactive_Config;
         elsif Match(UBS_Array'(1 => ToUBS("--fix-email"),
                                2 => ToUBS("-fe")))
           or Command_Basename = "topal-fix-email" then
            Run_Mode := Fix_Email;
         elsif Match(UBS_Array'(1 => ToUBS("--fix-folder"),
                                2 => ToUBS("-ff")))
           or Command_Basename = "topal-fix-folder" then
            Run_Mode := Fix_Folders;
            Folders := Eat_Remaining_Arguments;
         elsif Match(UBS_Array'(1 => ToUBS("--check-send-token"),
                                2 => ToUBS("-cst"))) then
            Run_Mode := Check_Send_Token;
            CST_Token := Eat;
         elsif Match(UBS_Array'(1 => ToUBS("-nps"),
                                2 => ToUBS("-s"))) then
            if not More then
               Error("-nps (-s) needs at least one argument: _THEFILE_"
                     & ", then _RECIPIENTS_");
            else
               Run_Mode := Nonpine_Send;
               Tmpfile := Eat;
               Recipients := Eat_Remaining_Arguments;
            end if;
         else
            -- Assume we meant topal -s arg1 arg2 ...
            Run_Mode := Nonpine_Send;
            Tmpfile := Eat;
            Recipients := Eat_Remaining_Arguments;
         end if;
      end if;
      -- Eat any remaining arguments; let's hope they're options.
      Parse_Options(Parse_All => True);
   exception
      when others =>
         Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
                              "Exception raised in Invocation.Parse_Command_Line");
         raise;
   end Parse_Command_Line;

end Invocation;
