package main

import (
	"encoding/json"
	"github.com/microcosm-cc/bluemonday"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strings"
	"time"
)

var p *bluemonday.Policy
var spaceReg *regexp.Regexp

func GetRunner(endpoint string) (RunningInstance) {
	ri_mutex.Lock()
	o, exists := runninginstances[endpoint]
	if exists == false {
		o := RunningInstance{}

		tr := &http.Transport {MaxIdleConns: 10, IdleConnTimeout: 7200 * time.Second}

		o.client = http.Client{Transport: tr}
		o.Status = KEEPALIVE
		runninginstances[endpoint] = o
	}
	ri_mutex.Unlock()

	return o
}


func UpdateRunner(endpoint string, o RunningInstance) {
	ri_mutex.Lock()
	runninginstances[endpoint] = o
	ri_mutex.Unlock()
}


func GetNodeInfo(endpoint string, o RunningInstance) (RunningInstance) {
	/* Checking order
	 * Mastodon/Pleroma
	 * Um..nothing else yet
	 */
	var nodeinfo NodeInfo
	pleromastodon_nodeinfo_uri := "https://" + endpoint + "/nodeinfo/2.0.json"

	req, _ := http.NewRequest("GET", pleromastodon_nodeinfo_uri, nil)

	pleromastodon_api_resp, err := o.client.Do(req)
	if err != nil {
		return o
	} else {
		defer pleromastodon_api_resp.Body.Close()
	}

	if pleromastodon_api_resp.StatusCode == 200 {
		err = json.NewDecoder(pleromastodon_api_resp.Body).Decode(&nodeinfo)
		if err == nil {
			o.Software = nodeinfo.Software.Name
			o.LastRun = time.Now().Format(time.RFC3339)
			defer pleromastodon_api_resp.Body.Close()
			return o
		}
	}

	// Check the front page
	index_uri := "https://" + endpoint + "/"
	req, _ = http.NewRequest("GET", index_uri, nil)
	resp_index, err := o.client.Do(req)
	o.LastRun = time.Now().Format(time.RFC3339)
	if err != nil {
		o.Status = UNSUPPORTED_INSTANCE
		log.Print("Unable to connect to " + endpoint + ", giving up")
		return o
	}
	defer resp_index.Body.Close()

	indexbin, err := ioutil.ReadAll(resp_index.Body)
	if err != nil {
		o.Status = UNSUPPORTED_INSTANCE
		log.Print("Unable to read index of " + endpoint + ", giving up")
		return o
	}
	indexstr := string(indexbin)

	if strings.Contains(indexstr, "Pleroma") || strings.Contains(indexstr, "Soapbox") {
		log.Print("Manual view: Pleroma" + endpoint)
		o.Software = "pleroma"
		o.Version = "guess"
	} else if strings.Contains(indexstr, "Mastodon") {
		log.Print("Manual view: Mastodon" + endpoint)
		o.Software = "mastodon"
		o.Version = "guess"
	} else if strings.Contains(indexstr, "Gab") {
		log.Print("Manual view: Gab" + endpoint)
		o.Software = "gab"
		o.Version = "guess"
	}

	return o
}

func StartInstance(endpoint string) {
	// Check if exists. If so, get the object. If not, create it
	o := GetRunner(endpoint)

	o = GetNodeInfo(endpoint, o)
	UpdateRunner(endpoint, o)

	if o.Software == "" {
		return
	}

	if o.Software == "pleroma" {
		log.Print("Starting " + endpoint + " as " + o.Software)
		o.CaptureType = "Poll"
		UpdateRunner(endpoint, o)
		PollMastodonPleroma(endpoint, &o)
	} else if o.Software == "mastodon" {
		log.Print("Starting " + endpoint + " as " + o.Software)
		o.CaptureType = "Stream"
		UpdateRunner(endpoint, o)
		StreamMastodon(endpoint, &o)
	}
}