// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) AutoRest Code Generator.

package com.azure.maps.traffic;

import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceClient;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.exception.HttpResponseException;
import com.azure.core.http.rest.Response;
import com.azure.core.http.rest.StreamResponse;
import com.azure.core.util.BinaryData;
import com.azure.core.util.Context;
import com.azure.core.util.FluxUtil;
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.http.rest.SimpleResponse;
import com.azure.maps.traffic.implementation.TrafficsImpl;
import com.azure.maps.traffic.implementation.helpers.Utility;
import com.azure.maps.traffic.models.TrafficFlowSegmentData;
import com.azure.maps.traffic.implementation.models.ResponseFormat;
import com.azure.maps.traffic.implementation.models.ErrorResponseException;
import com.azure.maps.traffic.models.TrafficIncidentDetail;
import com.azure.maps.traffic.models.TrafficIncidentViewport;
import com.azure.maps.traffic.models.TrafficFlowSegmentOptions;
import com.azure.maps.traffic.models.TrafficFlowTileOptions;
import com.azure.maps.traffic.models.TrafficIncidentDetailOptions;
import com.azure.maps.traffic.models.TrafficIncidentTileOptions;
import com.azure.maps.traffic.models.TrafficIncidentViewportOptions;

import reactor.core.publisher.Mono;

/** Initializes a new instance of the asynchronous TrafficClient type.
* Creating an async client using a {@link com.azure.core.credential.AzureKeyCredential}:
* <!-- src_embed com.azure.maps.traffic.async.builder.key.instantiation -->
* <pre>
* &#47;&#47; Authenticates using subscription key
* AzureKeyCredential keyCredential = new AzureKeyCredential&#40;System.getenv&#40;&quot;SUBSCRIPTION_KEY&quot;&#41;&#41;;
*
* &#47;&#47; Creates a builder
* TrafficClientBuilder builder = new TrafficClientBuilder&#40;&#41;;
* builder.credential&#40;keyCredential&#41;;
* builder.httpLogOptions&#40;new HttpLogOptions&#40;&#41;.setLogLevel&#40;HttpLogDetailLevel.BODY_AND_HEADERS&#41;&#41;;
*
* &#47;&#47; Builds the client
* TrafficAsyncClient client = builder.buildAsyncClient&#40;&#41;;
* </pre>
* <!-- end com.azure.maps.traffic.async.builder.key.instantiation -->
* <!-- src_embed com.azure.maps.traffic.async.builder.ad.instantiation -->
* <pre>
* &#47;&#47; Authenticates using Azure AD building a default credential
* &#47;&#47; This will look for AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_CLIENT_SECRET env variables
* DefaultAzureCredential tokenCredential = new DefaultAzureCredentialBuilder&#40;&#41;.build&#40;&#41;;
*
* &#47;&#47; Creates a builder
* TrafficClientBuilder builder = new TrafficClientBuilder&#40;&#41;;
* builder.credential&#40;tokenCredential&#41;;
* builder.trafficClientId&#40;System.getenv&#40;&quot;MAPS_CLIENT_ID&quot;&#41;&#41;;
* builder.httpLogOptions&#40;new HttpLogOptions&#40;&#41;.setLogLevel&#40;HttpLogDetailLevel.BODY_AND_HEADERS&#41;&#41;;
*
* &#47;&#47; Builds a client
* TrafficAsyncClient client = builder.buildAsyncClient&#40;&#41;;
* </pre>
* <!-- end com.azure.maps.traffic.async.builder.ad.instantiation -->
*/
@ServiceClient(builder = TrafficClientBuilder.class, isAsync = true)
public final class TrafficAsyncClient {
    private final TrafficsImpl serviceClient;
    private static final ClientLogger LOGGER = new ClientLogger(TrafficAsyncClient.class);

    /**
     * Initializes an instance of Traffics client.
     *
     * @param serviceClient the service client implementation.
     */
    TrafficAsyncClient(TrafficsImpl serviceClient) {
        this.serviceClient = serviceClient;
    }

