// vim:ts=4:sts=4:sw=4:noet:tw=72
package sc
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"time"
	"flokatirc/util"
	"github.com/sorcix/irc"
)
const (
	API_URL       = "https://robertsspaceindustries.com/api"
	API_METHOD    = "/stats/getCrowdfundStats"
	QUERY_CIT_URL = "https://robertsspaceindustries.com/citizens/"
	QUERY_ORG_URL = "https://robertsspaceindustries.com/orgs/"
	RE_CIT_NAME   = `
\s*
\s*(.*)\s*
\s*
`
	RE_CIT_RECORD = `
\s*UEE Citizen Record\s*#(.*)`
	RE_CIT_HANDLE = `
\s*Handle name\s*(.*)\s*
`
	RE_CIT_ORG    = `
(.*)`
	RE_CIT_SID    = `Spectrum Identification \(SID\)\s*
([A-Z0-9]*)`
	RE_CIT_RANK   = `Organization rank\s*
(.*)`
	RE_ORG_NAME   = `
(.*) ?/ ?`
	RE_ORG_COUNT  = `(.*) member`
	RE_ORG_MODEL  = `(.*)`
	RE_ORG_FOCUS  = `\s*- \s*
\s*\s* \s*- \s*
\s*\s* \s*
`
	RE_ORG_COMM   = `(.*)`
	FANS_INT      = 1000
	FLEET_INT     = 1000
	FUNDS_INT     = 10000
)
var (
	sayCh chan string
	fans  = 0
	fleet = 0
	funds = 0
)
func Init(ch chan string) {
	log.Println("Initializing sc module")
	sayCh = ch
	go scrapeLoop()
}
func HandleMessage(m *irc.Message) {
	tok := strings.Split(m.Trailing, " ")
	if len(tok) < 1 {
		return
	}
	switch tok[0] {
	case "!scstats":
		showScStats()
	case "!cit":
		if len(tok) > 1 {
			showCitizen(tok[1])
		}
	case "!org":
		if len(tok) > 1 {
			showOrganization(tok[1])
		}
	default:
	}
}
func toInt(v interface{}) int {
	switch v.(type) {
	case int:
		return v.(int)
	case float64:
		return int(v.(float64))
	case string:
		ret, _ := strconv.Atoi(v.(string))
		return ret
	default:
		return 0
	}
}
func scrapeLoop() {
	for {
		scraper()
		time.Sleep(1 * time.Minute)
	}
}
func scraper() {
	var data interface{}
	log.Println("Scraping SC stats")
	resp, err := http.PostForm(API_URL+API_METHOD,
		url.Values{"fans": {"true"}, "fleet": {"true"}, "funds": {"true"}})
	if err != nil {
		log.Printf("Error: %v", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Error: %v", err)
		return
	}
	err = json.Unmarshal(body, &data)
	if err != nil {
		log.Printf("Error: %v", err)
		return
	}
	stats := data.(map[string]interface{})["data"].(map[string]interface{})
	//fmt.Println(stats["fans"].(type))
	curFans := toInt(stats["fans"])
	curFleet := toInt(stats["fleet"])
	curFunds := toInt(stats["funds"]) / 100
	nextFans := ((fans / FANS_INT) * FANS_INT) + FANS_INT
	nextFleet := ((fleet / FLEET_INT) * FLEET_INT) + FLEET_INT
	nextFunds := ((funds / FUNDS_INT) * FUNDS_INT) + FUNDS_INT
	if curFans >= nextFans {
		sayCh <- "*\n*** [SC] Star Citizens: " + util.NumberToString(curFans, '.')
	}
	if curFleet >= nextFleet {
		sayCh <- "*\n*** [SC] The UEE Fleet: " + util.NumberToString(curFleet, '.')
	}
	if curFunds >= nextFunds {
		sayCh <- "*\n*** [SC] Funds raised: " + util.NumberToString(curFunds, '.')
	}
	fans = curFans
	fleet = curFleet
	funds = curFunds
}
func showScStats() {
	sayCh <- "*\n*** SC User and Funding Stats ###"
	sayCh <- fmt.Sprintf("*\nFans: %s", util.NumberToString(fans, '.'))
	sayCh <- fmt.Sprintf("*\nFleet: %s", util.NumberToString(fleet, '.'))
	sayCh <- fmt.Sprintf("*\nFunds: $ %s", util.NumberToString(funds, '.'))
}
func showCitizen(handle string) {
	resp, err := http.Get(QUERY_CIT_URL + handle)
	if err != nil {
		log.Printf("Error: %v", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Error: %v", err)
		return
	}
	reName := regexp.MustCompile(RE_CIT_NAME)
	reRecord := regexp.MustCompile(RE_CIT_RECORD)
	reHandle := regexp.MustCompile(RE_CIT_HANDLE)
	reOrg := regexp.MustCompile(RE_CIT_ORG)
	reSid := regexp.MustCompile(RE_CIT_SID)
	reRank := regexp.MustCompile(RE_CIT_RANK)
	name := reName.FindStringSubmatch(string(body))
	record := reRecord.FindStringSubmatch(string(body))
	handle_ := reHandle.FindStringSubmatch(string(body))
	org := reOrg.FindStringSubmatch(string(body))
	sid := reSid.FindStringSubmatch(string(body))
	rank := reRank.FindStringSubmatch(string(body))
	if len(name) > 1 {
		sayCh <- "*\n*** Citizen Info ***"
		sayCh <- "*\n" + "Name: " + string(name[1]) + " [" + string(handle_[1]) + "]"
		sayCh <- "*\n" + "URL: " + QUERY_CIT_URL + string(handle_[1])
		sayCh <- "*\n" + "UEE #: " + string(record[1])
		if len(org) > 1 {
			sayCh <- "*\n" + "Organization: " + string(org[1]) + " [" + string(sid[1]) + "]"
			sayCh <- "*\n" + "Rank: " + string(rank[1])
		} else {
			sayCh <- "*\n" + "Organization: "
		}
	} else {
		sayCh <- "*\n" + "*** No Such Citizen ***"
	}
}
func showOrganization(handle string) {
	resp, err := http.Get(QUERY_ORG_URL + handle)
	if err != nil {
		log.Printf("Error: %v", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Error: %v", err)
		return
	}
	reName := regexp.MustCompile(RE_ORG_NAME)
	reCount := regexp.MustCompile(RE_ORG_COUNT)
	reModel := regexp.MustCompile(RE_ORG_MODEL)
	reFocus := regexp.MustCompile(RE_ORG_FOCUS)
	reComm := regexp.MustCompile(RE_ORG_COMM)
	name := reName.FindStringSubmatch(string(body))
	count := reCount.FindStringSubmatch(string(body))
	model := reModel.FindStringSubmatch(string(body))
	focus := reFocus.FindStringSubmatch(string(body))
	comm := reComm.FindStringSubmatch(string(body))
	if len(name) > 1 {
		sayCh <- "*\n*** Organization Info ***"
		sayCh <- "*\nName: " + string(name[1]) + " [" + strings.ToUpper(handle) + "]"
		sayCh <- "*\nURL: " + QUERY_ORG_URL + strings.ToUpper(handle)
		sayCh <- "*\nMembers: " + string(count[1])
		sayCh <- "*\nModel: " + string(model[1])
		sayCh <- "*\nCommitment: " + string(comm[1])
		sayCh <- "*\nFocus: " + string(focus[1]) + ", " + string(focus[2])
	} else {
		sayCh <- "*\n*** No Such Organization ***"
	}
}