unit XData.Web.Client;

interface

uses
  Classes, SysUtils,
  Bcl.Rtti.Common,
  XData.Model.Classes,
  XData.Web.Connection,
  XData.Web.Request,
  XData.Web.Response;

const
{$IF COMPILERVERSION > 28}
  pidWeb = $10000;
{$ELSE}
  pidWeb = $1000;
{$IFEND}
  TMSWebPlatform = pidWin32 + pidWin64 + pidWeb;

type
  JSValue = type Variant;
  TJSObject = type TObject;
  TJSArray = type TObject;
  TXDataWebClient = class;

  TXDataClientResponse = class
  private
    FStatusCode: Integer;
    FResponseText: string;
    FRequestId: string;
    FResult: JSValue;
    FClient: TXDataWebClient;
    FResponse: IHttpResponse;
    FCount: Integer;
    FResultAsObject: TJSObject;
    FResultAsArray: TJSArray;
  public
    property StatusCode: Integer read FStatusCode;
    property ResponseText: string read FResponseText;
    property Result: JSValue read FResult;
    property ResultAsObject: TJSObject read FResultAsObject;
    property ResultAsArray: TJSArray read FResultAsArray;
    property RequestId: string read FRequestId;
    property Count: Integer read FCount;
    property Client: TXDataWebClient read FClient;
    property Response: IHttpResponse read FResponse;
  end;

  TXDataClientRequest = class
  strict private
    FRequestId: string;
    FClient: TXDataWebClient;
    FRequest: IHttpRequest;
  public
    property RequestId: string read FRequestId;
    property Client: TXDataWebClient read FClient;
    property Request: IHttpRequest read FRequest;
  end;

  TXDataClientError = class
  private
    FRequestId: string;
    FStatusCode: Integer;
    FRequestUrl: string;
    FErrorCode: string;
    FErrorMessage: string;
    FClient: TXDataWebClient;
    FResponse: IHttpResponse;
  public
    property StatusCode: Integer read FStatusCode;
    property RequestUrl: string read FRequestUrl;
    property RequestId: string read FRequestId;
    property ErrorCode: string read FErrorCode;
    property ErrorMessage: string read FErrorMessage;
    property Client: TXDataWebClient read FClient;
    property Response: IHttpResponse read FResponse;
  end;

  TXDataClientLoadEvent = procedure(Response: TXDataClientResponse) of object;
  TXDataClientLoadProc = reference to procedure(Response: TXDataClientResponse);
  TXDataClientErrorEvent = procedure(Error: TXDataClientError) of object;
  TXDataClientErrorProc = reference to procedure(Error: TXDataClientError);
  TXDataClientRequestEvent = procedure(Request: TXDataClientRequest) of object;

  TReferenceSolvingMode = (rsAll, rsNone);

  [ComponentPlatforms(TMSWebPlatform)]
  TXDataWebClient = class(TComponent)
  private
    FOnLoad: TXDataClientLoadEvent;
    FConnection: TXDataWebConnection;
    FOnError: TXDataClientErrorEvent;
    FOnRequest: TXDataClientRequestEvent;
    FReferenceSolvingMode: TReferenceSolvingMode;
    procedure SetConnection(const Value: TXDataWebConnection);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    procedure Get(const EntitySet: string; Id: JSValue; const RequestId: string = 'get'); overload;
    procedure Get(const EntitySet: string; Id: JSValue; SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc = nil); overload;
    procedure Get(const EntitySet, QueryString: string; Id: JSValue; const RequestId: string = 'get'); overload;
    procedure Get(const EntitySet, QueryString: string; Id: JSValue; SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc = nil); overload;
    function GetAsync(const EntitySet, QueryString: string; Id: JSValue): TXDataClientResponse; overload;
    function GetAsync(const EntitySet: string; Id: JSValue): TXDataClientResponse; overload;
    procedure Put(const EntitySet: string; Entity: TJSObject; const RequestId: string = 'put'); overload;
    procedure Put(const EntitySet: string; Entity: TJSObject; SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc = nil); overload;
    function PutAsync(const EntitySet: string; Entity: TJSObject): TXDataClientResponse;
    procedure Post(const EntitySet: string; Entity: TJSObject; const RequestId: string = 'post'); overload;
    procedure Post(const EntitySet: string; Entity: TJSObject; SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc = nil); overload;
    function PostAsync(const EntitySet: string; Entity: TJSObject): TXDataClientResponse;
    procedure Delete(const EntitySet: string; Entity: TJSObject; const RequestId: string = 'delete'); overload;
    procedure Delete(const EntitySet: string; Entity: TJSObject; SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc = nil); overload;
    function DeleteAsync(const EntitySet: string; Entity: TJSObject): TXDataClientResponse;
    procedure List(const EntitySet: string; const Query: string = ''; const RequestId: string = 'list'); overload;
    procedure List(const EntitySet: string; const Query: string; SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc = nil); overload;
    function ListAsync(const EntitySet: string; const Query: string = ''): TXDataClientResponse;
    procedure RawInvoke(const OperationId: string; Args: array of JSValue; const RequestId: string = ''); overload;
    procedure RawInvoke(const OperationId: string; Args: array of JSValue; SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc = nil); overload;
    function RawInvokeAsync(const OperationId: string; Args: array of JSValue): TXDataClientResponse;
  published
    property Connection: TXDataWebConnection read FConnection write SetConnection;
    property OnLoad: TXDataClientLoadEvent read FOnLoad write FOnLoad;
    property OnError: TXDataClientErrorEvent read FOnError write FOnError;
    property OnRequest: TXDataClientRequestEvent read FOnRequest write FOnRequest;
    property ReferenceSolvingMode: TReferenceSolvingMode read FReferenceSolvingMode write FReferenceSolvingMode default rsAll;
  end;

  EXDataClientException = class(Exception)
  end;

  EXDataClientRequestException = class(EXDataClientException)
  protected
    FErrorResult: TXDataClientError;
  public
    property ErrorResult: TXDataClientError read FErrorResult;
  end;

  EXDataOperationRequestException = class(EXDataClientRequestException)
  end;

  EXDataWrongParameterCount = class(EXDataClientException)
  end;

