2018-04-25 13:16:36 +02:00
package externalroute
import (
"fmt"
"strings"
"sync"
"time"
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
"bitbucket.org/nemt/nemt-portal-api/application/tncservice"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/config"
"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
"github.com/labstack/echo"
)
var (
instance * controller
once sync . Once
)
type controller struct {
cfg * config . Config
svc * applicationservice . Service
tnc * tncservice . Service
notification * notificationservice . Service
}
func controllerInstance ( cfg * config . Config , svc * applicationservice . Service , tnc * tncservice . Service , notification * notificationservice . Service ) * controller {
once . Do ( func ( ) {
instance = & controller {
cfg : cfg ,
svc : svc ,
tnc : tnc ,
notification : notification ,
}
} )
return instance
}
func ( c * controller ) getDriverNotification ( ride viewmodel . Ride , notificationType string , subject string , message string , to string , from string ) viewmodel . Notification {
retVal := viewmodel . Notification {
Type : notificationType ,
Message : message ,
Subject : subject ,
Ride : ride ,
User : ride . User ,
CreatedUser : ride . CreatedUser ,
To : to ,
From : from ,
}
return retVal
}
func ( c * controller ) handleCancel ( ctx echo . Context ) error {
var rideUUID = ctx . Param ( "ride_uuid" )
var userUUID = ctx . Param ( "user_uuid" )
ride , err := c . svc . Rides . GetByUUIDAndUserUUID ( rideUUID , userUUID )
if err != nil {
return routeutils . HandleAPIError ( ctx , err )
}
2018-06-01 10:39:46 +02:00
authUser , err := c . svc . Users . GetByUUID ( ride . CreatedUser . ID , "" )
if err != nil {
return routeutils . HandleAPIError ( ctx , err )
}
2018-04-25 13:16:36 +02:00
lyftRide := viewmodel . RideRequest { RideID : ride . InternalID }
if ride . Status . Key == "scheduled" && ! strings . Contains ( ride . InternalID , "s_" ) {
lyftRide . RideID = "s_" + ride . InternalID
}
2018-06-01 10:39:46 +02:00
if authUser . Test {
2018-04-25 13:16:36 +02:00
if err = c . tnc . Lyft . CancelRide ( lyftRide ) ; err != nil {
if err . Error ( ) != "ride_not_found" {
fmt . Println ( "Error to cancel with Lyft: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
}
} else {
fmt . Println ( "In Production" )
if err = c . tnc . LyftProd . CancelRide ( lyftRide ) ; err != nil {
fmt . Println ( "Error to cancel with Lyft: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
}
err = c . svc . Rides . UpdateStatus ( rideUUID , "canceled" )
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
// ride.Status.Key = "canceled"
// err = c.svc.Notification.SendNotification(ride.Status.Key, ride, viewmodel.RideRequest{})
// if err != nil {
// fmt.Println("Error to notify: ", err.Error())
// }
ctx . Response ( ) . Header ( ) . Set ( "Content-Type" , "application/json" )
return routeutils . ResponseNoContent ( ctx , nil )
}
func ( c * controller ) handleMessage ( ctx echo . Context ) error {
var rideUUID = ctx . Param ( "ride_uuid" )
var userUUID = ctx . Param ( "user_uuid" )
ride , err := c . svc . Rides . GetByUUIDAndUserUUID ( rideUUID , userUUID )
if err != nil {
return routeutils . HandleAPIError ( ctx , err )
}
message := make ( map [ string ] string )
err = ctx . Bind ( & message )
if err != nil || message [ "message" ] == "" {
return routeutils . ResponseAPIValidationError ( ctx , "message body param is mandatory" )
}
if err != nil || message [ "to" ] == "" {
return routeutils . ResponseAPIValidationError ( ctx , "to param is mandatory" )
}
notifications := make ( [ ] viewmodel . Notification , 0 )
if message [ "to" ] == "driver" {
notifications = append ( notifications , c . getDriverNotification ( ride , "sms" , "A message to driver" , message [ "message" ] , ride . Driver . PhoneNumber , * ride . User . PhoneNumber ) )
} else {
notifications = append ( notifications , c . getDriverNotification ( ride , "sms" , "A message to dispatcher" , message [ "message" ] , * ride . CreatedUser . PhoneNumber , * ride . User . PhoneNumber ) )
notifications = append ( notifications , c . getDriverNotification ( ride , "email" , "A message to dispatcher" , message [ "message" ] , * ride . CreatedUser . Email , * ride . User . Email ) )
}
notifications , err = c . svc . Notification . SendNotifications ( notifications )
if err != nil {
return routeutils . HandleAPIError ( ctx , err )
}
return routeutils . ResponseAPIOK ( ctx , notifications )
}
func ( c * controller ) handle ( ctx echo . Context ) error {
var rideUUID = ctx . Param ( "ride_uuid" )
var userUUID = ctx . Param ( "user_uuid" )
ride , err := c . svc . Rides . GetByUUIDAndUserUUID ( rideUUID , userUUID )
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
2018-06-01 10:39:46 +02:00
authUser , err := c . svc . Users . GetByUUID ( ride . CreatedUser . ID , "" )
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
2018-04-25 13:16:36 +02:00
if ride . Status . Key == "accepted" || ride . Status . Key == "pickedUp" || ride . Status . Key == "arrived" {
var lyftRide viewmodel . RideRequest
var err error
2018-06-01 10:39:46 +02:00
if authUser . Test {
2018-04-25 13:16:36 +02:00
lyftRide , err = c . tnc . Lyft . GetRideDetails ( viewmodel . RideRequest { RideID : ride . InternalID } )
} else {
lyftRide , err = c . tnc . LyftProd . GetRideDetails ( viewmodel . RideRequest { RideID : ride . InternalID } )
}
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
ride . Route . Location = ride . Route . Origin
ride . Route . Location . Address = ""
ride . Route . Location . Name = ""
switch ride . Status . Key {
case "accepted" :
if lyftRide . Origin . ETASeconds != nil {
ride . Route . ETA = * lyftRide . Origin . ETASeconds
} else {
ride . Route . ETA = 0
if c . cfg . App . Debug {
ride . Route . ETA = 350
}
}
case "pickedUp" :
case "arrived" :
if lyftRide . Destination . ETASeconds != nil {
ride . Route . ETA = * lyftRide . Destination . ETASeconds
} else {
ride . Route . ETA = 0
if c . cfg . App . Debug {
ride . Route . ETA = 350
}
}
}
if lyftRide . Location . Latitude != 0 && lyftRide . Location . Longitude != 0 {
ride . Route . Location . Latitude = lyftRide . Location . Latitude
ride . Route . Location . Longitude = lyftRide . Location . Longitude
ride . Route . Location . Bearing = lyftRide . Location . Bearing
}
}
ride . InternalID = ""
ride . User . Gender = nil
ride . User . Email = nil
ride . User . PhoneNumber = nil
ride . Passenger = viewmodel . UserLyft { }
// ride.Visit = viewmodel.Visit{
// ExternalID: ride.Visit.ExternalID,
// }
ride . CreatedUser = viewmodel . User { }
return routeutils . ResponseAPIOK ( ctx , ride )
}
func ( c * controller ) handleReady ( ctx echo . Context ) error {
var rideUUID = ctx . Param ( "ride_uuid" )
var userUUID = ctx . Param ( "user_uuid" )
ride , err := c . svc . Rides . GetByUUIDAndUserUUID ( rideUUID , userUUID )
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
authUser , err := c . svc . Users . GetByUUID ( ride . CreatedUser . ID , "" )
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
var nextRide viewmodel . Ride
if ride . TripType . Key == "from_visit_call" && ride . Status . Key == "willCall" {
nextRide = ride
} else if ride . Visit . TripType . Key == "roundtrip_call" && ride . TripType . Key == "to_visit" {
roundTripRide , err := c . svc . Rides . GetByVisitUUIDAndTripType ( ride . Visit . UUID , "from_visit_call" , authUser )
if err != nil {
fmt . Println ( "Error to get next ride: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
nextRide = roundTripRide
} else {
fmt . Println ( "Error on get next ride " )
return routeutils . ResponseAPINotFoundError ( ctx )
}
var lyftRide viewmodel . RideRequest
2018-06-01 10:39:46 +02:00
if authUser . Test {
2018-04-25 13:16:36 +02:00
lyftRide , err = c . tnc . Lyft . GetRideDetails ( viewmodel . RideRequest { RideID : ride . InternalID } )
} else {
fmt . Println ( "In Production" )
lyftRide , err = c . tnc . LyftProd . GetRideDetails ( viewmodel . RideRequest { RideID : ride . InternalID } )
}
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
lyftRide . RideID = ""
lyftRide . Destination = ride . Route . Destination
lyftRide . Origin = ride . Route . Origin
name := nextRide . User . Name
names := strings . Split ( name , " " )
lyftRide . Passenger . FirstName = names [ 0 ]
lyftRide . Passenger . LastName = " "
lyftRide . Passenger . PhoneNumber = * nextRide . User . PhoneNumber
lyftRide . RideType = "lyft"
2018-06-01 10:39:46 +02:00
if authUser . Test {
2018-04-25 13:16:36 +02:00
lyftRide , err = c . tnc . Lyft . RequestRide ( lyftRide )
} else {
fmt . Println ( "In Production" )
lyftRide , err = c . tnc . LyftProd . RequestRide ( lyftRide )
}
if err != nil {
return routeutils . HandleAPIError ( ctx , err )
}
currentTime := time . Now ( )
lyftRide . PickupTime = & currentTime
lyftRide . ReturnTime = & currentTime
nextRide . PickupTime = & currentTime
nextRide , err = c . svc . Rides . UpdateNewRide ( nextRide , lyftRide , authUser )
if err != nil {
fmt . Println ( "Error: " , err . Error ( ) )
return routeutils . HandleAPIError ( ctx , err )
}
go func ( ) {
err = c . svc . Notification . SendNotification ( lyftRide . Status , nextRide , lyftRide )
if err != nil {
fmt . Println ( "Error to notify user: " , err . Error ( ) )
}
} ( )
return routeutils . ResponseAPIOK ( ctx , nextRide )
}