// vi:ts=4:sts=4:sw=4:noet:tw=72
//
// flokatirc twitch module
//
// Copyright (c) 2016 Daniel Aberger <da@ixab.de>

package twitch

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"flokatirc/util"

	"github.com/sorcix/irc"
)

type TwitchChannelObject struct {
	_id    int `json:"_id"`
	_links struct {
		Chat          string `json:"chat"`
		Commercial    string `json:"commercial"`
		Editors       string `json:"editors"`
		Features      string `json:"features"`
		Follows       string `json:"follows"`
		Self          string `json:"self"`
		StreamKey     string `json:"stream_key"`
		Subscriptions string `json:"subscriptions"`
		Teams         string `json:"teams"`
		Videos        string `json:"videos"`
	} `json:"_links"`
	Background                   interface{} `json:"background"`
	Banner                       string      `json:"banner"`
	BroadcasterLanguage          string      `json:"broadcaster_language"`
	CreatedAt                    string      `json:"created_at"`
	Delay                        interface{} `json:"delay"`
	DisplayName                  string      `json:"display_name"`
	Followers                    int         `json:"followers"`
	Game                         string      `json:"game"`
	Language                     string      `json:"language"`
	Logo                         string      `json:"logo"`
	Mature                       bool        `json:"mature"`
	Name                         string      `json:"name"`
	Partner                      bool        `json:"partner"`
	ProfileBanner                string      `json:"profile_banner"`
	ProfileBannerBackgroundColor string      `json:"profile_banner_background_color"`
	Status                       string      `json:"status"`
	UpdatedAt                    string      `json:"updated_at"`
	URL                          string      `json:"url"`
	VideoBanner                  string      `json:"video_banner"`
	Views                        int         `json:"views"`
}

type TwitchStreamObject struct {
	_links struct {
		Channel string `json:"channel"`
		Self    string `json:"self"`
	} `json:"_links"`
	Stream struct {
		_id    int `json:"_id"`
		_links struct {
			Self string `json:"self"`
		} `json:"_links"`
		AverageFps float64 `json:"average_fps"`
		Channel    struct {
			_id    int `json:"_id"`
			_links struct {
				Chat          string `json:"chat"`
				Commercial    string `json:"commercial"`
				Editors       string `json:"editors"`
				Features      string `json:"features"`
				Follows       string `json:"follows"`
				Self          string `json:"self"`
				StreamKey     string `json:"stream_key"`
				Subscriptions string `json:"subscriptions"`
				Teams         string `json:"teams"`
				Videos        string `json:"videos"`
			} `json:"_links"`
			Background                   interface{} `json:"background"`
			Banner                       string      `json:"banner"`
			BroadcasterLanguage          string      `json:"broadcaster_language"`
			CreatedAt                    string      `json:"created_at"`
			Delay                        interface{} `json:"delay"`
			DisplayName                  string      `json:"display_name"`
			Followers                    int         `json:"followers"`
			Game                         string      `json:"game"`
			Language                     string      `json:"language"`
			Logo                         string      `json:"logo"`
			Mature                       bool        `json:"mature"`
			Name                         string      `json:"name"`
			Partner                      bool        `json:"partner"`
			ProfileBanner                string      `json:"profile_banner"`
			ProfileBannerBackgroundColor string      `json:"profile_banner_background_color"`
			Status                       string      `json:"status"`
			UpdatedAt                    string      `json:"updated_at"`
			URL                          string      `json:"url"`
			VideoBanner                  string      `json:"video_banner"`
			Views                        int         `json:"views"`
		} `json:"channel"`
		CreatedAt  string `json:"created_at"`
		Delay      int    `json:"delay"`
		Game       string `json:"game"`
		IsPlaylist bool   `json:"is_playlist"`
		Preview    struct {
			Large    string `json:"large"`
			Medium   string `json:"medium"`
			Small    string `json:"small"`
			Template string `json:"template"`
		} `json:"preview"`
		VideoHeight int `json:"video_height"`
		Viewers     int `json:"viewers"`
	} `json:"stream"`
}