    /**
     * __Traffic Flow Tile__
     * 
     * <!-- src_embed com.azure.maps.traffic.async.get_traffic_flow_tile -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Flow Tile:&quot;&#41;;
     *
     * &#47;&#47; options
     * asyncClient.getTrafficFlowTile&#40;
     *     new TrafficFlowTileOptions&#40;&#41;
     *         .setTrafficFlowTileStyle&#40;TrafficFlowTileStyle.RELATIVE_DELAY&#41;.setFormat&#40;TileFormat.PNG&#41;.setZoom&#40;10&#41;
     *         .setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * asyncClient.getTrafficFlowTile&#40;
     *     new TrafficFlowTileOptions&#40;&#41;
     *         .setTrafficFlowTileStyle&#40;TrafficFlowTileStyle.RELATIVE_DELAY&#41;.setFormat&#40;TileFormat.PNG&#41;.setZoom&#40;10&#41;
     *         .setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;.setThickness&#40;10&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.async.get_traffic_flow_tile -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>The Azure Flow Tile API serves 256 x 256 pixel tiles showing traffic flow. All tiles use the same grid system.
     * Because the traffic tiles use transparent images, they can be layered on top of map tiles to create a compound
     * display. The Flow tiles use colors to indicate either the speed of traffic on different road segments, or the
     * difference between that speed and the free-flow speed on the road segment in question.
     *
     * @param options {@link TrafficFlowTileOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<BinaryData> getTrafficFlowTile(TrafficFlowTileOptions options) {
        Mono<StreamResponse> responseMono = this.getTrafficFlowTileWithResponse(options, null);
        return BinaryData.fromFlux(responseMono.flatMapMany(response -> {
            return response.getValue();
        }));    
    }

    /**
     * __Traffic Flow Tile__
     * 
     * <!-- src_embed com.azure.maps.traffic.async.get_traffic_flow_tile -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Flow Tile:&quot;&#41;;
     *
     * &#47;&#47; options
     * asyncClient.getTrafficFlowTile&#40;
     *     new TrafficFlowTileOptions&#40;&#41;
     *         .setTrafficFlowTileStyle&#40;TrafficFlowTileStyle.RELATIVE_DELAY&#41;.setFormat&#40;TileFormat.PNG&#41;.setZoom&#40;10&#41;
     *         .setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * asyncClient.getTrafficFlowTile&#40;
     *     new TrafficFlowTileOptions&#40;&#41;
     *         .setTrafficFlowTileStyle&#40;TrafficFlowTileStyle.RELATIVE_DELAY&#41;.setFormat&#40;TileFormat.PNG&#41;.setZoom&#40;10&#41;
     *         .setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;.setThickness&#40;10&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.async.get_traffic_flow_tile -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>The Azure Flow Tile API serves 256 x 256 pixel tiles showing traffic flow. All tiles use the same grid system.
     * Because the traffic tiles use transparent images, they can be layered on top of map tiles to create a compound
     * display. The Flow tiles use colors to indicate either the speed of traffic on different road segments, or the
     * difference between that speed and the free-flow speed on the road segment in question.
     *
     * @param options {@link TrafficFlowTileOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<BinaryData>> getTrafficFlowTileWithResponse(TrafficFlowTileOptions options) {
        if (options == null) {
            throw LOGGER.logExceptionAsError(new NullPointerException("Options is null"));
        }
        StreamResponse response = null;
        try {
            response = this.getTrafficFlowTileWithResponse(options, null).block();
        } catch (RuntimeException ex) {
            return FluxUtil.monoError(LOGGER, ex);
        } 
        if (response != null) {
            return Mono.just(new SimpleResponse<BinaryData>(response.getRequest(), response.getStatusCode(), response.getHeaders(), BinaryData.fromFlux(response.getValue()).block()));
        } else {
            return Mono.error(new NullPointerException("Response is null"));
        }   
    }

    /**
     * __Traffic Flow Tile__
     * 
     * <!-- src_embed com.azure.maps.traffic.async.get_traffic_flow_tile -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Flow Tile:&quot;&#41;;
     *
     * &#47;&#47; options
     * asyncClient.getTrafficFlowTile&#40;
     *     new TrafficFlowTileOptions&#40;&#41;
     *         .setTrafficFlowTileStyle&#40;TrafficFlowTileStyle.RELATIVE_DELAY&#41;.setFormat&#40;TileFormat.PNG&#41;.setZoom&#40;10&#41;
     *         .setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * asyncClient.getTrafficFlowTile&#40;
     *     new TrafficFlowTileOptions&#40;&#41;
     *         .setTrafficFlowTileStyle&#40;TrafficFlowTileStyle.RELATIVE_DELAY&#41;.setFormat&#40;TileFormat.PNG&#41;.setZoom&#40;10&#41;
     *         .setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;.setThickness&#40;10&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.async.get_traffic_flow_tile -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>The Azure Flow Tile API serves 256 x 256 pixel tiles showing traffic flow. All tiles use the same grid system.
     * Because the traffic tiles use transparent images, they can be layered on top of map tiles to create a compound
     * display. The Flow tiles use colors to indicate either the speed of traffic on different road segments, or the
     * difference between that speed and the free-flow speed on the road segment in question.
     *
     * @param context The context to associate with this operation.
     * @param options {@link TrafficFlowTileOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response.
     */
    Mono<StreamResponse> getTrafficFlowTileWithResponse(TrafficFlowTileOptions options, Context context) {    
        if (options == null) {
            throw LOGGER.logExceptionAsError(new NullPointerException("Options is null"));
        }    
        return this.serviceClient.getTrafficFlowTileWithResponseAsync(
                options.getFormat(), 
                options.getTrafficFlowTileStyle(), 
                options.getZoom(), 
                options.getTileIndex(), 
                options.getThickness(),
                context).onErrorMap(throwable -> {
                    if (!(throwable instanceof ErrorResponseException)) {
                        return throwable;
                    }
                    ErrorResponseException exception = (ErrorResponseException) throwable;
                    return new HttpResponseException(exception.getMessage(), exception.getResponse());
                });
    }

