------------------------------------------------------------------------------
--                                                                          --
--                           POLYORB COMPONENTS                             --
--                                                                          --
--                         A W S . R E S P O N S E                          --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--         Copyright (C) 2000-2012, Free Software Foundation, Inc.          --
--                                                                          --
-- This is free software;  you can redistribute it  and/or modify it  under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  This software is distributed in the hope  that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY 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 and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
--                  PolyORB is maintained by AdaCore                        --
--                     (email: sales@adacore.com)                           --
--                                                                          --
------------------------------------------------------------------------------

--  This package is to be used to build answer to be sent to the client
--  browser.

with Ada.Strings.Unbounded;
with Ada.Streams;
with Ada.Finalization;

with AWS.Headers;
with AWS.Status;
with AWS.Messages;
with AWS.MIME;
--  with AWS.Net;
with AWS.Resources.Streams;
with AWS.Utils;

with SOAP.Message.Response;

package AWS.Response is

   use Ada;

   type Data is private;
   --  Note that this type use a reference counter which is not thread safe.

   type Data_Access is access all Data;

   type Data_Mode is (Header, Message, File, Stream, Socket_Taken, No_Data,
                      SOAP_Message);

   type Authentication_Mode is (Any, Basic, Digest);
   --  The authentication mode.
   --  "Basic" and "Digest" mean that server must accept the requested
   --  authentication mode. "Any" mean that server could accept any
   --  authentication from client.
   --  Note the order here should not be changed as it is used in AWS.Client.

   subtype Content_Length_Type is Integer range -1 .. Integer'Last;

   Undefined_Length : constant Content_Length_Type;
   --  Undefined length could be used when we do not know the message length
   --  at the start of transfer. The end of message could be determined by the
   --  chunked transfer-encoding in the HTTP/1.1, or by the closing connection
   --  in the HTTP/1.0.

   Default_Moved_Message : constant String
     := "Page moved<br><a href=""_@_"">Click here</a>";
   --  This is a template message, _@_ will be replaced by the Location (see
   --  function Build with Location below).

   ------------------
   -- Constructors --
   ------------------

   function Build
     (Content_Type  : String;
      Message_Body  : String;
      Status_Code   : Messages.Status_Code  := Messages.S200;
      Cache_Control : Messages.Cache_Option := Messages.Unspecified)
      return Data;

   function Build
     (Content_Type    : String;
      UString_Message : Strings.Unbounded.Unbounded_String;
      Status_Code     : Messages.Status_Code  := Messages.S200;
      Cache_Control   : Messages.Cache_Option := Messages.Unspecified)
      return Data;
   --  Return a message whose body is passed into Message_Body. The
   --  Content_Type parameter is the MIME type for the message
   --  body. Status_Code is the response status (see Messages.Status_Code
   --  definition).

   function Build
     (Content_Type  : String;
      Message_Body  : Streams.Stream_Element_Array;
      Status_Code   : Messages.Status_Code         := Messages.S200;
      Cache_Control : Messages.Cache_Option        := Messages.Unspecified)
      return Data;
   --  Idem above, but the message body is a stream element array.

   function Build
     (SOAP_Body : SOAP.Message.Response.Object)
      return Data;
   --  new function to build a soap response

   function URL (Location : String) return Data;
   --  This ask the server for a redirection to the specified URL.

   function Moved
     (Location : String;
      Message  : String := Default_Moved_Message)
      return Data;
   --  This send back a moved message (Messages.S301) with the specified
   --  message body.

   function Acknowledge
     (Status_Code  : Messages.Status_Code;
      Message_Body : String := "";
      Content_Type : String := MIME.Text_HTML)
      return Data;
   --  Returns a message to the Web browser. This routine must be used to
   --  send back an error message to the Web browser. For example if a
   --  requested resource cannot be served a message with status code S404
   --  must be sent.

   function Authenticate
     (Realm : String;
      Mode  : Authentication_Mode := Basic;
      Stale : Boolean             := False)
      return Data;
   --  Returns an authentification message (Messages.S401), the Web browser
   --  will then ask for an authentification. Realm string will be displayed
   --  by the Web Browser in the authentification dialog box.

   function File
     (Content_Type : String;
      Filename     : String;
      Status_Code  : Messages.Status_Code := Messages.S200)
      return Data;
   --  Returns a message whose message body is the content of the file. The
   --  Content_Type must indicate the MIME type for the file.

   function Stream
     (Content_Type  : String;
      Stream_Handle : Resources.Streams.Stream_Access;
      Stream_Size   : Content_Length_Type   := Undefined_Length;
      Status_Code   : Messages.Status_Code  := Messages.S200;
      Cache_Control : Messages.Cache_Option := Messages.No_Cache)
      return Data;
   --  Returns a message whose message body is the content of the user
   --  defined stream. The Content_Type must indicate the MIME type for
   --  the data stream, Stream_Size the total number of bytes and Status_Code
   --  the header status code which should be send back to client's browser.

   function Socket_Taken return Data;
   --  Must be used to say that the connection socket has been taken by user
   --  inside of user callback. No operations should be performed on this
   --  socket, and associated slot should be released for further operations.

   function Empty return Data;
   --  Returns an empty message (Data_Mode = No_Data and Status_Code is 204).
   --  It is used to say that user's handlers were not able to do something
   --  with the request. This is used by the callback's chain in the
   --  dispatcher and should not be used by users.

   ---------------
   -- Other API --
   ---------------

   function Header
     (D    : Data;
      Name : String;
      N    : Positive)
      return String;
   pragma Inline (Header);
   --  Return the N-th value for header Name.

   function Header
     (D    : Data;
      Name : String)
      return String;
   pragma Inline (Header);
   --  Return all values as a comma-separated string for header Name.
   --  See [RFC 2616 - 4.2] last paragraph.

