package darwindb

import (
	"fmt"
	"time"

	"hg.lukegb.com/lukegb/depot/go/trains/darwin"
)

// secondsify adds :00 onto the end of a string if it's HH:MM formatted, otherwise does nothing.
func secondsify(ts string) string {
	if len(ts) == 5 { // xx:xx (no seconds)
		return ts + ":00"
	}
	return ts
}

// startTime takes a train and ascertains its "start time".
func startTime(s *darwin.Schedule) (time.Time, error) {
	// We assume these are sensibly sorted by Darwin.
	if len(s.CallingPoints) == 0 {
		return time.Time{}, fmt.Errorf("no calling points")
	}
	cp := s.CallingPoints[0]

	var ts string
	tsCandidates := []string{cp.WTD, cp.PTD, cp.WTP, cp.WTA, cp.PTA}
	for _, tsc := range tsCandidates {
		if tsc != "" {
			ts = tsc
		}
	}
	if ts == "" {
		return time.Time{}, fmt.Errorf("failed to find a suitable timestamp in first calling point")
	}

	ts = fmt.Sprintf("%v %v", s.SSD, secondsify(ts))

	t, err := time.ParseInLocation("2006-01-02 15:04:05", ts, darwin.London)
	if err != nil {
		return time.Time{}, fmt.Errorf("parsing start time %q: %w", ts, err)
	}
	return t, nil
}

// timeToTimestamp takes a string HH:MM and places it appropriately given the approximate 'start time' of the train.
func timeToTimestamp(ts string, startTime time.Time) *time.Time {
	if ts == "" {
		return nil
	}
	ts = secondsify(ts)

	t, err := time.ParseInLocation("2006-01-02 15:04:05", startTime.Format("2006-01-02 ")+ts, darwin.London)
	if err != nil {
		return nil
	}

	// Follow Darwin rules for determining time skips
	// https://wiki.openraildata.com/index.php/Darwin:Schedule_Element#Ordering
	difference := t.Sub(startTime)
	switch {
	case difference > -6*time.Hour && difference < 18*time.Hour:
		return &t
	case difference <= -6*time.Hour:
		// e.g. 08:00 start time, 01:00 time "now" (-7 hrs) -- add a day
		t = t.AddDate(0, 0, 1)
		return &t
	case difference >= 18*time.Hour:
		// e.g. 01:00 start time, 22:00 time "now" (+18 hrs) -- sub a day
		t = t.AddDate(0, 0, -1)
		return &t
	}
	panic(fmt.Sprintf("unhandled difference %v", difference))
}