    /**
     * __Traffic Flow Segment__
     * 
     * <!-- src_embed com.azure.maps.traffic.async.get_traffic_flow_segment -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Flow Segment:&quot;&#41;;
     *
     * &#47;&#47; options
     * asyncClient.getTrafficFlowSegment&#40;
     *     new TrafficFlowSegmentOptions&#40;&#41;
     *         .setTrafficFlowSegmentStyle&#40;TrafficFlowSegmentStyle.ABSOLUTE&#41;.setZoom&#40;10&#41;
     *         .setCoordinates&#40;new GeoPosition&#40;4.84239, 52.41072&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * asyncClient.getTrafficFlowSegment&#40;
     *     new TrafficFlowSegmentOptions&#40;&#41;
     *         .setTrafficFlowSegmentStyle&#40;TrafficFlowSegmentStyle.ABSOLUTE&#41;.setZoom&#40;10&#41;
     *         .setCoordinates&#40;new GeoPosition&#40;4.84239, 52.41072&#41;&#41;.setOpenLr&#40;false&#41;
     *         .setThickness&#40;2&#41;.setUnit&#40;SpeedUnit.MPH&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.async.get_traffic_flow_segment -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This service provides information about the speeds and travel times of the road fragment closest to the given
     * coordinates. It is designed to work alongside the Flow layer of the Render Service to support clickable flow data
     * visualizations. With this API, the client side can connect any place in the map with flow data on the closest
     * road and present it to the user.
     *
     * @param options {@link TrafficFlowSegmentOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws HttpResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic Flow Segment call.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<TrafficFlowSegmentData> getTrafficFlowSegment(TrafficFlowSegmentOptions options) {
        Mono<Response<TrafficFlowSegmentData>> result = this.getTrafficFlowSegmentWithResponse(options, null);
        return result.flatMap(response -> {
            return Mono.just(response.getValue());
        });
    }

    /**
     * __Traffic Flow Segment__
     * 
     * <!-- src_embed com.azure.maps.traffic.async.get_traffic_flow_segment -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Flow Segment:&quot;&#41;;
     *
     * &#47;&#47; options
     * asyncClient.getTrafficFlowSegment&#40;
     *     new TrafficFlowSegmentOptions&#40;&#41;
     *         .setTrafficFlowSegmentStyle&#40;TrafficFlowSegmentStyle.ABSOLUTE&#41;.setZoom&#40;10&#41;
     *         .setCoordinates&#40;new GeoPosition&#40;4.84239, 52.41072&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * asyncClient.getTrafficFlowSegment&#40;
     *     new TrafficFlowSegmentOptions&#40;&#41;
     *         .setTrafficFlowSegmentStyle&#40;TrafficFlowSegmentStyle.ABSOLUTE&#41;.setZoom&#40;10&#41;
     *         .setCoordinates&#40;new GeoPosition&#40;4.84239, 52.41072&#41;&#41;.setOpenLr&#40;false&#41;
     *         .setThickness&#40;2&#41;.setUnit&#40;SpeedUnit.MPH&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.async.get_traffic_flow_segment -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This service provides information about the speeds and travel times of the road fragment closest to the given
     * coordinates. It is designed to work alongside the Flow layer of the Render Service to support clickable flow data
     * visualizations. With this API, the client side can connect any place in the map with flow data on the closest
     * road and present it to the user.
     *
     * @param options {@link TrafficFlowSegmentOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic Flow Segment call.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<TrafficFlowSegmentData>> getTrafficFlowSegmentWithResponse(TrafficFlowSegmentOptions options) {
        return this.getTrafficFlowSegmentWithResponse(options, null);
    }

    /**
     * __Traffic Flow Segment__
     * 
     * <!-- src_embed com.azure.maps.traffic.async.get_traffic_flow_segment -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Flow Segment:&quot;&#41;;
     *
     * &#47;&#47; options
     * asyncClient.getTrafficFlowSegment&#40;
     *     new TrafficFlowSegmentOptions&#40;&#41;
     *         .setTrafficFlowSegmentStyle&#40;TrafficFlowSegmentStyle.ABSOLUTE&#41;.setZoom&#40;10&#41;
     *         .setCoordinates&#40;new GeoPosition&#40;4.84239, 52.41072&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * asyncClient.getTrafficFlowSegment&#40;
     *     new TrafficFlowSegmentOptions&#40;&#41;
     *         .setTrafficFlowSegmentStyle&#40;TrafficFlowSegmentStyle.ABSOLUTE&#41;.setZoom&#40;10&#41;
     *         .setCoordinates&#40;new GeoPosition&#40;4.84239, 52.41072&#41;&#41;.setOpenLr&#40;false&#41;
     *         .setThickness&#40;2&#41;.setUnit&#40;SpeedUnit.MPH&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.async.get_traffic_flow_segment -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This service provides information about the speeds and travel times of the road fragment closest to the given
     * coordinates. It is designed to work alongside the Flow layer of the Render Service to support clickable flow data
     * visualizations. With this API, the client side can connect any place in the map with flow data on the closest
     * road and present it to the user.
     *
     * @param options {@link TrafficFlowSegmentOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic Flow Segment call.
     */
    Mono<Response<TrafficFlowSegmentData>> getTrafficFlowSegmentWithResponse(TrafficFlowSegmentOptions options, Context context) {
        return this.serviceClient.getTrafficFlowSegmentWithResponseAsync(
            ResponseFormat.JSON, 
            options.getTrafficFlowSegmentStyle(), 
            options.getZoom(), 
            Utility.toCoordinates(options.getCoordinates()), 
            options.getUnit(), 
            options.getThickness(),
            options.getOpenLr(),
            context).onErrorMap(throwable -> {
                if (!(throwable instanceof ErrorResponseException)) {
                    return throwable;
                }
                ErrorResponseException exception = (ErrorResponseException) throwable;
                return new HttpResponseException(exception.getMessage(), exception.getResponse());
            });
    }