implementation

{ TXDataWebClient }

procedure TXDataWebClient.Delete(const EntitySet: string; Entity: TJSObject;
  const RequestId: string);
begin

end;

procedure TXDataWebClient.Get(const EntitySet: string; Id: JSValue;
  const RequestId: string);
begin

end;

procedure TXDataWebClient.Get(const EntitySet, QueryString: string; Id: JSValue;
  const RequestId: string);
begin

end;

procedure TXDataWebClient.List(const EntitySet, Query, RequestId: string);
begin

end;

procedure TXDataWebClient.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if (Operation = opRemove) and (AComponent = FConnection) then
    Connection := nil;
end;

procedure TXDataWebClient.Post(const EntitySet: string; Entity: TJSObject;
  const RequestId: string);
begin

end;

procedure TXDataWebClient.Put(const EntitySet: string; Entity: TJSObject;
  const RequestId: string);
begin

end;

procedure TXDataWebClient.RawInvoke(const OperationId: string;
  Args: array of JSValue; const RequestId: string);
begin
end;

procedure TXDataWebClient.SetConnection(const Value: TXDataWebConnection);
begin
  if Value <> FConnection then
  begin
    if FConnection <> nil then
      FConnection.RemoveFreeNotification(Self);
    FConnection := Value;
    if FConnection <> nil then
      FConnection.FreeNotification(Self);
  end;
end;

procedure TXDataWebClient.Delete(const EntitySet: string; Entity: TJSObject;
  SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc);
begin

end;

function TXDataWebClient.DeleteAsync(const EntitySet: string;
  Entity: TJSObject): TXDataClientResponse;
begin
  Result := nil;
end;

procedure TXDataWebClient.Get(const EntitySet, QueryString: string; Id: JSValue;
  SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc);
begin

end;

function TXDataWebClient.GetAsync(const EntitySet: string;
  Id: JSValue): TXDataClientResponse;
begin
  Result := nil;
end;

function TXDataWebClient.GetAsync(const EntitySet, QueryString: string;
  Id: JSValue): TXDataClientResponse;
begin
  Result := nil;
end;

procedure TXDataWebClient.Get(const EntitySet: string; Id: JSValue;
  SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc);
begin

end;

procedure TXDataWebClient.List(const EntitySet, Query: string;
  SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc);
begin

end;

function TXDataWebClient.ListAsync(const EntitySet,
  Query: string): TXDataClientResponse;
begin
  Result := nil;
end;

procedure TXDataWebClient.Post(const EntitySet: string; Entity: TJSObject;
  SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc);
begin
end;

function TXDataWebClient.PostAsync(const EntitySet: string;
  Entity: TJSObject): TXDataClientResponse;
begin
  Result := nil;
end;

procedure TXDataWebClient.Put(const EntitySet: string; Entity: TJSObject;
  SuccessProc: TXDataClientLoadProc; ErrorProc: TXDataClientErrorProc);
begin

end;

function TXDataWebClient.PutAsync(const EntitySet: string;
  Entity: TJSObject): TXDataClientResponse;
begin
  Result := nil;
end;

procedure TXDataWebClient.RawInvoke(const OperationId: string;
  Args: array of JSValue; SuccessProc: TXDataClientLoadProc;
  ErrorProc: TXDataClientErrorProc);
begin

end;

function TXDataWebClient.RawInvokeAsync(const OperationId: string;
  Args: array of JSValue): TXDataClientResponse;
begin
  Result := nil;
end;

end.
