content: from __future__ import print_function
  from google.transit import gtfs_realtime_pb2
  import requests
  import pandas as pd
  from io import BytesIO
  import zipfile
  import os
  import os.path
  import datetime
  import math
  
  UTC_OFFSET = int(os.getenv('OFFSET', 7))
  DEFAULT_LOCATION = {u'lat': 39.7433814, u'lng': -104.98910989999999}
  
  def get_gtfs_data(force=False):
      url = 'http://www.rtd-denver.com/GoogleFeeder/google_transit_Apr16_Runboard.zip'
      headers_file = 'google_feeder_headers.txt'
  
      last_modified = requests.head(url).headers['Date']
      rerequest = False
  
      if not os.path.isfile(headers_file):
          rerequest = True
      else:
          with open(headers_file) as f:
              f_line = f.read()
              if last_modified not in f_line:
                  print("File are not the same, submit rerequest")
                  if force:
                      rerequest=True
              else:
                  print("File unchanged!")
                  if not os.path.isfile('stops.txt') or not os.path.isfile('trips.txt'):
                      rerequest = True
                      print("Files missing")
  
      if rerequest:
          print("Re-requesting data")
          request = requests.get(url)
          z = zipfile.ZipFile(BytesIO(request.content))
          z.extractall()
          with open(headers_file, 'w') as f:
              print(last_modified, file=f)
          return z
                  
  def convert_df_to_list(df):
  
      # bus20_east_list = [str(i) for i in bus20_east_df['trip_id'].tolist()]
      # bus20_west_list = [str(i) for i in bus20_west_df['trip_id'].tolist()]
      return([str(i) for i in df['trip_id'].tolist()])
  
  def get_real_time_data_request_response(header=False):
      if header:
          r = requests.head('http://www.rtd-denver.com/google_sync/TripUpdate.pb', auth=(os.getenv('RTD_USERNAME'), os.getenv('RTD_PASSWORD')))
          return(r.headers)
      else:
          r = requests.get('http://www.rtd-denver.com/google_sync/TripUpdate.pb', auth=(os.getenv('RTD_USERNAME'), os.getenv('RTD_PASSWORD')))
          if r.ok:
              return(r.content)
          else:
              return None
  
  def get_entities(bus_list):
  
      feed = gtfs_realtime_pb2.FeedMessage()
      content = get_real_time_data_request_response()
      feed.ParseFromString(content)
      list_entities = []
  
      for entity in feed.entity:
          if entity.trip_update.trip.trip_id in bus_list:
              list_entities.append(entity)
  
  
      print("Getting entities")
      print(list_entities)
      return(list_entities)
  
  def get_markers_for_list_entities(list_entities, stops_df, current_location=DEFAULT_LOCATION, trips_df=None):
      if trips_df is None:
          trips_df = pd.read_csv('trips.txt')
  
      marker = []
      for entity in list_entities:
          stop_time_update = entity.trip_update.stop_time_update[0]
          delay = stop_time_update.departure.delay
          uncertainty = stop_time_update.departure.uncertainty
          dt = datetime.datetime.fromtimestamp(stop_time_update.departure.time)
          dt = dt - datetime.timedelta(hours=UTC_OFFSET)
          departure_time = dt.strftime('%H:%M')
  
          closest_stop_time = 0
          closest_stop_name = ''
  
          trip_id = entity.trip_update.trip.trip_id
          route_id, route_name = get_bus_name(trip_id, trips_df)
  
          lat, lon, stop_name = get_location_of_stop_time_update(stop_time_update)
  
          marker.append((lat, lon, stop_name, departure_time, delay, uncertainty, closest_stop_time, closest_stop_name, route_id, route_name, trip_id))
  
      return marker
  
  def get_location_of_stop_time_update(stop_time_update):
      stops_df = pd.read_csv('stops.txt')
      lat = stops_df[stops_df['stop_id']==int(stop_time_update.stop_id)]['stop_lat'].iloc[0]
      lon = stops_df[stops_df['stop_id']==int(stop_time_update.stop_id)]['stop_lon'].iloc[0]
      stop_name = stops_df[stops_df['stop_id']==int(stop_time_update.stop_id)]['stop_name'].iloc[0].replace('[ X Stop ]', '')
      return lat, lon, stop_name
  
  
  def get_stop_location_list(stop_time_update):
      list_stop_location = []
  
      for stop_time in stop_time_update:
          lat, lon, stop_name = get_location_of_stop_time_update(stop_time)
  
          arrival_time_dt = datetime.datetime.fromtimestamp(stop_time.arrival.time) - datetime.timedelta(hours=UTC_OFFSET)
          arrival_time = arrival_time_dt.strftime('%H:%M')
          if stop_time.arrival.delay != 0 or stop_time.arrival.uncertainty !=0:
              arrival_time = arrival_time + '\nwith a delay of {} with uncertainty {}'
  
          departure_time_dt = datetime.datetime.fromtimestamp(stop_time.departure.time) - datetime.timedelta(hours=UTC_OFFSET)
          departure_time = departure_time_dt.strftime('%H:%M')
          if stop_time.departure.delay != 0 or stop_time.departure.uncertainty !=0:
              departure_time = departure_time + '\nwith a delay of {} with uncertainty {}'
  
          list_stop_location.append({'lat': lat, 'lng': lon, 'stop_name': stop_name, 'departure_time': departure_time, 'arrival_time': arrival_time})
  
      return list_stop_location
  
  def get_closest_stop_time(closest_stop_id, entity):
  
      for stop_time_update in entity.trip_update.stop_time_update:
          if int(stop_time_update.stop_id) == int(closest_stop_id):
              dt = datetime.datetime.fromtimestamp(stop_time_update.departure.time)
              dt = dt - datetime.timedelta(hours=UTC_OFFSET)
              departure_time = dt.strftime('%H:%M')
              return(departure_time)
  
  def get_stop_name(stop_id, stops_df):
      return(stops_df.loc[stops_df['stop_id'] == 10277]['stop_name'].values[0])
  
  def find_closest_stop(stops_df, latlon, stop_id_list):
      lat = latlon[0]
      lon = latlon[1]
      stops_df = stops_df[stops_df['stop_id'].isin(stop_id_list)]
      stops_df['minimum_distance'] = (stops_df['stop_lat'] - lat)**2 + (stops_df['stop_lon'] - lon)**2
      
      closest_stop_id = stops_df.loc[stops_df['minimum_distance'].argmin()]['stop_id']
      
      return closest_stop_id
  
  def get_bus_name(trip_id, trips_df):
      return(trips_df[trips_df['trip_id'] == int(trip_id)]['route_id'].values[0],
              trips_df[trips_df['trip_id'] == int(trip_id)]['trip_headsign'].values[0])
  
  def get_stop_id_list(entity):
      stop_id_list = []
      for sq in entity.trip_update.stop_time_update:
          stop_id_list.append(int(sq.stop_id))
      return stop_id_list
  
  def get_bus_list(trips_df):
      trips_df['unique_route_id'] = trips_df['route_id']+': '+trips_df['trip_headsign']
      bl = trips_df['unique_route_id'].unique()
      return(bl.tolist())
  
  
  def get_location_of_routes(l):
  
      routePaths = {}
      for entity in l:
          trip_id = entity.trip_update.trip.trip_id
          routePaths[trip_id] = get_stop_location_list(entity.trip_update.stop_time_update)
  
      return routePaths
  
  def get_all_current_position_markers(route, current_location=DEFAULT_LOCATION):
      stops_df = pd.read_csv('stops.txt')
  
      l = get_currently_active_trips(route)
      print("Inside get all current position markers")
      print(l)
      markers = {route: get_markers_for_list_entities(l,  stops_df, current_location)}
      routePaths = get_location_of_routes(l)
  
      data = {'markers': markers,
              'routePaths': routePaths }
  
      return(data)
  
  def parse_route_name(route):
      route_id = route.split(':')[0].replace('Route ', '').strip(' ')
      trip_headsign = route.split(':')[1].strip(' ')
      
      return route_id, trip_headsign
  
  def get_trip_id(route, trips_df):
      dt = datetime.datetime.now()
      dt = dt - datetime.timedelta(hours=4)
      dt.isoweekday()
  
      saturday = dt.isoweekday() == 6
      sunday = dt.isoweekday() == 7
  
      if saturday:
          trips_df = trips_df[trips_df['service_id'] == 'SA']
      elif sunday:
          trips_df = trips_df[trips_df['service_id'] == 'SU']
      else: # weekday:
          trips_df = trips_df[trips_df['service_id'] == 'WK']
  
      trips_df['unique_route_id'] = 'Route ' + trips_df['route_id']+': '+trips_df['trip_headsign']
      route_id, trip_headsign = parse_route_name(route)
      trips_df = trips_df[trips_df['route_id'] == route_id]
      trips_df = trips_df[trips_df['trip_headsign'] == trip_headsign]
      return trips_df['trip_id'].tolist()
  
  def get_currently_active_trips(route):
      trips_df = pd.read_csv('trips.txt')
      total_trip_list = [str(item) for item in get_trip_id(route, trips_df)]
      print("total trip list is ")
      print(total_trip_list)
      return get_entities(total_trip_list)
  
  def get_route_name(trip_id):
      df = pd.read_csv('./trips.txt')
      route_df = df[df['trip_id'] == int(trip_id)]
  
      return(str(route_df['route_id'].values[0]) + ': ' + route_df['trip_headsign'].values[0])
  
  def get_route_data(trip_id):
      return({
          'stop_time_update': get_stop_time_update(trip_id),
          'route_name': get_route_name(trip_id),
      })
  
  def get_stop_time_update(trip_id):
      feed = gtfs_realtime_pb2.FeedMessage()
      content = get_real_time_data_request_response()
      feed.ParseFromString(content)
      list_entities = []
  
      realtime_entity_list = feed.entity
  
      for trip in realtime_entity_list:
          if trip.trip_update.trip.trip_id == str(trip_id):
              return([stop_time_update_to_dict(stu) for stu in trip.trip_update.stop_time_update])
  
  def stop_time_update_to_dict(stu):
      lat, lon, stop_name = get_location_of_stop_time_update(stu)
      return({
          'location': [lat, lon],
          'stop_name': stop_name,
          'stop_sequence': stu.stop_sequence,
          'arrival': {
              'time': time_convert(stu.arrival.time),
              'uncertainty': stu.arrival.uncertainty,
              'delay': stu.arrival.delay
          },
          'departure': {
              'time': time_convert(stu.departure.time),
              'uncertainty': stu.departure.uncertainty,
              'delay': stu.departure.delay
          },
          'schedule_relationship': 'SCHEDULED' if stu.schedule_relationship==0 else 'UNKNOWN'
      })
  
  def time_convert(t):
      dt = datetime.datetime.fromtimestamp(t)
      dt = dt - datetime.timedelta(hours=UTC_OFFSET)
      departure_time = dt.strftime('%H:%M')
      return(departure_time)
  
  def get_trip_ids(route_id, trip_headsign):
  
      trips_df = pd.read_csv("./trips.txt")
  
      route_df = trips_df[(trips_df['route_id'] == str(route_id)) & (trips_df['trip_headsign'] == trip_headsign)]
  
      feed = gtfs_realtime_pb2.FeedMessage()
      content = get_real_time_data_request_response()
      feed.ParseFromString(content)
      list_entities = []
  
      realtime_entity_list = feed.entity
  
      current_routes = []
  
      for trip in realtime_entity_list:
          if any(route_df['trip_id'] == int(trip.trip_update.trip.trip_id)):
              lat, lon, stop_name = get_location_of_stop_time_update(trip.trip_update.stop_time_update[0])
              current_routes.append({
                      'trip_name': route_id + ": " + trip_headsign,
                      'trip_id': int(trip.trip_update.trip.trip_id),
                      'location': [lat, lon],
                      'current_location': stop_name,
                      'expected_departure': time_convert(trip.trip_update.stop_time_update[0].departure.time)
                  })
  
      return(current_routes)
  
  
  
  def distance_on_unit_sphere(x, lat2, long2):
  
      lat1 = x['stop_lat']
      long1 = x['stop_lon']
  
      # Convert latitude and longitude to
      # spherical coordinates in radians.
      degrees_to_radians = math.pi/180.0
  
      # phi = 90 - latitude
      phi1 = (90.0 - lat1)*degrees_to_radians
      phi2 = (90.0 - lat2)*degrees_to_radians
  
      # theta = longitude
      theta1 = long1*degrees_to_radians
      theta2 = long2*degrees_to_radians
  
      # Compute spherical distance from spherical coordinates.
  
      # For two locations in spherical coordinates
      # (1, theta, phi) and (1, theta', phi')
      # cosine( arc length ) =
      #    sin phi sin phi' cos(theta-theta') + cos phi cos phi'
      # distance = rho * arc length
  
      cos = (math.sin(phi1)*math.sin(phi2)*math.cos(theta1 - theta2) +
             math.cos(phi1)*math.cos(phi2))
      arc = math.acos( cos )
  
      # Remember to multiply arc by the radius of the earth
      # in your favorite set of units to get length.
      return 3959 * arc
  
  def list_of_closest_buses(lat, lng):
      trips_df = pd.read_csv('./trips.txt')
      stop_df = pd.read_csv('./stops.txt')
      stop_df['proximity'] = stop_df.apply(distance_on_unit_sphere, args=(lat,lng), axis=1)
      stop_df = stop_df.sort_values(by='proximity')
      stop_times_df = pd.read_csv('./stop_times.txt')
      unique_bus_names = []
      i = 0
      while len(unique_bus_names) < 5:
          build_bus_name_list(unique_bus_names, stop_df, stop_times_df, trips_df, i)
          i = i+1
  
      return(unique_bus_names)
  
  def build_bus_name_list(unique_bus_names, stop_df, stop_times_df, trips_df, i):
      stop_id = stop_df.iloc[i]['stop_id']
  
      def match_bus_name(x):
          route_id, route_name = get_bus_name(x['trip_id'], trips_df)
          return(route_id + ": " + route_name)
  
      for item in stop_times_df[stop_times_df['stop_id'] == stop_id].apply(match_bus_name, axis=1).unique():
          if item not in unique_bus_names:
              unique_bus_names.append(item)
  