    /**
     * __Traffic Incident Tile__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_tile -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Tile:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentTile&#40;
     *     new TrafficIncidentTileOptions&#40;&#41;
     *         .setFormat&#40;TileFormat.PNG&#41;.setTrafficIncidentTileStyle&#40;TrafficIncidentTileStyle.S3&#41;
     *         .setZoom&#40;10&#41;.setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentTile&#40;
     *     new TrafficIncidentTileOptions&#40;&#41;
     *         .setFormat&#40;TileFormat.PNG&#41;.setTrafficIncidentTileStyle&#40;TrafficIncidentTileStyle.S3&#41;
     *         .setZoom&#40;10&#41;.setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;175&#41;.setY&#40;408&#41;&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_tile -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This service serves 256 x 256 pixel tiles showing traffic incidents. All tiles use the same grid system.
     * Because the traffic tiles use transparent images, they can be layered on top of map tiles to create a compound
     * display. Traffic tiles render graphics to indicate traffic on the roads in the specified area.
     *
     * @param options {@link TrafficIncidentTileOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<BinaryData> getTrafficIncidentTile(TrafficIncidentTileOptions options) {
        Mono<StreamResponse> responseMono = this.getTrafficIncidentTileWithResponse(options, null);
        if (options == null) {
            throw LOGGER.logExceptionAsError(new NullPointerException("Options is null"));
        }
        return BinaryData.fromFlux(responseMono.flatMapMany(response -> {
            return response.getValue();
        })); 
    }

    /**
     * __Traffic Incident Tile__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_tile -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Tile:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentTile&#40;
     *     new TrafficIncidentTileOptions&#40;&#41;
     *         .setFormat&#40;TileFormat.PNG&#41;.setTrafficIncidentTileStyle&#40;TrafficIncidentTileStyle.S3&#41;
     *         .setZoom&#40;10&#41;.setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentTile&#40;
     *     new TrafficIncidentTileOptions&#40;&#41;
     *         .setFormat&#40;TileFormat.PNG&#41;.setTrafficIncidentTileStyle&#40;TrafficIncidentTileStyle.S3&#41;
     *         .setZoom&#40;10&#41;.setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;175&#41;.setY&#40;408&#41;&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_tile -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This service serves 256 x 256 pixel tiles showing traffic incidents. All tiles use the same grid system.
     * Because the traffic tiles use transparent images, they can be layered on top of map tiles to create a compound
     * display. Traffic tiles render graphics to indicate traffic on the roads in the specified area.
     *
     * @param options {@link TrafficIncidentTileOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<BinaryData>> getTrafficIncidentTileWithResponse(TrafficIncidentTileOptions options) {
        if (options == null) {
            throw LOGGER.logExceptionAsError(new NullPointerException("Options is null"));
        }
        StreamResponse response = this.getTrafficIncidentTileWithResponse(options, null).block();
        if (response != null) {
            return Mono.just(new SimpleResponse<BinaryData>(response.getRequest(), response.getStatusCode(), response.getHeaders(), null));
        } else {
            return Mono.error(new NullPointerException("Response is null"));
        }   
    }

    /**
     * __Traffic Incident Tile__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_tile -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Tile:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentTile&#40;
     *     new TrafficIncidentTileOptions&#40;&#41;
     *         .setFormat&#40;TileFormat.PNG&#41;.setTrafficIncidentTileStyle&#40;TrafficIncidentTileStyle.S3&#41;
     *         .setZoom&#40;10&#41;.setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;1022&#41;.setY&#40;680&#41;&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentTile&#40;
     *     new TrafficIncidentTileOptions&#40;&#41;
     *         .setFormat&#40;TileFormat.PNG&#41;.setTrafficIncidentTileStyle&#40;TrafficIncidentTileStyle.S3&#41;
     *         .setZoom&#40;10&#41;.setTileIndex&#40;new TileIndex&#40;&#41;.setX&#40;175&#41;.setY&#40;408&#41;&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_tile -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This service serves 256 x 256 pixel tiles showing traffic incidents. All tiles use the same grid system.
     * Because the traffic tiles use transparent images, they can be layered on top of map tiles to create a compound
     * display. Traffic tiles render graphics to indicate traffic on the roads in the specified area.
     *
     * @param context The context to associate with this operation.
     * @param options {@link TrafficIncidentTileOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return the response.
     */
    Mono<StreamResponse> getTrafficIncidentTileWithResponse(TrafficIncidentTileOptions options, Context context) { 
        if (options == null) {
            throw LOGGER.logExceptionAsError(new NullPointerException("Options is null"));
        }       
        return this.serviceClient.getTrafficIncidentTileWithResponseAsync(
            options.getFormat(), 
            options.getTrafficIncidentTileStyle(), 
            options.getZoom(), 
            options.getTileIndex(),
            options.getTrafficState(),
            context).onErrorMap(throwable -> {
                if (!(throwable instanceof ErrorResponseException)) {
                    return throwable;
                }
                ErrorResponseException exception = (ErrorResponseException) throwable;
                return new HttpResponseException(exception.getMessage(), exception.getResponse());
            });
    }

