with Ada.Strings.UTF_Encoding;

with AnsiAda;

package CLIC.TTY
with Preelaborate
is

   subtype UTF_8_String is Ada.Strings.UTF_Encoding.UTF_8_String;

   --  Color/Formatting related subprograms. These won't have any
   --  effect if a redirection of output is detected, or if global
   --  flag Simple_Logging.Is_TTY is false.

   --  Re-expose for clients
   package ANSI renames AnsiAda;

   function Is_TTY return Boolean;

   procedure Force_Disable_TTY
     with Post => not Is_TTY;
   --  Disable TTY support even if availabe

   --------------------
   -- Color enabling --
   --------------------

   function Color_Enabled return Boolean;

   procedure Disable_Color;
   --  Disables color/formatting output even when TTY is capable

   procedure Enable_Color (Force : Boolean := False);
   --  Prepares colors for the logging messages. Unless Force, will do nothing
   --  if a console redirection is detected.

   function Format (Text  : String;
                    Fore  : ANSI.Colors := ANSI.Default;
                    Back  : ANSI.Colors := ANSI.Default;
                    Style : ANSI.Styles := ANSI.Default)
                    return String;
   --  Wrap text with the appropriate ANSI sequences. Following text will be
   --  unaffected. Default colors are interpreted as no change of color (will
   --  result in no color sequences), not as setting the default color (which
   --  is always set after a color change).

   ------------------------
   -- Predefined formats --
   ------------------------

   function Text_With_Fallback (Text : String; Fallback : String)
                                return String
     with Post => Text_With_Fallback'Result =
       (if Color_Enabled and then Is_TTY then Text else Fallback);
   --  Intended to have a rich text and a safe alternative

   function Info (Text : UTF_8_String := "") return UTF_8_String;
   --  Prepends Text with a Emph ("🛈") or "Note: " if no tty color enabled

   function Success (Text : UTF_8_String := "") return UTF_8_String;
   --  Prepends Text (in normal formatting) with a green check mark, or a
   --  simple Success: text if no tty or color enabled.

   function OK (Text : String) return String;
   --  Bold Light_Green

   function Emph (Text : String) return String;
   --  Something to highlight not negatively, bold cyan

   function Error (Text : String) return String;
   --  Bold Red

   function Warn (Text : String) return String;
   --  Bold Yellow

   function Bold (Text : String) return String;

   function Dim (Text : String) return String;

   function Italic (Text : String) return String;

   function Underline (Text : String) return String;

   function Description (Text : String) return String;
   --  Not bold cyan for crate descriptions

   function Terminal (Text : String) return String;
   --  For showing commands that the user can run; mimics old amber displays.

   function URL (Text : String) return String;

   function Version (Text : String) return String;
   --  For versions/version sets, bold magenta

private

   function Text_With_Fallback (Text : String; Fallback : String)
                                return String
   is (if Color_Enabled and then Is_TTY
       then Text
       else Fallback);

   function Info (Text : UTF_8_String := "") return UTF_8_String is
     (if Color_Enabled and then Is_TTY
      then Emph (U ("ⓘ")) & " " & Text
      else "Note: " & Text);

   function Success (Text : UTF_8_String := "") return UTF_8_String is
     (if Color_Enabled and then Is_TTY
      then OK (U ("✓")) & " " & Text
      else "Success: " & Text);

   function OK (Text : String) return String is
     (Format (Text,
              Fore  => ANSI.Light_Green,
              Style => ANSI.Bright));

   function Emph (Text : String) return String is
     (Format (Text,
              Fore  => ANSI.Cyan,
              Style => ANSI.Bright));

   function Error (Text : String) return String is
     (Format (Text,
              Fore  => ANSI.Red,
              Style => ANSI.Bright));

   function Warn (Text : String) return String is
     (Format (Text,
              Fore  => ANSI.Yellow,
              Style => ANSI.Bright));

   function Bold (Text : String) return String is
     (Format (Text,
              Style => ANSI.Bright));

   function Dim (Text : String) return String is
     (Format (Text,
              Style => ANSI.Dim));

   function Italic (Text : String) return String is
     (Format (Text,
              Style => ANSI.Italic));

   function Underline (Text : String) return String is
     (Format (Text,
              Style => ANSI.Underline));

   function Name (Text : String) return String is
     (Bold (Text));

   function Description (Text : String) return String is
     (Format (Text,
              Fore  => ANSI.Light_Cyan));

   function Terminal (Text : String) return String is
     (if Color_Enabled and then Is_TTY
      then ANSI.Color_Wrap (Text, ANSI.Palette_Fg (5, 3, 0))
      else Text);

   function URL (Text : String) return String renames Version;

   function Version (Text : String) return String is
     (Format (Text,
              Fore  => ANSI.Magenta,
              Style => ANSI.Bright));

end CLIC.TTY;
