package main

import (
//	"crypto/sha1"
	"encoding/json"
	"fmt"
//	"html"
	"io/ioutil"
	"log"
	"net/http"
	"os"
//	"strings"
//	"time"
)

// CreateObject - Used by post web receiver
type CreateObject struct {
	Actor   string   `json:"actor"`
	Cc      []string `json:"cc"`
	Content string   `json:"content"`
	To      []string `json:"to"`
	Type    string   `json:"type"`
}

// RelayBase - The base object used by web receiver
type RelayBase struct {
	Actor string   `json:"actor"`
	Cc    []string `json:"cc"`
	Object    json.RawMessage `json:"Object"`
	ID        string          `json:"id"`
	Published string          `json:"published"`
	To        []string        `json:"to"`
	Type      string          `json:"type"`
}

func hostmeta(w http.ResponseWriter, r *http.Request) {
	fmt.Println("PATH --> ", r.URL.Path)
	host := r.Host
	xml := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><XRD xmlns=\"http://docs.oasis-open.org/ns/xri/xrd-1.0\"><Link rel=\"lrdd\" template=\"https://" + host + "/.well-known/webfinger?resource={uri}\" type=\"application/xrd+xml\" /></XRD>"
	w.Header().Set("Content-Type", "application/xrd+xml")
	fmt.Fprintf(w, xml)
}

func webfinger(w http.ResponseWriter, r *http.Request) {
	fmt.Println("PATH --> ", r.URL.Path)
	host := r.Host

	webfingermap := make(map[string]interface{})
	webfingermap["subject"] = "acct:fedilogue@" + host
	webfingermap["aliases"] = []string{"https://" + host + "/users/fedilogue"}
	link0 := make(map[string]string)
	link0["rel"] = "http://webfinger.net/rel/profile-page"
	link0["type"] = "text/html"
	link0["href"] = "https://" + host + "/users/fedilogue"
	link1 := make(map[string]string)
	link1["rel"] = "self"
	link1["type"] = "application/activity+json"
	link1["href"] = "https://" + host + "/users/fedilogue"
	link2 := make(map[string]string)
	link2["rel"] = "self"
	link2["type"] = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
	link2["href"] = "https://" + host + "/users/fedilogue"
	link3 := make(map[string]string)
	link3["rel"] = "http://ostatus.org/schema/1.0/subscribe"
	link3["template"] = "https://" + host + "/ostatus_subscribe?acct={uri}"

	links := []map[string]string{link0, link1, link2, link3}
	webfingermap["links"] = links

	webfingerbin, err := json.Marshal(webfingermap)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	webfingerstr := string(webfingerbin)

	query := r.URL.Query()
	resourceRaw, exists := query["resource"]

	if exists {
		resource := resourceRaw[0]
		if resource != "acct:fedilogue@"+host {
			fmt.Println("Writes properly but wrong acct")
			w.Header().Set("Content-Type", "application/json; charset=utf-8")
			fmt.Fprintf(w, webfingerstr)
			return
		}
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		fmt.Fprintf(w, webfingerstr)
	} else {
		fmt.Println(query)
		w.WriteHeader(http.StatusNotFound)
		return
	}
}

func inboxHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {

		fmt.Println("PATH --> ", r.URL.Path)

		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			fmt.Println(err)
			return
		}

		var findtype RelayBase
		err = json.Unmarshal(body, &findtype)

		fmt.Println(string(body))

		switch findtype.Type {
		case "Create":
			var createobject CreateObject
			var newpost ReportPost

			err = json.Unmarshal(findtype.Object, &createobject)
			if err != nil {
				return
			}

			newpost.Uri = findtype.ID
			log.Print(newpost.Uri)

		case "Like":
		case "Announcement":
		case "Delete":
		case "Undo":
		default:
			fmt.Println("Others --> " + findtype.Type)
		}
	}
}

func usersFedilogueFollowers(w http.ResponseWriter, r *http.Request) {
	fmt.Println("PATH --> ", r.URL.Path)
	host := r.Host
	contextlist := map[string]string{"@language": "und"}

	context := []interface{}{"https://www.w3.org/ns/activitystreams", "https://" + host + "/schemas/litepub-0.1.jsonld", contextlist}
	followersmap := make(map[string]interface{})
	followersmap["@context"] = context

	staticjson := "{\"@context\":[\"https://www.w3.org/ns/activitystreams\",\"https://" + host + "/schemas/litepub-0.1.jsonld\",{\"@language\":\"und\"}],\"first\":{\"id\":\"https://" + host + "/users/fedilogue/followers?page=1\",\"next\":\"https://" + host + "/users/fedilogue/followers?page=2\",\"orderedItems\":[\"https://mastodon.host/users/federationbot\"],\"partOf\":\"https://" + host + "/users/fedilogue/followers\",\"totalItems\":1,\"type\":\"OrderedCollectionPage\"},\"id\":\"https://" + host + "/users/fedilogue/followers\",\"totalItems\":1,\"type\":\"OrderedCollection\"}"

	w.Header().Set("Content-Type", "application/activity+json; charset=utf-8")
	fmt.Fprintf(w, staticjson)
}

