/*
 * Copyright 2018, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.partner.mapsbooking.rest;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.partner.mapsbooking.v3.model.ApiV3;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/** Booking REST Server for API v3 with authentication. */
@Path("/v3")
public class BookingService {

  private JsonFormat.Printer jsonPrinter() {
    return JsonFormat.printer().preservingProtoFieldNames();
  }

  @GET
  @Produces(MediaType.TEXT_PLAIN)
  public String checkServer() {
    // method for testing
    return "Got it!";
  }

  @Path("/CheckAvailability")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String checkAvailability(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String to protocol buffer
    ApiV3.CheckAvailabilityRequest.Builder requestBuilder =
        ApiV3.CheckAvailabilityRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.CheckAvailabilityRequest checkAvailabilityRequest = requestBuilder.build();

    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.CheckAvailabilityResponse response = performCheckAvailability(checkAvailabilityRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to perform availability check
  private ApiV3.CheckAvailabilityResponse performCheckAvailability(
      ApiV3.CheckAvailabilityRequest request) {

    //        Check availability business logic:
    //        e.g.
    //        ApiV3.Slot requestedSlot = request.getSlot();
    //        int available_spots = ...;
    //        ApiV3.CheckAvailabilityResponse response =
    //                ApiV3.CheckAvailabilityResponse.newBuilder()
    //                        .setSlot(requestedSlot)
    //                        .setCountAvailable(available_spots)
    //                        .build();
    //        return response;

    throw new UnsupportedOperationException("Not implemented yet");
  }

  @Path("/CreateBooking")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String createBooking(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String into protocol buffer
    ApiV3.CreateBookingRequest.Builder requestBuilder = ApiV3.CreateBookingRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.CreateBookingRequest createBookingRequest = requestBuilder.build();

    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.CreateBookingResponse response = performCreateBooking(createBookingRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to create a booking based on the request
  private ApiV3.CreateBookingResponse performCreateBooking(ApiV3.CreateBookingRequest request) {

    //        Create booking business logic:
    //        e.g.
    //        ApiV3.Booking createdBooking = ApiV3.Booking.newBuilder()
    //                .setBookingId("sampleBooking1")
    //                .setSlot(request.getSlot())
    //                .setUserInformation(request.getUserInformation())
    //                .setStatus(ApiV3.BookingStatus.CONFIRMED)
    //                .build();
    //
    //        ApiV3.CreateBookingResponse response = ApiV3.CreateBookingResponse.newBuilder()
    //                .setBooking(createdBooking)
    //                .build();
    //
    //        Business logic error -> set the BookingFailure in the response
    //        e.g.
    //        BookingServerModel.BookingFailure bookingFailure =
    // BookingServerModel.BookingFailure.newBuilder()
    //                .setCause(BookingServerModel.BookingFailure.Cause.SLOT_UNAVAILABLE)
    //                .setDescription("slot is not available now")
    //                .build();
    //        BookingServerModel.CreateBookingResponse response =
    // BookingServerModel.CreateBookingResponse.newBuilder()
    //                .setBookingFailure(bookingFailure).build();
    //
    //        return response;

    throw new UnsupportedOperationException("Not implemented yet");
  }

  @Path("/UpdateBooking")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String updateBooking(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String into protocol buffer
    ApiV3.UpdateBookingRequest.Builder requestBuilder = ApiV3.UpdateBookingRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.UpdateBookingRequest updateBookingRequest = requestBuilder.build();

    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.UpdateBookingResponse response = performUpdateBooking(updateBookingRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to update the booking based on the request
  private ApiV3.UpdateBookingResponse performUpdateBooking(ApiV3.UpdateBookingRequest request) {

    //        Update booking business logic:
    //        e.g.
    //        ApiV3.Booking booking = request.getBooking();
    //        ApiV3.Booking updatedBooking = ...
    //        ApiV3.UpdateBookingResponse response = ApiV3.UpdateBookingResponse.newBuilder()
    //                .setBooking(updatedBooking)
    //                .build();
    //
    //        Business logic error -> set the BookingFailure in the response
    //        e.g.
    //        BookingServerModel.BookingFailure bookingFailure =
    // BookingServerModel.BookingFailure.newBuilder()
    //                .setCause(BookingServerModel.BookingFailure.Cause.BOOKING_NOT_CANCELLABLE)
    //                .setDescription("this booking is not cancellable")
    //                .build();
    //        BookingServerModel.CreateBookingResponse response =
    // BookingServerModel.CreateBookingResponse.newBuilder()
    //                .setBookingFailure(bookingFailure).build();
    //
    //        return response;

    throw new UnsupportedOperationException("Not implemented yet");
  }

  @Path("/GetBookingStatus")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String getBookingStatus(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String into protocol buffer
    ApiV3.GetBookingStatusRequest.Builder requestBuilder =
        ApiV3.GetBookingStatusRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.GetBookingStatusRequest getBookingStatusRequest = requestBuilder.build();

    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.GetBookingStatusResponse response = performGetBookingStatus(getBookingStatusRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to get the booking status and prepayment status based on
  // the request
  private ApiV3.GetBookingStatusResponse performGetBookingStatus(
      ApiV3.GetBookingStatusRequest request) {

    //        Get booking status business logic:
    //        e.g.
    //        String bookingId = request.getBookingId();
    //        ...
    //        ApiV3.GetBookingStatusResponse response = ApiV3.GetBookingStatusResponse.newBuilder()
    //                .setBookingId(bookingId)
    //                .setBookingStatus(ApiV3.BookingStatus.CONFIRMED)
    //                .setPrepaymentStatus(ApiV3.PrepaymentStatus.PREPAYMENT_NOT_PROVIDED)
    //                .build();
    //
    //        If booking id is not found -> throw new NotFoundException("Booking id not found");
    //
    //        return response;

    throw new UnsupportedOperationException("Not implemented yet");
  }

  @Path("/ListBookings")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String getListBooking(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String into protocol buffer
    ApiV3.ListBookingsRequest.Builder requestBuilder = ApiV3.ListBookingsRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.ListBookingsRequest listBookingsRequest = requestBuilder.build();

    // Unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.ListBookingsResponse response = performGetListBooking(listBookingsRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to look up all bookings with the given userId
  private ApiV3.ListBookingsResponse performGetListBooking(ApiV3.ListBookingsRequest request) {

    //        List bookings business logic:
    //        e.g.
    //        String userId = request.getUserId();
    //        List<ApiV3.Booking> bookings = ...
    //
    //        ApiV3.ListBookingsResponse response = ApiV3.ListBookingsResponse.newBuilder()
    //                .addAllBookings(bookings)
    //                .build();
    //
    //        If user id not found -> throw new NotFoundException("User id not found");
    //
    //        return response;

    throw new UnsupportedOperationException("Not implemented yet");
  }

  @Path("/CheckOrderFulfillability")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String checkOrderFulfillability(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String into protocol buffer
    ApiV3.CheckOrderFulfillabilityRequest.Builder requestBuilder =
        ApiV3.CheckOrderFulfillabilityRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.CheckOrderFulfillabilityRequest checkOrderFulfillabilityRequest = requestBuilder.build();

    // For unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.CheckOrderFulfillabilityResponse response =
        performCheckOrderFulfillability(checkOrderFulfillabilityRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to perform order fulfillability check
  private ApiV3.CheckOrderFulfillabilityResponse performCheckOrderFulfillability(
      ApiV3.CheckOrderFulfillabilityRequest request) {

    //        Check order fulfillability business logic:
    //        e.g.
    //        String merchantId = request.getMerchantId();
    //        List<ApiV3.LineItem> lineItems = request.getItemList();
    //
    //        List<ApiV3.LineItemFulfillability> itemFulfillabilities =
    //                getLineItemFulfillability(merchantId,lineItems);
    //        ApiV3.OrderFulfillability.OrderFulfillabilityResult result =
    //                getOrderFulfillabilityResult(itemFulfillabilities);
    //
    //        ApiV3.OrderFulfillability.Builder orderFulfillability =
    // ApiV3.OrderFulfillability.newBuilder()
    //                .setResult(result);
    //        for (int i = 0; i < itemFulfillabilities.size(); i++) {
    //            orderFulfillability.setItemFulfillability(i, itemFulfillabilities.get(i));
    //        }
    //        ApiV3.Price total = ...   // total processing fees & taxes for this order
    //        ApiV3.CheckOrderFulfillabilityResponse response =
    // ApiV3.CheckOrderFulfillabilityResponse.newBuilder()
    //                .setFulfillability(orderFulfillability.build())
    //                .setFeesAndTaxes(total)
    //                .build();
    //
    //        return response;

    throw new UnsupportedOperationException("Not implemented yet");
  }

  @Path("/CreateOrder")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String createOrder(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String into protocol buffer
    ApiV3.CreateOrderRequest.Builder requestBuilder = ApiV3.CreateOrderRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.CreateOrderRequest createOrderRequest = requestBuilder.build();

    // For unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.CreateOrderResponse response = performCreateOrder(createOrderRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to create the order based on the request
  private ApiV3.CreateOrderResponse performCreateOrder(ApiV3.CreateOrderRequest request) {

    //        Create order business logic:
    //        e.g.
    //        ApiV3.Order order = request.getOrder();

    //        normal case -> create this order in the backend, return response:
    //        ApiV3.CreateOrderResponse response = ApiV3.CreateOrderResponse.newBuilder()
    //                .setOrder(order)
    //                .build();
    //
    //        Business logic error -> set the BookingFailure in the response
    //        e.g.
    //        ApiV3.OrderFailure orderFailure = ApiV3.OrderFailure.newBuilder()
    //                .setCause(ApiV3.OrderFailure.Cause.ORDER_UNFULFILLABLE)
    //                .setFulfillability(orderFulfillability...)
    //                .build();
    //        ApiV3.CreateOrderResponse response = ApiV3.CreateOrderResponse.newBuilder()
    //                .setOrderFailure(orderFailure)
    //                .build();
    //
    //        return response;

    throw new UnsupportedOperationException("Not implemented yet");
  }

  @Path("/ListOrders")
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public String listOrders(String request) throws InvalidProtocolBufferException {

    // use JsonFormat.Parser to convert Json String into protocol buffer
    ApiV3.ListOrdersRequest.Builder requestBuilder = ApiV3.ListOrdersRequest.newBuilder();
    JsonFormat.Parser jsonParser = JsonFormat.parser();
    jsonParser.merge(request, requestBuilder);
    ApiV3.ListOrdersRequest listOrdersRequest = requestBuilder.build();

    // For unexpected error: throw exception and handle it in BookingExceptionMapper class,
    // return corresponding response and HTTP code
    //
    // Normal path: get response object from the helper function
    ApiV3.ListOrdersResponse response = getListOrders(listOrdersRequest);

    // use JsonFormat to convert protocol buffer to Json
    String jsonResponse = jsonPrinter().print(response);
    return jsonResponse;
  }

  // TODO(partner): Implement this method to list orders based on user id or order ids
  private ApiV3.ListOrdersResponse getListOrders(ApiV3.ListOrdersRequest request) {

    //        List orders business logic:
    //        e.g.
    //        String userId = request.getUserId();
    //        ApiV3.ListOrdersRequest.OrderIds orderIds = request.getOrderIds();
    //        List<ApiV3.Order> orders = new ArrayList<ApiV3.Order>();
    //        if (userId != null) {
    //            orders = findOrdersByUserId(userId);
    //        } else if (orderIds != null) {
    //            List<String> orderId = orderIds.getOrderIdList();
    //            orders = getOrders(orderId);
    //        } else {
    //            throw new NotFoundException("No userId or orderId matched");
    //        }
    //        ApiV3.ListOrdersResponse.Builder response = ApiV3.ListOrdersResponse.newBuilder();
    //        for (int i = 0; i < orders.size(); i++) {
    //            response.setOrder(i, orders.get(i));
    //        }
    //
    //        return response.build();

    throw new UnsupportedOperationException("Not implemented yet");
  }
}