--     procedure Send_Header (Socket : Net.Socket_Type'Class; D : Data);
--     pragma Inline (Send_Header);
   --  Send all header lines to the socket.

   function Mode (D : Data) return Data_Mode;
   pragma Inline (Mode);
   --  Returns the data mode, either Header, Message or File.

   function Authentication (D : Data) return Authentication_Mode;
   pragma Inline (Authentication);
   --  Returns the authentication mode requested by server.

   function Authentication_Stale (D : Data) return Boolean;
   pragma Inline (Authentication_Stale);
   --  Returns the stale parameter for authentication.

   function Status_Code (D : Data) return Messages.Status_Code;
   pragma Inline (Status_Code);
   --  Returns the status code.

   function Content_Length (D : Data) return Content_Length_Type;
   pragma Inline (Content_Length);
   --  Returns the content length (i.e. the message body length). A value of 0
   --  indicate that there is no message body.

   function Content_Type (D : Data) return String;
   pragma Inline (Content_Type);
   --  Returns the MIME type for the message body.

   function Cache_Control (D : Data) return Messages.Cache_Option;
   pragma Inline (Cache_Control);
   --  Returns the cache control specified for the response

   function Filename (D : Data) return String;
   pragma Inline (Filename);
   --  Returns the filename which should be sent back.

   function Location (D : Data) return String;
   pragma Inline (Location);
   --  Returns the location for the new page in the case of a moved
   --  message. See Moved constructor above.

   function Message_Body (D : Data) return String;
   pragma Inline (Message_Body);
   --  Returns the message body content as a string.

   function Message_Body
     (D : Data)
      return Strings.Unbounded.Unbounded_String;
   pragma Inline (Message_Body);
   --  Returns the message body content as a unbounded_string.

   function Message_Body (D : Data) return Streams.Stream_Element_Array;
   pragma Inline (Message_Body);
   --  Returns message body as a binary content.

   function SOAP_Message (D : Data) return SOAP.Message.Response.Object;
   pragma Inline (SOAP_Message);
   --  returns the soap objects carried by D

   procedure Create_Resource
     (File :    out AWS.Resources.File_Type;
      D    : Data);
   pragma Inline (Create_Resource);
   --  Creates the resource object (either a file or in-memory object) for
   --  the data to be sent to the client. The resource should be closed after
   --  use.

   function Realm (D : Data) return String;
   pragma Inline (Realm);
   --  Returns the Realm for the current authentification request.

   type Callback is access function (Request : Status.Data) return Data;
   --  This is the Web Server Callback procedure. A client must declare and
   --  pass such procedure to the HTTP record.

private

   use Ada.Strings.Unbounded;

   Undefined_Length : constant Content_Length_Type := -1;

   type Natural_Access is access Natural;

   type Data is new Ada.Finalization.Controlled with record
      Ref_Counter    : Natural_Access;
      Mode           : Data_Mode            := No_Data;
      Status_Code    : Messages.Status_Code := Messages.S200;
      Content_Length : Content_Length_Type  := 0;
      Filename       : Unbounded_String;
      Stream         : Resources.Streams.Stream_Access;
      Message_Body   : Utils.Stream_Element_Array_Access;
      SOAP_Message   : SOAP.Message.Response.Object;  --  new field
      Header         : AWS.Headers.List;
   end record;

   procedure Initialize (Object : in out Data);
   procedure Adjust     (Object : in out Data);
   procedure Finalize   (Object : in out Data);

end AWS.Response;