func usersFedilogueFollowing(w http.ResponseWriter, r *http.Request) {
	host := r.Host
	fmt.Println("PATH --> ", r.URL.Path)
	staticjson := "{\"@context\": [\"https://www.w3.org/ns/activitystreams\", \"https://" + host + "/schemas/litepub-0.1.jsonld\", {\"@language\": \"und\"}], \"first\": {\"id\": \"https://" + host + "/users/fedilogue/following?page=1\", \"orderedItems\": [], \"partOf\": \"https://" + host + "/users/fedilogue/following\", \"totalItems\": 0, \"type\": \"OrderedCollectionPage\"}, \"id\": \"https://" + host + "/users/fedilogue/following\", \"totalItems\": 0, \"type\": \"OrderedCollection\"}"
	w.Header().Set("Content-Type", "application/activity+json; charset=utf-8")
	fmt.Fprintf(w, staticjson)
}

func usersFedilogue(w http.ResponseWriter, r *http.Request) {
	fmt.Println("PATH --> ", r.URL.Path)
	host := r.Host

	fmt.Println(r.Host)
	fmt.Println(r.Header["Accept"])

	publickeybin, err := ioutil.ReadFile("keys/public.pem")
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	publickeypemstr := string(publickeybin)

	publicKey := map[string]string{"id": "https://" + host + "/users/fedilogue#main-key", "owner": "https://" + host + "/users/fedilogue", "publicKeyPem": publickeypemstr}

	capabilities := map[string]bool{}
	tag := []string{}
	contextlist := map[string]string{"@language": "und"}
	attachment := []string{}
	endpoints := map[string]string{"oauthAuthorizationEndpoint": "https://" + host + "/oauth/authorize", "oauthRegistrationEndpoint": "https://" + host + "/api/v1/apps", "oauthTokenEndpoint": "https://" + host + "/oauth/token", "sharedInbox": "https://" + host + "/inbox", "uploadMedia": "https://" + host + "/api/ap/upload_media"}

	context := []interface{}{"https://www.w3.org/ns/activitystreams", "https://" + host + "/schemas/litepub-0.1.jsonld", contextlist}
	userjsonmap := make(map[string]interface{})
	userjsonmap["@context"] = context
	userjsonmap["attachment"] = attachment
	userjsonmap["capabilities"] = capabilities
	userjsonmap["discoverable"] = false
	userjsonmap["endpoints"] = endpoints
	userjsonmap["followers"] = "https://" + host + "/users/fedilogue/followers"
	userjsonmap["following"] = "https://" + host + "/users/fedilogue/following"
	userjsonmap["id"] = "https://" + host + "/users/fedilogue"
	userjsonmap["inbox"] = "https://" + host + "/users/fedilogue/inbox"
	userjsonmap["manuallyApprovesFollowers"] = false
	userjsonmap["name"] = "Fedilogue Mass Follower"
	userjsonmap["outbox"] = "https://" + host + "/users/fedilogue/outbox"
	userjsonmap["preferredUsername"] = "fedilogue"
	userjsonmap["publicKey"] = publicKey
	userjsonmap["summary"] = ""
	userjsonmap["tag"] = tag
	userjsonmap["type"] = "Person"
	userjsonmap["uri"] = "https://" + host + "/users/fedilogue"

	userjsonbin, err := json.Marshal(userjsonmap)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	userjsonstr := string(userjsonbin)
	w.Header().Set("Content-Type", "application/activity+json; charset=utf-8")
	fmt.Fprintf(w, userjsonstr)
}

func errorHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("404 --> ", r.URL.Path)
}

func webmain() {
	http.HandleFunc("/.well-known/webfinger", webfinger)
	http.HandleFunc("/.well-known/host-meta", hostmeta)
	http.HandleFunc("/inbox", inboxHandler())
	http.HandleFunc("/users/fedilogue", usersFedilogue)
	http.HandleFunc("/users/fedilogue/followers", usersFedilogueFollowers)
	http.HandleFunc("/users/fedilogue/following", usersFedilogueFollowing)
	http.HandleFunc("/", errorHandler)
	log.Print("Starting HTTP inbox on port 8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}