    /**
     * __Traffic Incident Detail__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_detail -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Detail:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentDetail&#40;
     *     new TrafficIncidentDetailOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;.setBoundingZoom&#40;11&#41;
     *         .setIncidentDetailStyle&#40;IncidentDetailStyle.S3&#41;.setBoundingZoom&#40;11&#41;
     *         .setTrafficmodelId&#40;&quot;1335294634919&quot;&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentDetail&#40;
     *     new TrafficIncidentDetailOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;.setBoundingZoom&#40;11&#41;
     *         .setIncidentDetailStyle&#40;IncidentDetailStyle.S3&#41;.setBoundingZoom&#40;11&#41;
     *         .setTrafficmodelId&#40;&quot;1335294634919&quot;&#41;.setLanguage&#40;&quot;en&quot;&#41;
     *         .setProjectionStandard&#40;ProjectionStandard.EPSG900913&#41;.setIncidentGeometryType&#40;IncidentGeometryType.ORIGINAL&#41;
     *         .setExpandCluster&#40;false&#41;.setOriginalPosition&#40;false&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_detail -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This API provides information on traffic incidents inside a given bounding box, based on the current Traffic
     * Model ID. The Traffic Model ID is available to grant synchronization of data between calls and API's. The Traffic
     * Model ID is a key value for determining the currency of traffic incidents. It is updated every minute, and is
     * valid for two minutes before it times out. It is used in rendering [incident
     * tiles](https://docs.microsoft.com/rest/api/maps/traffic/gettrafficincidenttile). It can be obtained from
     * the [Viewport API](https://docs.microsoft.com/rest/api/maps/traffic/gettrafficincidentviewport).
     *
     * @param options {@link TrafficIncidentDetailOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic incident Detail call.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<TrafficIncidentDetail> getTrafficIncidentDetail(TrafficIncidentDetailOptions options) {
        Mono<Response<TrafficIncidentDetail>> result = this.getTrafficIncidentDetailWithResponse(options, null);
        return result.flatMap(response -> {
            return Mono.just(response.getValue());
        });
    }

    /**
     * __Traffic Incident Detail__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_detail -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Detail:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentDetail&#40;
     *     new TrafficIncidentDetailOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;.setBoundingZoom&#40;11&#41;
     *         .setIncidentDetailStyle&#40;IncidentDetailStyle.S3&#41;.setBoundingZoom&#40;11&#41;
     *         .setTrafficmodelId&#40;&quot;1335294634919&quot;&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentDetail&#40;
     *     new TrafficIncidentDetailOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;.setBoundingZoom&#40;11&#41;
     *         .setIncidentDetailStyle&#40;IncidentDetailStyle.S3&#41;.setBoundingZoom&#40;11&#41;
     *         .setTrafficmodelId&#40;&quot;1335294634919&quot;&#41;.setLanguage&#40;&quot;en&quot;&#41;
     *         .setProjectionStandard&#40;ProjectionStandard.EPSG900913&#41;.setIncidentGeometryType&#40;IncidentGeometryType.ORIGINAL&#41;
     *         .setExpandCluster&#40;false&#41;.setOriginalPosition&#40;false&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_detail -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This API provides information on traffic incidents inside a given bounding box, based on the current Traffic
     * Model ID. The Traffic Model ID is available to grant synchronization of data between calls and API's. The Traffic
     * Model ID is a key value for determining the currency of traffic incidents. It is updated every minute, and is
     * valid for two minutes before it times out. It is used in rendering [incident
     * tiles](https://docs.microsoft.com/rest/api/maps/traffic/gettrafficincidenttile). It can be obtained from
     * the [Viewport API](https://docs.microsoft.com/rest/api/maps/traffic/gettrafficincidentviewport).
     *
     * @param options {@link TrafficIncidentDetailOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic incident Detail call.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<TrafficIncidentDetail>> getTrafficIncidentDetailWithResponse(TrafficIncidentDetailOptions options) {
        return this.getTrafficIncidentDetailWithResponse(options, null);
    }
    
    /**
     * __Traffic Incident Detail__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_detail -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Detail:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentDetail&#40;
     *     new TrafficIncidentDetailOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;.setBoundingZoom&#40;11&#41;
     *         .setIncidentDetailStyle&#40;IncidentDetailStyle.S3&#41;.setBoundingZoom&#40;11&#41;
     *         .setTrafficmodelId&#40;&quot;1335294634919&quot;&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentDetail&#40;
     *     new TrafficIncidentDetailOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;.setBoundingZoom&#40;11&#41;
     *         .setIncidentDetailStyle&#40;IncidentDetailStyle.S3&#41;.setBoundingZoom&#40;11&#41;
     *         .setTrafficmodelId&#40;&quot;1335294634919&quot;&#41;.setLanguage&#40;&quot;en&quot;&#41;
     *         .setProjectionStandard&#40;ProjectionStandard.EPSG900913&#41;.setIncidentGeometryType&#40;IncidentGeometryType.ORIGINAL&#41;
     *         .setExpandCluster&#40;false&#41;.setOriginalPosition&#40;false&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_detail -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This API provides information on traffic incidents inside a given bounding box, based on the current Traffic
     * Model ID. The Traffic Model ID is available to grant synchronization of data between calls and API's. The Traffic
     * Model ID is a key value for determining the currency of traffic incidents. It is updated every minute, and is
     * valid for two minutes before it times out. It is used in rendering [incident
     * tiles](https://docs.microsoft.com/rest/api/maps/traffic/gettrafficincidenttile). It can be obtained from
     * the [Viewport API](https://docs.microsoft.com/rest/api/maps/traffic/gettrafficincidentviewport).
     *
     * @param context The context to associate with this operation.
     * @param options {@link TrafficIncidentDetailOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic incident Detail call.
     */
    Mono<Response<TrafficIncidentDetail>> getTrafficIncidentDetailWithResponse(TrafficIncidentDetailOptions options, Context context) {
        return this.serviceClient.getTrafficIncidentDetailWithResponseAsync(
            ResponseFormat.JSON,
            options.getIncidentDetailStyle(),
            Utility.toBoundingBox(options.getBoundingBox()),
            options.getBoundingZoom(),
            options.getTrafficIncidentDetailTrafficModelId(),
            options.getLanguage(),
            options.getProjectionStandard(),
            options.getIncidentGeometryType(),
            options.getExpandCluster(),
            options.getOriginalPosition(),
            context).onErrorMap(throwable -> {
                if (!(throwable instanceof ErrorResponseException)) {
                    return throwable;
                }
                ErrorResponseException exception = (ErrorResponseException) throwable;
                return new HttpResponseException(exception.getMessage(), exception.getResponse());
            });
    }

