/*
 * 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 ext.maps.booking.partner.v2;

import ext.maps.booking.partner.v2.ApitemplateV2BookingService.AvailabilityUpdate;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.Booking;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.BookingStatus;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.CheckAvailabilityRequest;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.CheckAvailabilityResponse;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.CheckAvailabilityResponse.DurationRequirement;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.CreateBookingRequest;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.CreateBookingResponse;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.GetBookingStatusRequest;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.GetBookingStatusResponse;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.ListBookingsRequest;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.ListBookingsResponse;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.PrepaymentStatus;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.Slot;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.UpdateBookingRequest;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.UpdateBookingResponse;
import ext.maps.booking.partner.v2.ApitemplateV2BookingService.UserPaymentOption;
import grpc.health.v1.Health.HealthImpl;
import io.grpc.Grpc;
import io.grpc.Metadata;
import io.grpc.Server;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import io.grpc.ServerInterceptors;
import io.grpc.Status;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyServerBuilder;
import io.grpc.stub.StreamObserver;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x500.style.IETFUtils;
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;

/** Booking Server with TLS enabled */
public class BookingService {
  private static final Logger logger = Logger.getLogger(BookingService.class.getName());

  private Server server;

  private final String host;
  private final int port;
  private final String certChainFilePath;
  private final String privateKeyFilePath;
  private final String trustedrootsFilePath;
  private final Set<String> acceptedCNs;

  public BookingService(
      String host,
      int port,
      String certChainFilePath,
      String privateKeyFilePath,
      String trustedrootsFilePath,
      Set<String> acceptedCNs) {
    this.host = host;
    this.port = port;
    this.certChainFilePath = certChainFilePath;
    this.privateKeyFilePath = privateKeyFilePath;
    this.trustedrootsFilePath = trustedrootsFilePath;
    this.acceptedCNs = acceptedCNs;
  }

  private SslContextBuilder getSslContextBuilder() {
    SslContextBuilder sslClientContextBuilder =
        SslContextBuilder.forServer(new File(certChainFilePath), new File(privateKeyFilePath));
    if (trustedrootsFilePath != null) {
      sslClientContextBuilder.trustManager(new File(trustedrootsFilePath));
      sslClientContextBuilder.clientAuth(ClientAuth.OPTIONAL);
    }
    return GrpcSslContexts.configure(sslClientContextBuilder, SslProvider.OPENSSL);
  }

  private void start() throws IOException {

    server =
        NettyServerBuilder.forAddress(new InetSocketAddress(host, port))
            .addService(ServerInterceptors.intercept(new BookingServiceImpl(), new MyInterceptor()))
            .addService(new HealthImpl())
            .sslContext(getSslContextBuilder().build())
            .build()
            .start();

    logger.info("Booking Server started, listening on " + port);
    Runtime.getRuntime()
        .addShutdownHook(
            new Thread() {
              @Override
              public void run() {
                // Use stderr here since the logger may have been reset by its JVM shutdown hook.
                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                BookingService.this.stop();
                System.err.println("*** server shut down");
              }
            });
  }

  private void stop() {
    if (server != null) {
      server.shutdown();
    }
  }

  /** Await termination on the main thread since the grpc library uses daemon threads. */
  private void blockUntilShutdown() throws InterruptedException {
    if (server != null) {
      server.awaitTermination();
    }
  }

  /** Main launches the server. */
  public static void main(String[] args) throws IOException, InterruptedException {
    // Set the accepted cns of the server
    Set<String> acceptedCNs = new HashSet<String>();
    acceptedCNs.add("mapsbooking.businesslink-3.net");

    // TODO(partner): override your host name, port, server_cert_chain file path,
    // private_key file path and trusted_client_roots file path here to build the server
    final BookingService server =
        new BookingService(
            "localhost",
            8443,
            "src/main/certificates/server_cert_chain.pem",
            "src/main/certificates/server_private_key.pem",
            "src/main/certificates/trusted_client_roots.pem",
            acceptedCNs);
    server.start();
    server.blockUntilShutdown();
  }

