text: //
  // Copyright 2018 Google Inc.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //      http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  //
  
  #import <Foundation/Foundation.h>
  
  #import "Service/Sources/EDOMessage.h"
  
  NS_ASSUME_NONNULL_BEGIN
  
  @class EDOHostService;
  @class EDOServicePort;
  @class EDOServiceRequest;
  @class EDOServiceResponse;
  
  /**
   *  The request handler.
   *
   *  @param request The incoming request.
   *  @param context The context of the response handler. It is usually the host service instance.
   *
   *  @return The response.
   */
  typedef EDOServiceResponse *_Nonnull (^EDORequestHandler)(EDOServiceRequest *request,
                                                            id _Nullable context);
  
  /** The base request class for the request to send. */
  @interface EDOServiceRequest : EDOMessage
  
  /**
   *  The request handler.
   *
   *  The sub classes should override this and provide its own handler. The default implementation
   *  returns an EDOErrorRequestNotHandled response.
   */
  @property(readonly, class) EDORequestHandler requestHandler;
  
  - (instancetype)initWithMessageID:(NSString *)messageID NS_UNAVAILABLE;
  
  /**
   *  Checks if the request matches the @c port.
   *
   *  @note The default implementation will always return YES. Subclasses should override this
   *        if it contains the service-sensitive information such as the object address.
   *
   *  @param port The service identity from which this request will send to.
   *
   *  @return YES if both the service port and UUID matches, that is, for the same service.
   */
  - (BOOL)matchesService:(EDOServicePort *)port;
  
  @end
  
  /** The base response class for the response to receive. */
  @interface EDOServiceResponse : EDOMessage
  
  /** Time spent in seconds to generate the response. */
  @property(nonatomic) double duration;
  
  - (instancetype)init NS_UNAVAILABLE;
  
  @end
  
  /** The error response for a request if not handled and errored. */
  @interface EDOErrorResponse : EDOServiceResponse
  
  /** The error object if there is any. */
  @property(readonly, nonatomic) NSError *error;
  
  /** Creates an error response with the given error object from a request. */
  + (instancetype)errorResponse:(NSError *)error forRequest:(EDOServiceRequest *)request;
  
  /** Creates an error response with an unhandled error. */
  + (instancetype)unhandledErrorResponseForRequest:(EDOServiceRequest *)request;
  
  - (instancetype)init NS_UNAVAILABLE;
  - (instancetype)initWithMessageID:(NSString *)messageID NS_UNAVAILABLE;
  
  /** Initializes the response with an @c NSError. */
  - (instancetype)initWithMessageID:(NSString *)messageID
                              error:(NSError *)error NS_DESIGNATED_INITIALIZER;
  
  /** @see -[NSCoding initWithCoder:]. */
  - (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
  
  @end
  
  NS_ASSUME_NONNULL_END
  