    /**
     * __Traffic Incident Viewport__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_viewport -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Viewport:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentViewport&#40;
     *     new TrafficIncidentViewportOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setBoundingZoom&#40;2&#41;.setOverview&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setOverviewZoom&#40;2&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentViewport&#40;
     *     new TrafficIncidentViewportOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setBoundingZoom&#40;2&#41;.setOverview&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setOverviewZoom&#40;2&#41;.setCopyright&#40;true&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_viewport -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This API returns legal and technical information for the viewport described in the request. It should be
     * called by client applications whenever the viewport changes (for instance, through zooming, panning, going to a
     * location, or displaying a route). The request should contain the bounding box and zoom level of the viewport
     * whose information is needed. The return will contain map version information, as well as the current Traffic
     * Model ID and copyright IDs. The Traffic Model ID returned by the Viewport Description is used by other APIs to
     * retrieve last traffic information for further processing.
     *
     * @param options {@link TrafficIncidentViewportOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic Incident Viewport call.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<TrafficIncidentViewport> getTrafficIncidentViewport(TrafficIncidentViewportOptions options) {
        Mono<Response<TrafficIncidentViewport>> result = this.getTrafficIncidentViewportWithResponse(options, null);
        return result.flatMap(response -> {
            return Mono.just(response.getValue());
        });
    }

    /**
     * __Traffic Incident Viewport__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_viewport -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Viewport:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentViewport&#40;
     *     new TrafficIncidentViewportOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setBoundingZoom&#40;2&#41;.setOverview&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setOverviewZoom&#40;2&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentViewport&#40;
     *     new TrafficIncidentViewportOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setBoundingZoom&#40;2&#41;.setOverview&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setOverviewZoom&#40;2&#41;.setCopyright&#40;true&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_viewport -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This API returns legal and technical information for the viewport described in the request. It should be
     * called by client applications whenever the viewport changes (for instance, through zooming, panning, going to a
     * location, or displaying a route). The request should contain the bounding box and zoom level of the viewport
     * whose information is needed. The return will contain map version information, as well as the current Traffic
     * Model ID and copyright IDs. The Traffic Model ID returned by the Viewport Description is used by other APIs to
     * retrieve last traffic information for further processing.
     *
     * @param options {@link TrafficIncidentViewportOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic Incident Viewport call.
     */
    @ServiceMethod(returns = ReturnType.SINGLE)
    public Mono<Response<TrafficIncidentViewport>> getTrafficIncidentViewportWithResponse(TrafficIncidentViewportOptions options) {
        return this.getTrafficIncidentViewportWithResponse(options, null);
    }
    
