package kmb

import (
    "fmt"
    "sort"
    "strings"
    "time"

    query "github.com/tgckpg/golifehk/query"
    utils "github.com/tgckpg/golifehk/utils"
)

type QueryResult struct {
    Schedules *map[*RouteStop] *[] *Schedule
    Lang string
    Error error
    Query *query.QueryObject
}

func writeRouteHead( sb *strings.Builder, r *RouteStop ) {
    utils.WriteMDv2Text( sb, r.RouteId )
    if r.Direction == "O" {
        sb.WriteString( "↑" )
    } else if r.Direction == "I" {
        sb.WriteString( "↓" )
    }
    if r.ServiceType != "1" {
        utils.WriteMDv2Text( sb, utils.ToPower( r.ServiceType ) )
    }
}

func writeShortRoute( lang *string, sb *strings.Builder, r *RouteStop ) {

    if r.PrevStop() != nil {
        utils.WriteMDv2Text( sb, (*(r.PrevStop().BusStop).Name)[ *lang ] )
        sb.WriteString( " \\> " )
    }

    sb.WriteString( "*" )
    utils.WriteMDv2Text( sb, (*(r.BusStop).Name)[ *lang ] )
    sb.WriteString( "*" )

    if r.NextStop() != nil {
        sb.WriteString( " \\> " )
        utils.WriteMDv2Text( sb, (*(r.NextStop().BusStop).Name)[ *lang ] )
    }

    sb.WriteString( "\n" )
}

func ( this *QueryResult ) Message() ( string, error ) {

    if this.Error != nil {
        return "", this.Error
    }

    sb := strings.Builder{}

    if 0 < len( *this.Query.Results ) {

        // Print Stop Names, then print the list of routes
        if this.Query.Key == "" {
            busStops := map[string] *BusStop{}
            for _, item := range *this.Query.Results {
                var r *RouteStop
                r = any( item ).( *RouteStop )

                b := r.BusStop
                if b.Routes == nil {
                    continue
                }

                busStops[ b.BusStopId ] = b
            }

            for _, b := range busStops {
                utils.WriteMDv2Text( &sb, (*b.Name)[ this.Lang ] )
                sb.WriteString( "\n  " )
                for _, route := range *b.Routes {
                    writeRouteHead( &sb, route )
                    sb.WriteString( " " )
                }
                sb.WriteString( "\n" )
            }

        // We got a route key
        } else {

            // We also got other search keys with 1 < Results
            // Get the ETA for this stop
            if 1 < len( *this.Query.SearchTerms )  {

                now := time.Now()
                for _, item := range *this.Query.Results {
                    var r *RouteStop
                    r = any( item ).( *RouteStop )
                    writeRouteHead( &sb, r )
                    sb.WriteString( "\n" )
                    writeShortRoute( &this.Lang, &sb, r )

                    for _, schedule := range *(*this.Schedules)[ r ] {

                        if !schedule.ETA.IsZero() {

                            _m := schedule.ETA.Sub( now ).Minutes()

                            sb.WriteString( "  \\* " )
                            txt := "%.0f min(s)"

                            if this.Lang == "zh-Hant" {
                                txt = "%.0f 分鐘"
                            }

                            utils.WriteMDv2Text( &sb, fmt.Sprintf( txt, _m ) )

                            if _m < 0 {
                                sb.WriteString( " 走左了?" )
                            }
                        }

                        if schedule.Remarks_en != "" {
                            sb.WriteString( "  \\*\\* " )
                            switch this.Lang {
                            case "en":
                                utils.WriteMDv2Text( &sb, schedule.Remarks_en )
                            case "zh-Hant":
                                utils.WriteMDv2Text( &sb, schedule.Remarks_tc )
                            }
                        }

                        sb.WriteString( "\n" )
                    }

                    sb.WriteString( "\n" )
                }

            // We got only the route key, proceed to list the route stops
            } else {
                // Result contains all route stops, we only need the starting one
                routes := [] *RouteStop{}

                for _, item := range *this.Query.Results {
                    var r *RouteStop
                    r = any( item ).( *RouteStop )
                    if r.PrevStop() == nil {
                        routes = append( routes, r )
                    }
                }

                sort.Sort( ByRoute( routes ) )

                for _, r := range routes {
                    writeRouteHead( &sb, r )
                    sb.WriteString( "\n" )
                    for {
                        b := *r.BusStop
                        utils.WriteMDv2Text( &sb, (*b.Name)[ this.Lang ] )
                        r = r.NextStop()
                        if r == nil {
                            break
                        }

                        sb.WriteString( " \\> " )
                    }
                    sb.WriteString( "\n" )
                }


            }
        }
    } else {
        return "", fmt.Errorf( "No Results" )
    }

    return sb.String(), nil
}