# Copyright 2016 gRPC authors.
#
# 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.

"""A gRPC server servicing both Greeter and RouteGuide RPCs."""

from concurrent import futures
import time
import math

import grpc

import helloworld_pb2
import helloworld_pb2_grpc
import route_guide_pb2
import route_guide_pb2_grpc
import route_guide_resources

_ONE_DAY_IN_SECONDS = 60 * 60 * 24


def _get_feature(feature_db, point):
  """Returns Feature at given location or None."""
  for feature in feature_db:
    if feature.location == point:
      return feature
  return None


def _get_distance(start, end):
  """Distance between two points."""
  coord_factor = 10000000.0
  lat_1 = start.latitude / coord_factor
  lat_2 = end.latitude / coord_factor
  lon_1 = start.longitude / coord_factor
  lon_2 = end.longitude / coord_factor
  lat_rad_1 = math.radians(lat_1)
  lat_rad_2 = math.radians(lat_2)
  delta_lat_rad = math.radians(lat_2 - lat_1)
  delta_lon_rad = math.radians(lon_2 - lon_1)

  a = (pow(math.sin(delta_lat_rad / 2), 2) +
       (math.cos(lat_rad_1) * math.cos(lat_rad_2) *
        pow(math.sin(delta_lon_rad / 2), 2)))
  c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
  R = 6371000; # metres
  return R * c;


class _GreeterServicer(helloworld_pb2_grpc.GreeterServicer):

  def SayHello(self, request, context):
    return helloworld_pb2.HelloReply(message='Hello, {}!'.format(request.name))


class _RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
  """Provides methods that implement functionality of route guide server."""

  def __init__(self):
    self.db = route_guide_resources.read_route_guide_database()

  def GetFeature(self, request, context):
    feature = _get_feature(self.db, request)
    if feature is None:
      return route_guide_pb2.Feature(name="", location=request)
    else:
      return feature

  def ListFeatures(self, request, context):
    left = min(request.lo.longitude, request.hi.longitude)
    right = max(request.lo.longitude, request.hi.longitude)
    top = max(request.lo.latitude, request.hi.latitude)
    bottom = min(request.lo.latitude, request.hi.latitude)
    for feature in self.db:
      if (feature.location.longitude >= left and
          feature.location.longitude <= right and
          feature.location.latitude >= bottom and
          feature.location.latitude <= top):
        yield feature

  def RecordRoute(self, request_iterator, context):
    point_count = 0
    feature_count = 0
    distance = 0.0
    prev_point = None

    start_time = time.time()
    for point in request_iterator:
      point_count += 1
      if _get_feature(self.db, point):
        feature_count += 1
      if prev_point:
        distance += _get_distance(prev_point, point)
      prev_point = point

    elapsed_time = time.time() - start_time
    return route_guide_pb2.RouteSummary(point_count=point_count,
                                        feature_count=feature_count,
                                        distance=int(distance),
                                        elapsed_time=int(elapsed_time))

  def RouteChat(self, request_iterator, context):
    prev_notes = []
    for new_note in request_iterator:
      for prev_note in prev_notes:
        if prev_note.location == new_note.location:
          yield prev_note
      prev_notes.append(new_note)


def serve():
  server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
  helloworld_pb2_grpc.add_GreeterServicer_to_server(_GreeterServicer(), server)
  route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
      _RouteGuideServicer(), server)
  server.add_insecure_port('[::]:50051')
  server.start()
  try:
    while True:
      time.sleep(_ONE_DAY_IN_SECONDS)
  except KeyboardInterrupt:
    server.stop(0)


if __name__ == '__main__':
  serve()
