From 3f57b28d4512f839d57778f1be781556976158aa Mon Sep 17 00:00:00 2001
From: Janne Mareike Koschinski <janne@kuschku.de>
Date: Fri, 26 Apr 2019 20:32:12 +0200
Subject: [PATCH] Implemented API Client

---
 client.go                 | 152 ++++++++++++++++++++++++++++++++++++++
 external_coachsequence.go |   4 +-
 external_station.go       |   2 +-
 external_timetable.go     |  42 +++++------
 types_util.go             |  60 +++++++--------
 5 files changed, 206 insertions(+), 54 deletions(-)
 create mode 100644 client.go

diff --git a/client.go b/client.go
new file mode 100644
index 0000000..7c23082
--- /dev/null
+++ b/client.go
@@ -0,0 +1,152 @@
+package bahn
+
+import (
+	"fmt"
+	"net/http"
+	"time"
+)
+
+type ApiClient struct {
+	IrisBaseUrl          string
+	CoachSequenceBaseUrl string
+	netClient            *http.Client
+}
+
+func (c *ApiClient) Station(evaId int64) ([]Station, error) {
+	var err error
+
+	url := fmt.Sprintf("%s/timetable/station/%d", c.IrisBaseUrl, evaId)
+
+	var stations []Station
+
+	var response *http.Response
+	if response, err = c.netClient.Get(url); err != nil {
+		return stations, err
+	}
+
+	if stations, err = StationsFromReader(response.Body); err != nil {
+		return stations, err
+	}
+
+	if err = response.Body.Close(); err != nil {
+		return stations, err
+	}
+
+	return stations, err
+}
+
+func (c *ApiClient) Timetable(evaId int64, date time.Time) (Timetable, error) {
+	var err error
+
+	BahnFormat := "060102/15"
+	url := fmt.Sprintf("%s/timetable/plan/%d/%s", c.IrisBaseUrl, evaId, date.Format(BahnFormat))
+
+	var timetable Timetable
+
+	var response *http.Response
+	if response, err = c.netClient.Get(url); err != nil {
+		return timetable, err
+	}
+
+	if timetable, err = TimetableFromReader(response.Body); err != nil {
+		return timetable, err
+	}
+
+	if err = response.Body.Close(); err != nil {
+		return timetable, err
+	}
+
+	return timetable, err
+}
+
+func (c *ApiClient) RealtimeAll(evaId int64, date time.Time) (Timetable, error) {
+	var err error
+
+	url := fmt.Sprintf("%s/timetable/fchg/%d", c.IrisBaseUrl, evaId)
+
+	var timetable Timetable
+
+	var response *http.Response
+	if response, err = c.netClient.Get(url); err != nil {
+		return timetable, err
+	}
+
+	if timetable, err = TimetableFromReader(response.Body); err != nil {
+		return timetable, err
+	}
+
+	if err = response.Body.Close(); err != nil {
+		return timetable, err
+	}
+
+	return timetable, err
+}
+
+func (c *ApiClient) RealtimeRecent(evaId int64, date time.Time) (Timetable, error) {
+	var err error
+
+	url := fmt.Sprintf("%s/timetable/rchg/%d", c.IrisBaseUrl, evaId)
+
+	var timetable Timetable
+
+	var response *http.Response
+	if response, err = c.netClient.Get(url); err != nil {
+		return timetable, err
+	}
+
+	if timetable, err = TimetableFromReader(response.Body); err != nil {
+		return timetable, err
+	}
+
+	if err = response.Body.Close(); err != nil {
+		return timetable, err
+	}
+
+	return timetable, err
+}
+
+func (c *ApiClient) WingDefinition(parent string, wing string) (WingDefinition, error) {
+	var err error
+
+	url := fmt.Sprintf("%s/timetable/wingdef/%s/%s", c.IrisBaseUrl, parent, wing)
+
+	var wingDefinition WingDefinition
+
+	var response *http.Response
+	if response, err = c.netClient.Get(url); err != nil {
+		return wingDefinition, err
+	}
+
+	if wingDefinition, err = WingDefinitionFromReader(response.Body); err != nil {
+		return wingDefinition, err
+	}
+
+	if err = response.Body.Close(); err != nil {
+		return wingDefinition, err
+	}
+
+	return wingDefinition, err
+}
+
+func (c *ApiClient) CoachSequence(line string, date time.Time) (CoachSequence, error) {
+	var err error
+
+	url := fmt.Sprintf("%s/%s/%s", c.CoachSequenceBaseUrl, line, date.Format(TimeLayoutShort))
+
+	var coachSequence CoachSequence
+
+	var response *http.Response
+	if response, err = c.netClient.Get(url); err != nil {
+		return coachSequence, err
+	}
+
+	if coachSequence, err = CoachSequenceFromReader(response.Body); err != nil {
+		return coachSequence, err
+	}
+
+	if err = response.Body.Close(); err != nil {
+		return coachSequence, err
+	}
+
+	return coachSequence, err
+}
diff --git a/external_coachsequence.go b/external_coachsequence.go
index 36c134e..ce3feb3 100644
--- a/external_coachsequence.go
+++ b/external_coachsequence.go
@@ -117,8 +117,8 @@ func parseCoachSequenceFormation(data rawCoachSequenceFormation) CoachSequenceFo
 }
 
 type rawCoachSequenceStop struct {
-	Departure        mediumBahnTime                    `json:"abfahrtszeit"`
-	Arrival          mediumBahnTime                    `json:"ankunftszeit"`
+	Departure        timeMedium                        `json:"abfahrtszeit"`
+	Arrival          timeMedium                        `json:"ankunftszeit"`
 	Station          string                            `json:"bahnhofsname"`
 	EvaId            string                            `json:"evanummer"`
 	Platform         string                            `json:"gleisbezeichnung"`
diff --git a/external_station.go b/external_station.go
index 955c895..1cba05b 100644
--- a/external_station.go
+++ b/external_station.go
@@ -41,7 +41,7 @@ type rawStation struct {
 	EvaId       string          `xml:"eva,attr,omitempty"`
 	StationCode string          `xml:"ds100,attr,omitempty"`
 	Db          bool            `xml:"db,attr,omitempty"`
-	CreatedAt   *bahnTime       `xml:"creationts,attr,omitempty"`
+	CreatedAt   *timeLong       `xml:"creationts,attr,omitempty"`
 }
 
 func parseStation(data rawStation) Station {
diff --git a/external_timetable.go b/external_timetable.go
index fb354ae..e12fa1e 100644
--- a/external_timetable.go
+++ b/external_timetable.go
@@ -42,14 +42,14 @@ func parseTimetable(data rawTimetable) Timetable {
 type rawMessage struct {
 	MessageId           string                  `xml:"id,attr,omitempty"`
 	Type                rawMessageType          `xml:"t,attr,omitempty"`
-	From                *shortBahnTime          `xml:"from,attr,omitempty"`
-	To                  *shortBahnTime          `xml:"to,attr,omitempty"`
+	From                *timeShort              `xml:"from,attr,omitempty"`
+	To                  *timeShort              `xml:"to,attr,omitempty"`
 	Code                *int                    `xml:"c,attr,omitempty"`
 	InternalText        string                  `xml:"int,attr,omitempty"`
 	ExternalText        string                  `xml:"ext,attr,omitempty"`
 	Category            string                  `xml:"cat,attr,omitempty"`
 	ExternalCategory    string                  `xml:"ec,attr,omitempty"`
-	Timestamp           *shortBahnTime          `xml:"ts,attr,omitempty"`
+	Timestamp           *timeShort              `xml:"ts,attr,omitempty"`
 	Priority            rawPriority             `xml:"pr,attr,omitempty"`
 	Owner               string                  `xml:"o,attr,omitempty"`
 	ExternalLink        string                  `xml:"elnk,attr,omitempty"`
@@ -188,7 +188,7 @@ type rawDistributorMessage struct {
 	DistributorType rawDistributorType `xml:"t,attr,omitempty"`
 	DistributorName string             `xml:"n,attr,omitempty"`
 	InternalText    string             `xml:"int,attr,omitempty"`
-	Timestamp       *shortBahnTime     `xml:"ts,attr,omitempty"`
+	Timestamp       *timeShort         `xml:"ts,attr,omitempty"`
 }
 
 func parseDistributorMessages(data []rawDistributorMessage) []DistributorMessage {
@@ -260,13 +260,13 @@ func parseTimetableStop(data rawTimetableStop) TimetableStop {
 }
 
 type rawTripLabel struct {
-	Messages     []rawMessage   `xml:"m,omitempty"`
-	CreatedAt    *shortBahnTime `xml:"ct,attr"`
-	FilterFlag   rawFilterFlag  `xml:"f,attr,omitempty"`
-	TripType     rawTripType    `xml:"t,attr,omitempty"`
-	Owner        string         `xml:"o,attr,omitempty"`
-	TripCategory string         `xml:"c,attr,omitempty"`
-	TripNumber   string         `xml:"n,attr,omitempty"`
+	Messages     []rawMessage  `xml:"m,omitempty"`
+	CreatedAt    *timeShort    `xml:"ct,attr"`
+	FilterFlag   rawFilterFlag `xml:"f,attr,omitempty"`
+	TripType     rawTripType   `xml:"t,attr,omitempty"`
+	Owner        string        `xml:"o,attr,omitempty"`
+	TripCategory string        `xml:"c,attr,omitempty"`
+	TripNumber   string        `xml:"n,attr,omitempty"`
 }
 
 func parseTripLabel(data rawTripLabel) TripLabel {
@@ -344,9 +344,9 @@ func parseTripType(data rawTripType) TripType {
 }
 
 type rawHistoricDelay struct {
-	Timestamp *shortBahnTime `xml:"ts,attr"`
-	Arrival   *shortBahnTime `xml:"ar,attr"`
-	Departure *shortBahnTime `xml:"dp,attr"`
+	Timestamp *timeShort     `xml:"ts,attr"`
+	Arrival   *timeShort     `xml:"ar,attr"`
+	Departure *timeShort     `xml:"dp,attr"`
 	Source    rawDelaySource `xml:"src,attr"`
 	Code      string         `xml:"cod,attr"`
 }
@@ -407,10 +407,10 @@ func parseDelaySource(data rawDelaySource) DelaySource {
 }
 
 type rawHistoricPlatformChange struct {
-	Timestamp         *shortBahnTime `xml:"ts,attr,omitempty"`
-	ArrivalPlatform   string         `xml:"ar,attr,omitempty"`
-	DeparturePlatform string         `xml:"dp,attr,omitempty"`
-	Cause             string         `xml:"cot,attr,omitempty"`
+	Timestamp         *timeShort `xml:"ts,attr,omitempty"`
+	ArrivalPlatform   string     `xml:"ar,attr,omitempty"`
+	DeparturePlatform string     `xml:"dp,attr,omitempty"`
+	Cause             string     `xml:"cot,attr,omitempty"`
 }
 
 func parseHistoricPlatformChanges(data []rawHistoricPlatformChange) []HistoricPlatformChange {
@@ -432,7 +432,7 @@ func parseHistoricPlatformChange(data rawHistoricPlatformChange) HistoricPlatfor
 
 type rawConnection struct {
 	ConnectionId     string              `xml:"id,attr,omitempty"`
-	Timestamp        *shortBahnTime      `xml:"ts,attr,omitempty"`
+	Timestamp        *timeShort          `xml:"ts,attr,omitempty"`
 	EvaId            int64               `xml:"eva,attr,omitempty"`
 	ConnectionStatus rawConnectionStatus `xml:"cs,attr,omitempty"`
 	Ref              *rawTimetableStop   `xml:"ref,omitempty"`
@@ -520,11 +520,11 @@ type rawEvent struct {
 	Messages []rawMessage `xml:"m,omitempty"`
 
 	PlannedPlatform    string          `xml:"pp,attr,omitempty"`
-	PlannedTime        *shortBahnTime  `xml:"pt,attr,omitempty"`
+	PlannedTime        *timeShort      `xml:"pt,attr,omitempty"`
 	PlannedPath        *bahnStringList `xml:"ppth,attr,omitempty"`
 	PlannedDestination string          `xml:"pde,attr,omitempty"`
 	ChangedPlatform    string          `xml:"cp,attr,omitempty"`
-	ChangedTime        *shortBahnTime  `xml:"ct,attr"`
+	ChangedTime        *timeShort      `xml:"ct,attr"`
 	ChangedPath        *bahnStringList `xml:"cpth,attr,omitempty"`
 	ChangedDestination string          `xml:"cde,attr,omitempty"`
 	PlannedStatus      rawEventStatus  `xml:"ps,attr,omitempty"`
diff --git a/types_util.go b/types_util.go
index 4482d05..ba55d62 100644
--- a/types_util.go
+++ b/types_util.go
@@ -33,26 +33,26 @@ func (s *bahnStringList) Value() []string {
 	}
 }
 
-type bahnTime struct {
+type timeLong struct {
 	time.Time
 }
 
-const bahnTimeLayout = "06-01-02 15:04:05.999"
+const TimeLayoutLong = "06-01-02 15:04:05.999"
 
-func (t *bahnTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
+func (t *timeLong) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
 	if t == nil || t.IsZero() {
 		return xml.Attr{}, nil
 	} else {
 		return xml.Attr{
 			Name:  name,
-			Value: t.Format(bahnTimeLayout),
+			Value: t.Format(TimeLayoutLong),
 		}, nil
 	}
 }
 
-func (t *bahnTime) UnmarshalXMLAttr(attr xml.Attr) error {
+func (t *timeLong) UnmarshalXMLAttr(attr xml.Attr) error {
 	if attr.Value != "" {
-		value, err := time.Parse(bahnTimeLayout, attr.Value)
+		value, err := time.Parse(TimeLayoutLong, attr.Value)
 		if err != nil {
 			return err
 		}
@@ -61,7 +61,7 @@ func (t *bahnTime) UnmarshalXMLAttr(attr xml.Attr) error {
 	return nil
 }
 
-func (t *bahnTime) Value() *time.Time {
+func (t *timeLong) Value() *time.Time {
 	if t != nil {
 		return &t.Time
 	} else {
@@ -69,26 +69,26 @@ func (t *bahnTime) Value() *time.Time {
 	}
 }
 
-type shortBahnTime struct {
+type timeShort struct {
 	time.Time
 }
 
-const shortBahnTimeLayout = "0601021504"
+const TimeLayoutShort = "0601021504"
 
-func (t *shortBahnTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
+func (t *timeShort) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
 	if t == nil || t.IsZero() {
 		return xml.Attr{}, nil
 	} else {
 		return xml.Attr{
 			Name:  name,
-			Value: t.Format(shortBahnTimeLayout),
+			Value: t.Format(TimeLayoutShort),
 		}, nil
 	}
 }
 
-func (t *shortBahnTime) UnmarshalXMLAttr(attr xml.Attr) error {
+func (t *timeShort) UnmarshalXMLAttr(attr xml.Attr) error {
 	if attr.Value != "" {
-		value, err := time.Parse(shortBahnTimeLayout, attr.Value)
+		value, err := time.Parse(TimeLayoutShort, attr.Value)
 		if err != nil {
 			return err
 		}
@@ -97,7 +97,7 @@ func (t *shortBahnTime) UnmarshalXMLAttr(attr xml.Attr) error {
 	return nil
 }
 
-func (t *shortBahnTime) Value() *time.Time {
+func (t *timeShort) Value() *time.Time {
 	if t != nil {
 		return &t.Time
 	} else {
@@ -105,26 +105,26 @@ func (t *shortBahnTime) Value() *time.Time {
 	}
 }
 
-type mediumBahnTime struct {
+type timeMedium struct {
 	time.Time
 }
 
-const mediumBahnTimeLayout = "2006-01-02T15:04:05"
+const TimeLayoutMedium = "2006-01-02T15:04:05"
 
-func (t *mediumBahnTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
+func (t *timeMedium) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
 	if t == nil || t.IsZero() {
 		return xml.Attr{}, nil
 	} else {
 		return xml.Attr{
 			Name:  name,
-			Value: t.Format(mediumBahnTimeLayout),
+			Value: t.Format(TimeLayoutMedium),
 		}, nil
 	}
 }
 
-func (t *mediumBahnTime) UnmarshalXMLAttr(attr xml.Attr) error {
+func (t *timeMedium) UnmarshalXMLAttr(attr xml.Attr) error {
 	if attr.Value != "" {
-		value, err := time.Parse(mediumBahnTimeLayout, attr.Value)
+		value, err := time.Parse(TimeLayoutMedium, attr.Value)
 		if err != nil {
 			return err
 		}
@@ -133,17 +133,17 @@ func (t *mediumBahnTime) UnmarshalXMLAttr(attr xml.Attr) error {
 	return nil
 }
 
-func (t *mediumBahnTime) MarshalJSON() ([]byte, error) {
+func (t *timeMedium) MarshalJSON() ([]byte, error) {
 	var text string
 	if t == nil || t.IsZero() {
 		text = ""
 	} else {
-		text = t.Format(mediumBahnTimeLayout)
+		text = t.Format(TimeLayoutMedium)
 	}
 	return json.Marshal(&text)
 }
 
-func (t *mediumBahnTime) UnmarshalJSON(data []byte) error {
+func (t *timeMedium) UnmarshalJSON(data []byte) error {
 	var err error
 
 	var text string
@@ -153,7 +153,7 @@ func (t *mediumBahnTime) UnmarshalJSON(data []byte) error {
 
 	if text != "" {
 		var value time.Time
-		if value, err = time.Parse(mediumBahnTimeLayout, text); err != nil {
+		if value, err = time.Parse(TimeLayoutMedium, text); err != nil {
 			return err
 		}
 		t.Time = value
@@ -161,7 +161,7 @@ func (t *mediumBahnTime) UnmarshalJSON(data []byte) error {
 	return nil
 }
 
-func (t *mediumBahnTime) Value() *time.Time {
+func (t *timeMedium) Value() *time.Time {
 	if t != nil {
 		return &t.Time
 	} else {
@@ -173,7 +173,7 @@ type bahnDate struct {
 	time.Time
 }
 
-const bahnDateLayout = "2006-01-02"
+const DateLayoutLong = "2006-01-02"
 
 func (t *bahnDate) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
 	if t == nil || t.IsZero() {
@@ -181,14 +181,14 @@ func (t *bahnDate) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
 	} else {
 		return xml.Attr{
 			Name:  name,
-			Value: t.Format(bahnDateLayout),
+			Value: t.Format(DateLayoutLong),
 		}, nil
 	}
 }
 
 func (t *bahnDate) UnmarshalXMLAttr(attr xml.Attr) error {
 	if attr.Value != "" {
-		value, err := time.Parse(bahnDateLayout, attr.Value)
+		value, err := time.Parse(DateLayoutLong, attr.Value)
 		if err != nil {
 			return err
 		}
@@ -202,7 +202,7 @@ func (t *bahnDate) MarshalJSON() ([]byte, error) {
 	if t == nil || t.IsZero() {
 		text = ""
 	} else {
-		text = t.Format(bahnDateLayout)
+		text = t.Format(DateLayoutLong)
 	}
 	return json.Marshal(&text)
 }
@@ -217,7 +217,7 @@ func (t *bahnDate) UnmarshalJSON(data []byte) error {
 
 	if text != "" {
 		var value time.Time
-		if value, err = time.Parse(bahnDateLayout, text); err != nil {
+		if value, err = time.Parse(DateLayoutLong, text); err != nil {
 			return err
 		}
 		t.Time = value
-- 
GitLab