%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Copyright (C) 2018-2021 The Octave Project Developers
%%
%% See the file COPYRIGHT.md in the top-level directory of this
%% distribution or <https://octave.org/copyright/>.
%%
%% This file is part of Octave.
%%
%% Octave 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 3 of the License, or
%% (at your option) any later version.
%%
%% Octave 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 Octave; see the file COPYING.  If not, see
%% <https://www.gnu.org/licenses/>.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

classdef weboptions_java < handle

  %% -*- texinfo -*-
  %% @deftypefn  {} {@var{output} =} weboptions_java ()
  %% @deftypefnx {} {@var{output} =} weboptions_java (@var{name1}, @var{value1}, @dots{})
  %%
  %% Specify parameters for RESTful web services.
  %%
  %% @code{weboptions_java} with no inputs returns a default @code{weboptions_java} object
  %% to specify parameters for a request to a web service.  A @code{weboptions_java}
  %% object can be an optional input argument to the @code{webread} and
  %% @code{webwrite} functions.
  %%
  %% Multiple name and value pair arguments may be specified in any order as
  %% @var{name1}, @var{value1}, @var{name2}, @var{value2}, etc.
  %%
  %% The option names must match @strong{exactly} one of those specified in the
  %% table below.
  %%
  %% The following options are available:
  %%
  %% @itemize @bullet
  %% @item
  %% @samp{CharacterEncoding} --- Specify the character encoding of the data:
  %%
  %% @samp{auto} (default), @samp{UTF-8}, @samp{US-ASCII}
  %% @samp{auto} chooses an encoding based on the content-type of the data.
  %%
  %% @item
  %% @samp{UserAgent} --- Specify the User Agent for the connection.
  %%
  %% Default value is @samp{GNU Octave/version}, where @samp{version} is the
  %% current version of Octave as returned by @code{version}.
  %%
  %% @item
  %% @samp{Timeout} --- Specify the timeout value for the connection in seconds.
  %%
  %% Default is 10 seconds.  @samp{Inf} is not currently supported.
  %%
  %% @item
  %% @samp{Username} --- User identifier for a basic HTTP connection.
  %%
  %% Default is NULL@.  It must be a string.
  %%
  %% @item
  %% @samp{Password} --- User authentication password for HTTP connection.
  %%
  %% Default is NULL@.  It must be a string or character vector.
  %% Programming Note: If you display a @code{weboption} object with the Password
  %% property set, the value is displayed as a string containing
  %% @qcode{'*'}.  However, the object stores the value of the Password
  %% property as plain text.
  %%
  %% @item
  %% @samp{KeyName} --- Specify the name of an additional key to be added to
  %% the HTTP request header.  It should be coupled with @samp{KeyValue}.  It
  %% must be a string or character vector.
  %%
  %% @item
  %% @samp{KeyValue} --- Specify the value of the key @samp{KeyName}.
  %%
  %% @samp{KeyName} must be present in order to assign to this field.
  %%
  %% @item
  %% @samp{@nospell{HeaderFields}} --- Specify the header fields for the
  %% connection.
  %%
  %% Names and values of header fields, specified as an m-by-2 array of strings
  %% or cell array of character vectors to add to the HTTP request header.
  %% @nospell{HeaderFields}@{i,1@} is the name of a field and
  %% @nospell{HeaderFields}@{i,2@} is its value.
  %%
  %% @example
  %% @group
  %% weboptions_java ('HeaderFields', @{'Content-Length' '78';'Content-Type' 'application/json'@})
  %% Creates a weboptions_java object that contains two header fields: Content-Length
  %% with value 78 and Content-Type with value application/json.
  %% @end group
  %% @end example
  %%
  %% @item
  %% @samp{ContentType} --- Specify the content type of the data.
  %%
  %% The following values are available:
  %% @samp{auto}, @samp{text}, @samp{json}
  %%
  %% Default is @samp{auto}.  It automatically determines the content type.
  %% All other formats like @samp{audio}, @samp{binary}, etc.@: available in
  %% @sc{matlab} are not currently supported.
  %%
  %% @item
  %% @samp{ContentReader} --- Not yet implemented.  Only for @sc{matlab}
  %% compatibility.
  %%
  %% @item
  %% @samp{MediaType} --- Not yet implemented.  Only for @sc{matlab}
  %% compatibility.
  %%
  %% @item
  %% @samp{RequestMethod} --- Specifies the type of request to be made.
  %%
  %% The following methods are available:
  %% @samp{get}, @samp{put}, @samp{post}, @samp{delete}, @samp{patch}
  %%
  %% @code{webread} uses the HTTP GET method.  @code{webwrite} uses the HTTP POST
  %% method as default.
  %%
  %% @item
  %% @samp{ArrayFormat} -- Not yet implemented.  Only for @sc{matlab}
  %% compatibility.
  %%
  %% @item
  %% @samp{CertificateFilename} --- Not yet implemented.  Only for @sc{matlab}
  %% compatibility.
  %% @end itemize
  %%
  %% @seealso{webread, webwrite}
  %% @end deftypefn

  properties
    CharacterEncoding = 'auto';
    UserAgent = ['GNU Octave/', version()];
    Timeout = 10;
    Username = '';
    Password = '';
    KeyName = '';
    KeyValue = '';
    HeaderFields = {};
    ContentType = 'auto';
    ContentReader = '';
    MediaType = 'auto';
    RequestMethod = 'auto';
    ArrayFormat = 'csv';
    CertificateFilename = '';
  end

  methods
    function f = weboptions_java (varargin)
      if (rem (numel (varargin), 2) ~= 0)
        error ('weboptions_java: invalid number of arguments');
      else
        h = cell2struct (varargin(2:2:end), varargin(1:2:end), 2);
        if is_Octave_test()
            is_numfields = (numfields (h) > 14);
        else
            is_numfields = (length(fieldnames (h)) > 14);
        end
        if is_numfields
          error ('weboptions_java: invalid number of arguments');
        end

        if (isfield (h, 'CharacterEncoding'))
          f.CharacterEncoding = h.CharacterEncoding;
          h = rmfield (h, 'CharacterEncoding');
        end

        if (isfield (h, 'UserAgent'))
          f.UserAgent = h.UserAgent;
          h = rmfield (h, 'UserAgent');
        end

        if (isfield (h, 'Timeout'))
          f.Timeout = h.Timeout;
          h = rmfield (h, 'Timeout');
        end

        if (isfield (h, 'Username'))
          f.Username = h.Username;
          h = rmfield (h, 'Username');
        end

        if (isfield (h, 'Password'))
          f.Password = h.Password;
          h = rmfield (h, 'Password');
        end

        if (isfield (h, 'KeyName'))
          f.KeyName = h.KeyName;
          h = rmfield (h, 'KeyName');
        end

        if (isfield (h, 'KeyValue'))
          f.KeyValue = h.KeyValue;
          h = rmfield (h, 'KeyValue');
        end

        if (isfield (h, 'HeaderFields'))
          f.HeaderFields = h.HeaderFields;
          h = rmfield (h, 'HeaderFields');
        end

        if (isfield (h, 'ContentType'))
          f.ContentType = h.ContentType;
          h = rmfield (h, 'ContentType');
        end

        if (isfield (h, 'ContentReader'))
          f.ContentReader = h.ContentReader;
          h = rmfield (h, 'ContentReader');
        end

        if (isfield (h, 'MediaType'))
          f.MediaType = h.MediaType;
          h = rmfield (h, 'MediaType');
        end

        if (isfield (h, 'RequestMethod'))
          f.RequestMethod = h.RequestMethod;
          h = rmfield (h, 'RequestMethod');
        end

        if (isfield (h, 'ArrayFormat'))
          f.ArrayFormat = h.ArrayFormat;
          h = rmfield (h, 'ArrayFormat');
        end

        if (isfield (h, 'CertificateFilename'))
          f.CertificateFilename = h.CertificateFilename;
          h = rmfield (h, 'CertificateFilename');
        end

        if (~ isempty (fieldnames (h)))
          field = fieldnames (h);
          error (['weboptions_java: Undefined field ' field{1}]);
        end
      end
    end

    function f = set.CharacterEncoding (f, value)
      if (~ any (strcmpi (value, {'UTF-8', 'US-ASCII', 'auto'})));
        error ('weboptions_java: Invalid CharacterEncoding value');
      else
        f.CharacterEncoding = value;
      end
    end

    function f = set.UserAgent (f, value)
      if (~ ischar (value) && ~ isrow (value));
        error ('weboptions_java: UserAgent must be a string');
      else
        f.UserAgent = value;
      end
    end

    function f = set.Timeout (f, value)
      if (~ isreal (value) || ~ isscalar (value) ...
          || floor(value) ~= value || value < 0)
        error ('weboptions_java: invalid Timeout value');
      else
        f.Timeout = value;
      end
    end

    function f = set.Username (f, value)
      if (~ ischar (value) && ~ isrow (value))
        error ('weboptions_java: Username must be a string');
      else
        f.Username = value;
      end
    end

    function f = set.Password (f, value)
      if (~ ischar (value) && ~ isrow (value))
        error ('weboptions_java: Password must be a string');
      else
        f.Password = value;
      end
    end

    function f = set.KeyName (f, value)
      if (~ ischar (value) && ~ isrow (value))
        error ('weboptions_java: invalid KeyName value');
      else
        f.KeyName = value;
      end
    end

    function f = set.KeyValue (f, value)
      if (isempty (f.KeyName) && ~ isempty (value))
        error ('weboptions_java: field KeyName empty.  Cannot set KeyValue.');
      else
        f.KeyValue = value;
      end
    end

    function f = set.HeaderFields (f, value)
      if (~ isempty (value))
        if (~ iscellstr (value) || ~ ismatrix (value))
          error ('weboptions_java: HeaderFields must be array of strings or a cell array');
        % fix for flattened array in __restful_service__
        elseif (size (value,2) ~= 2) && mod(numel(value),2) ~= 0
          error ('weboptions_java: HeaderFields must be of size m-by-2');
        end
      end
      f.HeaderFields = value;
    end

    function f = set.ContentType (f, value)
      if (~ isempty (value))
        if (~ any (strcmpi (value, {'auto', 'json', 'text'})))
          error ('weboptions_java: invalid ContentType value');
        end
      end
      f.ContentType = value;
    end

    function f = set.ContentReader (f, value)
      f.ContentReader = value;
    end

    function f = set.MediaType (f, value)
      f.MediaType = value;
    end

    function f = set.RequestMethod (f, value)
      if (~ isempty (value))
        if (~ any (strcmpi (value, {'auto', 'get', 'put', 'post',...
                                    'delete', 'patch'})))
          error ('weboptions_java: invalid RequestMethod value');
        end
      end
      f.RequestMethod = value;
    end

    function f = set.ArrayFormat (f, value)
      if (~ isempty (value))
        if (~ any (strcmpi (value, {'csv', 'json', 'php', 'repeating'})))
          error ('weboptions_java: invalid ArrayFormat value');
        end
      end
      f.ArrayFormat = value;
    end

    function f = set.CertificateFilename (f, value)
      f.CertificateFilename = value;
    end

    function disp (f)
      s_Timeout = int2str (f.Timeout);
      s_Password = repmat ('*', 1, numel (num2str (f.Password)));

      if (~ isempty (f.ContentReader))
        s_ContentReader = ['['', strjoin_test(f.ContentReader, '', ''), '']'];
      else
        s_ContentReader = '[]';
      end

      if (~ isempty (f.HeaderFields))
        s_HeaderFields = ['{'', strjoin_test(f.HeaderFields, '', ''), ''}'];
      else
        s_HeaderFields = '{}';
      end

      if (~ isempty (f.KeyValue))
        s_KeyValue = num2str (f.KeyValue);
      else
        s_KeyValue = '''';
      end

      printf ('%s =', inputname (1));
      output = ['\n\n   weboptions_java with properties:     \n',...
                '\n      CharacterEncoding: '', f.CharacterEncoding, ''',...
                '\n              UserAgent: '', f.UserAgent, ''',...
                '\n                Timeout: ' , s_Timeout, '',...
                '\n               Username: '', f.Username, ''',...
                '\n               Password: '', Password, ''',...
                '\n                KeyName: '', f.KeyName, ''',...
                '\n               KeyValue: ' , s_KeyValue,...
                '\n            ContentType: '', f.ContentType, ''',...
                '\n          ContentReader: ' , s_ContentReader,...
                '\n              MediaType: '', f.MediaType, ''',...
                '\n          RequestMethod: '', f.RequestMethod, ''',...
                '\n            ArrayFormat: '', f.ArrayFormat, ''',...
                '\n           HeaderFields: ' , s_HeaderFields,...
                '\n    CertificateFilename: '', f.CertificateFilename, ''\n'];
      disp (output);
    end

  end
  
end