var (
	sayCh  chan string
	twitch = map[string]bool{
		"rocketbeanstv": false,
		"scnr_onair":    false,
		"starcitizen":   false,
		"crash_academy": false,
		"cigcommunity":  false,
		"isfa_live":     false,
		"blizzard":      false,
		"ea":            false,
		"warcraft":      false,
		"starcraft":     false,
		"bobross":       false,
	}
	twitchapiurlstreams  = "https://api.twitch.tv/kraken/streams/"
	twitchapiurlchannels = "https://api.twitch.tv/kraken/channels/"
)

func Init(ch chan string) {
	log.Println("Initializing twitch module")
	sayCh = ch
	go pollStreamData()
}

func HandleMessage(m *irc.Message) {
	tok := strings.Split(m.Trailing, " ")
	if len(tok) < 1 {
		return
	}
	switch tok[0] {
	case "!twitch":
		switch len(tok) {
		case 1:
			onlinestreams := 0
			for streamname, _ := range twitch {
				var so TwitchStreamObject
				var co TwitchChannelObject
				so = getTwitchStreamObject(streamname)
				if so.Stream.Game != "" {
					onlinestreams++
					co = getTwitchChannelObject(streamname)
					twitchSendMsg(co, so)
					twitch[streamname] = true
				} else {
					twitch[streamname] = false
				}
			}
			if onlinestreams == 0 {
				sayCh <- fmt.Sprintf("*\n%s", "[TWTCH] All streams offline")
			}
		case 2:
			streamname := tok[1]
			var so TwitchStreamObject
			var co TwitchChannelObject
			so = getTwitchStreamObject(streamname)
			if so.Stream.Game != "" {
				co = getTwitchChannelObject(streamname)
				twitchSendMsg(co, so)
			} else {
				sayCh <- fmt.Sprintf("*\n%s", "[TWTCH] "+streamname+" not found or offline")
			}
		default:
		}
	default:
	}
}

func pollStreamData() {
	time.Sleep(10 * time.Second)
	for {
		for streamname, _ := range twitch {
			var so TwitchStreamObject
			var co TwitchChannelObject
			so = getTwitchStreamObject(streamname)
			if so.Stream.Game != "" && !twitch[streamname] {
				co = getTwitchChannelObject(streamname)
				twitchSendMsg(co, so)
				twitch[streamname] = true
			} else if so.Stream.Game == "" && twitch[streamname] {
				twitch[streamname] = false
			}
		}
		time.Sleep(180 * time.Second)
	}
}

func getTwitchStreamObject(streamname string) TwitchStreamObject {
	twsurl := twitchapiurlstreams + streamname
	var tobj TwitchStreamObject
	resp, err := http.Get(twsurl)
	if err != nil {
		log.Println(err)
	} else {
		reader, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Println(err)
		} else {
			defer resp.Body.Close()
			json.Unmarshal(reader, &tobj)
			return tobj
		}
	}
	return tobj
}

func getTwitchChannelObject(streamname string) TwitchChannelObject {
	twcurl := twitchapiurlchannels + streamname
	var tcobj TwitchChannelObject
	resp2, err := http.Get(twcurl)
	if err != nil {
		log.Println(err)
	} else {
		reader2, err := ioutil.ReadAll(resp2.Body)
		if err != nil {
			log.Println(err)
		} else {
			defer resp2.Body.Close()
			json.Unmarshal(reader2, &tcobj)
			return tcobj
		}
	}
	return tcobj
}

func twitchSendMsg(tcobj TwitchChannelObject, tso TwitchStreamObject) {
	sayCh <- fmt.Sprintf("*\n%s", "[TWTCH] "+tso.Stream.Channel.DisplayName+", "+util.NumberToString(tso.Stream.Viewers, '.')+" viewers, playing: "+tso.Stream.Game+", "+tcobj.URL)
	sayCh <- fmt.Sprintf("*\n%s", "[TWTCH] "+"Title: \""+tcobj.Status+"\"")
}