    /**
     * __Traffic Incident Viewport__
     * 
     * <!-- src_embed com.azure.maps.traffic.sync.get_traffic_incident_viewport -->
     * <pre>
     * System.out.println&#40;&quot;Get Traffic Incident Viewport:&quot;&#41;;
     *
     * &#47;&#47; options
     * client.getTrafficIncidentViewport&#40;
     *     new TrafficIncidentViewportOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setBoundingZoom&#40;2&#41;.setOverview&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setOverviewZoom&#40;2&#41;&#41;;
     *
     * &#47;&#47; complete
     * client.getTrafficIncidentViewport&#40;
     *     new TrafficIncidentViewportOptions&#40;&#41;
     *         .setBoundingBox&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setBoundingZoom&#40;2&#41;.setOverview&#40;new GeoBoundingBox&#40;45, 45, 45, 45&#41;&#41;
     *         .setOverviewZoom&#40;2&#41;.setCopyright&#40;true&#41;&#41;;
     * </pre>
     * <!-- end com.azure.maps.traffic.sync.get_traffic_incident_viewport -->
     *
     * <p>**Applies to**: S0 and S1 pricing tiers.
     *
     * <p>This API returns legal and technical information for the viewport described in the request. It should be
     * called by client applications whenever the viewport changes (for instance, through zooming, panning, going to a
     * location, or displaying a route). The request should contain the bounding box and zoom level of the viewport
     * whose information is needed. The return will contain map version information, as well as the current Traffic
     * Model ID and copyright IDs. The Traffic Model ID returned by the Viewport Description is used by other APIs to
     * retrieve last traffic information for further processing.
     *
     * @param context The context to associate with this operation.
     * @param options {@link TrafficIncidentViewportOptions} the options to be used in this search.
     * @throws IllegalArgumentException thrown if parameters fail the validation.
     * @throws ErrorResponseException thrown if the request is rejected by server.
     * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent.
     * @return this object is returned from a successful Traffic Incident Viewport call.
     */
    Mono<Response<TrafficIncidentViewport>> getTrafficIncidentViewportWithResponse(TrafficIncidentViewportOptions options, Context context) {
        return this.serviceClient.getTrafficIncidentViewportWithResponseAsync(
            ResponseFormat.JSON, 
            Utility.toBoundingBox(options.getBoundingBox()),
            options.getBoundingZoom(), 
            Utility.toBoundingBox(options.getOverviewBox()), 
            options.getOverviewZoom(), 
            options.getCopyright(),
            context).onErrorMap(throwable -> {
                if (!(throwable instanceof ErrorResponseException)) {
                    return throwable;
                }
                ErrorResponseException exception = (ErrorResponseException) throwable;
                return new HttpResponseException(exception.getMessage(), exception.getResponse());
            });
    }
}
