func EnvTVmazeCredentials() TVmazeCredentials {
	return TVmazeCredentials{}
}
EnvTVmazeCredentials returns a struct variable which contains credentials for the TVmaze API.
package series
import (
	"fmt"
	"net/url"
	"strconv"
	"time"
	"goirate/movies"
	"goirate/utils"
)
type TVmazeCredentials struct {
}
type TVmazeToken struct {
}
type TVmazeSeries struct {
	ID        int    `json:"id"`
	Name      string `json:"name"`
	Premiered string `json:"premiered"`
}
type apiEndpoint string
const (
	baseEndpoint     apiEndpoint = "https://api.tvmaze.com"
	searchEndpoint   apiEndpoint = baseEndpoint + "/search/shows"
	lookupEndpoint   apiEndpoint = baseEndpoint + "/lookup/shows"
	showEndpoint     apiEndpoint = baseEndpoint + "/shows/%v"
	episodesEndpoint apiEndpoint = baseEndpoint + "/shows/%v/episodes"
)
func (ep apiEndpoint) String() string {
	return string(ep)
}
func (cred *TVmazeCredentials) Login() (TVmazeToken, error) {
	var tkn TVmazeToken
	return tkn, nil
}
func (tkn *TVmazeToken) Search(searchName string) ([]TVmazeSeries, error) {
	var searchResults []TVmazeSeries
	var searchResponse []struct {
		Show TVmazeSeries `json:"show"`
	}
	var searchURL string
	if id, err := strconv.Atoi(searchName); err == nil {
		show, err := tkn.lookupSeriesTVmaze(id)
		return []TVmazeSeries{show}, err
	} else if movies.IsIMDbURL(searchName) {
		imdbID, err := movies.ExtractIMDbID(searchName)
		if err != nil {
			return nil, err
		}
		show, err := tkn.lookupSeriesIMDB(imdbID)
		return []TVmazeSeries{show}, err
	} else if movies.IsIMDbID(searchName) {
		imdbID, err := movies.FormatIMDbID(searchName)
		if err != nil {
			return nil, err
		}
		show, err := tkn.lookupSeriesIMDB(imdbID)
		return []TVmazeSeries{show}, err
	}
	searchURL = fmt.Sprintf("%v?q=%v", searchEndpoint, url.QueryEscape(searchName))
	err := tkn.apiCall(searchURL, &searchResponse)
	if err == nil && len(searchResponse) > 0 {
		for _, show := range searchResponse {
			searchResults = append(searchResults, show.Show)
		}
	}
	if len(searchResponse) == 0 {
		return nil, fmt.Errorf("show not found on TVmaze")
	}
	return searchResults, nil
}
func (tkn *TVmazeToken) SearchFirst(searchName string) (*TVmazeSeries, error) {
	shows, err := tkn.Search(searchName)
	if len(shows) > 0 {
		return &shows[0], err
	}
	return nil, err
}
func (tkn *TVmazeToken) LastEpisode(seriesID int) (Episode, error) {
	var episode Episode
	callback := func(ep Episode) {
		if !ep.HasAired() {
			return
		}
		if ep.IsAfter(episode) {
			episode = ep
		}
	}
	err := tkn.getEpisodes(seriesID, callback)
	return episode, err
}
func (tkn *TVmazeToken) NextEpisode(seriesID int, episode Episode) (nextEpisode Episode, err error) {
	nextSeasonOut := false
	nextSeasonFirst := Episode{Season: episode.Season + 1, Episode: 1}
	seasonHasMore := false
	curSeasonNext := Episode{Season: episode.Season, Episode: episode.Episode + 1}
	callback := func(ep Episode) {
		if ep.Season == episode.Season+1 {
			nextSeasonOut = true
			if ep.Episode == 1 {
				nextSeasonFirst = ep
			}
		}
		if ep.Season == episode.Season && ep.Episode == episode.Episode+1 {
			seasonHasMore = true
			curSeasonNext = ep
		}
	}
	err = tkn.getEpisodes(seriesID, callback)
	if nextSeasonOut && !seasonHasMore {
		nextEpisode = nextSeasonFirst
	} else {
		nextEpisode = curSeasonNext
	}
	return
}
func (tkn *TVmazeToken) lookupSeriesTVmaze(seriesID int) (TVmazeSeries, error) {
	var lookupResponse TVmazeSeries
	searchURL := fmt.Sprintf(string(showEndpoint), seriesID)
	err := tkn.apiCall(searchURL, &lookupResponse)
	return lookupResponse, err
}
func (tkn *TVmazeToken) lookupSeriesIMDB(imdbID string) (TVmazeSeries, error) {
	var lookupResponse TVmazeSeries
	searchURL := fmt.Sprintf("%v?imdb=%v", lookupEndpoint, imdbID)
	err := tkn.apiCall(searchURL, &lookupResponse)
	return lookupResponse, err
}
func (tkn *TVmazeToken) getEpisodes(seriesID int, callback func(Episode)) error {
	var episodeSearchResponse []struct {
		Season  uint   `json:"season"`
		Episode uint   `json:"number"`
		Name    string `json:"name"`
		Airdate string `json:"airdate"`
	}
	episodesURL := fmt.Sprintf(episodesEndpoint.String(), seriesID)
	err := tkn.apiCall(episodesURL, &episodeSearchResponse)
	if err != nil {
		return err
	}
	for _, ep := range episodeSearchResponse {
		var aired *time.Time
		if ep.Airdate != "" {
			tmp, err := time.Parse("2006-01-02", ep.Airdate)
			if err != nil {
				return err
			}
			aired = &tmp
		}
		episode := Episode{
			Season:  ep.Season,
			Episode: ep.Episode,
			Title:   ep.Name,
			Aired:   aired,
		}
		callback(episode)
	}
	return nil
}
func (tkn *TVmazeToken) apiCall(url string, v interface{}) error {
	httpClient := utils.HTTPClient{}
	return httpClient.GetJSON(url, &v)
}