  /**
   * Implement the server interceptor to do peer certificate validation that checks for a specific
   * CN in the subject name, if the CN check fails, the connection will be closed with
   * "PERMISSION_DENIED" status message.
   */
  private class MyInterceptor implements ServerInterceptor {
    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
        ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
      SSLSession sslSession = call.getAttributes().get(Grpc.TRANSPORT_ATTR_SSL_SESSION);
      try {
        Certificate[] peerCerts = sslSession.getPeerCertificates();
        if (peerCerts[0] instanceof java.security.cert.X509Certificate) {
          X509Certificate peerCert = (X509Certificate) peerCerts[0];
          X500Name x500Name = new JcaX509CertificateHolder(peerCert).getSubject();
          RDN cn = x500Name.getRDNs(BCStyle.CN)[0];
          String peerCN = IETFUtils.valueToString(cn.getFirst().getValue());
          if (!acceptedCNs.contains(peerCN)) {
            throw new SSLPeerUnverifiedException("Invalid CN");
          }
        } else {
          throw new SSLPeerUnverifiedException("Invalid certificate type");
        }
      } catch (SSLPeerUnverifiedException se) {
        System.err.println(se.getMessage());
        call.close(Status.PERMISSION_DENIED, headers);
        return new ServerCall.Listener<ReqT>() {};
      } catch (CertificateEncodingException ce) {
        System.err.println(ce.getMessage());
        call.close(Status.PERMISSION_DENIED, headers);
        return new ServerCall.Listener<ReqT>() {};
      }
      return next.startCall(call, headers);
    }
  }

  /** The implementation of Booking Service. */
  static class BookingServiceImpl extends BookingServiceGrpc.BookingServiceImplBase {
    @Override
    public void checkAvailability(
        CheckAvailabilityRequest request,
        StreamObserver<CheckAvailabilityResponse> responseObserver) {

      Slot requestedSlot = request.getSlot();

      // TODO(partner): perform availability check
      //
      // Error conditions: response with corresponding canonical gRPC error code
      // example:
      //  responseObserver.onError(
      //      new StatusException(
      //          io.grpc.Status.INVALID_ARGUMENT.withDescription("Invalid merchant id")
      //      )
      //  );
      //
      // Happy path: implement the helper functions, populate the response

      CheckAvailabilityResponse response =
          CheckAvailabilityResponse.newBuilder()
              .setSlot(requestedSlot)
              .setCountAvailable(getAvailableSpots(requestedSlot))
              .setDurationRequirement(getDurationRequirement(requestedSlot)) // optional
              .setAvailabilityUpdate(getAvailabilityUpdate(requestedSlot)) // optional
              .build();

      responseObserver.onNext(response);
      responseObserver.onCompleted();
    }

    private int getAvailableSpots(Slot slot) {
      // TODO(partner): get the available spots for the given slot
      //
      // int available_spots = ...
      // return available_spots;

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

    private DurationRequirement getDurationRequirement(Slot slot) {
      // TODO(partner): optional, get the duration requirment for the given slot
      //
      // DurationRequirement durationRequirement = ...
      // return durationRequirement;

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

    private AvailabilityUpdate getAvailabilityUpdate(Slot slot) {
      // TODO(partner): optional, get the availability update for the given slot
      //
      // AvailabilityUpdate availabilityUpdate = ...
      // return availabilityUpdate;

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

    @Override
    public void createBooking(
        CreateBookingRequest request, StreamObserver<CreateBookingResponse> responseObserver) {

      // TODO(partner): create a booking based on the request
      //
      // Error conditions:
      // unexpected error -> response with corresponding canonical gRPC error code
      // example:
      //  responseObserver.onError(
      //      new StatusException(
      //          io.grpc.Status.INVALID_ARGUMENT.withDescription("Invalid merchant id")
      //      )
      //  );
      // business logic error -> set the BookingFailure in the response
      // example:
      // BookingFailure bookingFailure = BookingFailure.newBuilder()
      //     .setCause(Cause.SLOT_UNAVAILABLE)
      //     .setDescription("slot is not available now")
      //     .build();
      // CreateBookingResponse response = CreateBookingResponse.newBuilder()
      //     .setBookingFailure(bookingFailure)...
      //
      // Happy path: implement the helper functions, populate the response

      Booking booking = createSuccessfulBooking(request);

      CreateBookingResponse response =
          CreateBookingResponse.newBuilder()
              .setBooking(booking)
              .setUserPaymentOption(getUserPaymentOption(booking)) // optional
              .build();

      responseObserver.onNext(response);
      responseObserver.onCompleted();
    }

    private Booking createSuccessfulBooking(CreateBookingRequest request) {
      // TODO(partner): create a booking based on the create booking request and return the
      // created booking instance
      //
      // Booking created = ...(e.g.
      // Booking.newBuilder()
      //     .setBookingId("sampleBooking1")
      //     .setSlot(request.getSlot())
      //     .setUserInformation(request.getUserInformation())
      //     .setStatus(BookingStatus.CONFIRMED)
      //     .setPaymentInformation(request.getPaymentInformation())
      //     .build()
      // )
      // return created;

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

    private UserPaymentOption getUserPaymentOption(Booking booking) {
      // TODO(partner): optional, get the user payment option for the given booking
      //
      // UserPaymentOption paymentOption = ...
      // return paymentOption;

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

    @Override
    public void updateBooking(
        UpdateBookingRequest request, StreamObserver<UpdateBookingResponse> responseObserver) {

      // TODO(partner): update the booking based on the request
      //
      // Error conditions:
      // unexpected error -> response with corresponding canonical gRPC error code
      // example:
      //  responseObserver.onError(
      //      new StatusException(
      //          io.grpc.Status.NOT_FOUND.withDescription("Unknown booking id")
      //      )
      //  );
      // business logic error -> set the BookingFailure in the response
      // example:
      // BookingFailure bookingFailure = BookingFailure.newBuilder()
      //     .setCause(Cause.SLOT_UNAVAILABLE)
      //     .setDescription("slot is not available now")
      //     .build();
      // CreateBookingResponse response = CreateBookingResponse.newBuilder()
      //     .setBookingFailure(bookingFailure)...
      //
      // Happy path: implement the helper functions, populate the response

      Booking booking = updateSuccessfulBooking(request);

      UpdateBookingResponse response =
          UpdateBookingResponse.newBuilder()
              .setBooking(booking)
              .setUserPaymentOption(getUserPaymentOption(booking)) // option
              .build();

      responseObserver.onNext(response);
      responseObserver.onCompleted();
    }

    private Booking updateSuccessfulBooking(UpdateBookingRequest request) {
      // TODO(partner): look up the booking with bookingId, update fields according to
      // updateMask and return the updated booking instance
      //
      // String bookingId = request.getBooking().getBookingId();
      // FieldMask updateMask = request.getUpdateMask();
      // Booking updated = ...
      // return updated;

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

    @Override
    public void getBookingStatus(
        GetBookingStatusRequest request,
        StreamObserver<GetBookingStatusResponse> responseObserver) {

      String bookingId = request.getBookingId();

      // TODO(partner): look up the booking status and prepayment status with bookingId
      //
      // Error conditions:
      // unexpected error -> response with corresponding canonical gRPC error code
      // example:
      //  responseObserver.onError(
      //      new StatusException(
      //          io.grpc.Status.NOT_FOUND.withDescription("Unknown booking id")
      //      )
      //  );
      //
      // Happy path: implement the helper functions, populate the response

      GetBookingStatusResponse response =
          GetBookingStatusResponse.newBuilder()
              .setBookingId(bookingId)
              .setBookingStatus(getBookingStatus(bookingId))
              .setPrepaymentStatus(getPrepaymentStatus(bookingId))
              .build();

      responseObserver.onNext(response);
      responseObserver.onCompleted();
    }

    private BookingStatus getBookingStatus(String bookingId) {
      // TODO(partner): get the booking status for the given bookingId
      //
      // BookingStatus bookingStatus = ...
      // return bookingStatus;

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

    private PrepaymentStatus getPrepaymentStatus(String bookingId) {
      // TODO(partner): get the prepayment status for the given bookingId
      //
      // Prepayment prepaymentStatus = ...
      // return prepaymentStatus;

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

    @Override
    public void listBookings(
        ListBookingsRequest request, StreamObserver<ListBookingsResponse> responseObserver) {

      String userId = request.getUserId();

      // TODO(partner): look up all bookings with the given userId
      //
      // Error conditions:
      // unexpected error -> response with corresponding canonical gRPC error code
      // example:
      //  responseObserver.onError(
      //      new StatusException(
      //          io.grpc.Status.NOT_FOUND.withDescription("Unknown user id")
      //      )
      //  );
      //
      // Happy path: implement the helper function, populate the response

      ListBookingsResponse response =
          ListBookingsResponse.newBuilder().addAllBookings(getListBooking(userId)).build();

      responseObserver.onNext(response);
      responseObserver.onCompleted();
    }

    private List<Booking> getListBooking(String userId) {
      // TODO(partner): get the bookings list for the given userId
      //
      // List<Booking> bookings = ...
      // return bookings;

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