// This is a simple example
package cloudflare

import 	(
	"log"
	"os"
	"bytes"
	"io/ioutil"
	"net/http"

	"go.wit.com/gui"
)

/*
curl --request POST \
  --url https://api.cloudflare.com/client/v4/zones/zone_identifier/dns_records \
  --header 'Content-Type: application/json' \
  --header 'X-Auth-Email: ' \
  --data '{
  "content": "198.51.100.4",
  "name": "example.com",
  "proxied": false,
  "type": "A",
  "comment": "Domain verification record",
  "tags": [
    "owner:dns-team"
  ],
  "ttl": 3600
}'
*/

// CFdialog is everything you need forcreating 
// a new record: name, TTL, type (CNAME, A, etc)
var CFdialog RRT

// Resource Record (used in a DNS zonefile)
type RRT struct {
	cloudflareW *gui.Node	// the window node
	cloudflareB *gui.Node	// the cloudflare button

	TypeNode *gui.Node	// CNAME, A, AAAA, ...
	NameNode *gui.Node	// www, mail, ...
	ValueNode *gui.Node	// 4.2.2.2, "dkim stuff", etc

	proxyNode *gui.Node	// If cloudflare is a port 80 & 443 proxy
	ttlNode *gui.Node	// just set to 1 which means automatic to cloudflare
	curlNode *gui.Node	// shows you what you could run via curl
	resultNode *gui.Node	// what the cloudflare API returned
	saveNode *gui.Node	// button to send it to cloudflare

	zoneNode *gui.Node	// "wit.com"
	zoneIdNode *gui.Node	// cloudflare zone ID
	apiNode *gui.Node	// cloudflare API key (from environment var CF_API_KEY)
	emailNode *gui.Node	// cloudflare email (from environment var CF_API_EMAIL)

	ID     string
	Type   string
	Name   string
	Content string
	ProxyS string
	Proxied bool
	Proxiable bool
	Ttl string
}

func CreateRR(myGui *gui.Node, zone string, zoneID string) {
	if (CFdialog.cloudflareW != nil) {
		// skip this if the window has already been created
		log.Println("createRR() the cloudflare window already exists")
		CFdialog.cloudflareB.Disable()
		return
	}
	CFdialog.cloudflareW = myGui.NewWindow("cloudflare " + zone + " API")
	CFdialog.cloudflareW.Custom = func () {
		log.Println("createRR() don't really exit here")
		CFdialog.cloudflareW = nil
		CFdialog.cloudflareB.Enable()
	}

	CFdialog.ID = zoneID

	group := CFdialog.cloudflareW.NewGroup("Create a new DNS Resource Record (rr)")

	// make a grid 2 things wide
	grid := group.NewGrid("gridnuts", 2, 3)

	grid.NewLabel("zone")
	CFdialog.zoneNode = grid.NewLabel("zone")
	CFdialog.zoneNode.SetText(zone)

	grid.NewLabel("zone ID")
	CFdialog.zoneIdNode = grid.NewLabel("zoneID")
	CFdialog.zoneIdNode.SetText(zoneID)

	grid.NewLabel("shell env $CF_API_EMAIL")
	CFdialog.emailNode = grid.NewLabel("type")
	CFdialog.emailNode.SetText(os.Getenv("CF_API_EMAIL"))

	grid.NewLabel("shell env $CF_API_KEY")
	CFdialog.apiNode = grid.NewLabel("type")
	CFdialog.apiNode.SetText(os.Getenv("CF_API_KEY"))

	grid.NewLabel("Record Type")
	CFdialog.TypeNode = grid.NewCombobox("type")
	CFdialog.TypeNode.AddText("A")
	CFdialog.TypeNode.AddText("AAAA")
	CFdialog.TypeNode.AddText("CNAME")
	CFdialog.TypeNode.AddText("TXT")
	CFdialog.TypeNode.AddText("MX")
	CFdialog.TypeNode.AddText("NS")
	CFdialog.TypeNode.Custom = func () {
		CreateCurlRR()
	}
	CFdialog.TypeNode.SetText("AAAA")

	grid.NewLabel("Name (usually the hostname)")
	CFdialog.NameNode = grid.NewCombobox("name")
	CFdialog.NameNode.AddText("www")
	CFdialog.NameNode.AddText("mail")
	CFdialog.NameNode.AddText("git")
	CFdialog.NameNode.AddText("go")
	CFdialog.NameNode.AddText("blog")
	CFdialog.NameNode.AddText("ns1")
	CFdialog.NameNode.Custom = func () {
		CreateCurlRR()
	}
	CFdialog.NameNode.SetText("www")

	grid.NewLabel("Cloudflare Proxy")
	CFdialog.proxyNode = grid.NewDropdown("proxy")
	CFdialog.proxyNode.AddText("On")
	CFdialog.proxyNode.AddText("Off")
	CFdialog.proxyNode.Custom = func () {
		CreateCurlRR()
	}
	CFdialog.proxyNode.SetText("Off")

	grid.NewLabel("Value")
	CFdialog.ValueNode = grid.NewCombobox("value")
	CFdialog.ValueNode.AddText("127.0.0.1")
	CFdialog.ValueNode.AddText("2001:4860:4860::8888")
	CFdialog.ValueNode.AddText("ipv6.wit.com")
	CFdialog.ValueNode.Custom = func () {
		CreateCurlRR()
	}
	CFdialog.ValueNode.SetText("127.0.0.1")
	CFdialog.ValueNode.Expand()

	group.NewLabel("curl")
	CFdialog.curlNode = group.NewTextbox("curl")
	CFdialog.curlNode.Custom = func () {
		CreateCurlRR()
	}
	CFdialog.curlNode.SetText("put the curl text here")

	CFdialog.resultNode = group.NewTextbox("result")
	CFdialog.resultNode.SetText("API response will show here")

	CFdialog.saveNode = group.NewButton("Save", func () {
		url, data := CreateCurlRR()
		result := curl(url, data)
		CFdialog.resultNode.SetText(result)
	})
	CFdialog.saveNode.Disable()

	group.Pad()
	grid.Pad()
	grid.Expand()
}

func CreateCurlRR() (string, string) {
	// enable the Save/Create Button
	if (CFdialog.saveNode != nil) {
		CFdialog.saveNode.Enable()
	}

	if (CFdialog.TypeNode != nil) {
		CFdialog.Type = CFdialog.TypeNode.S
	}
	if (CFdialog.NameNode != nil) {
		CFdialog.Name = CFdialog.NameNode.S
	}
	if (CFdialog.proxyNode != nil) {
		if (CFdialog.proxyNode.S == "On") {
			CFdialog.ProxyS = "true"
		} else {
			CFdialog.ProxyS = "false"
		}
	}
	if (CFdialog.ValueNode != nil) {
		CFdialog.Content = CFdialog.ValueNode.S
	}
	CFdialog.Ttl = "3600"

	var url string = "https://api.cloudflare.com/client/v4/zones/" + CFdialog.ID + "/dns_records"
	// https://api.cloudflare.com/client/v4/zones/zone_identifier/dns_records \
	// var authKey string = os.Getenv("CF_API_KEY")
	// var email string = os.Getenv("CF_API_EMAIL")

	// make a json record to send on port 80 to cloudflare
	var tmp string
	tmp = `{"content": "` + CFdialog.Content + `", `
	tmp += `"name": "` + CFdialog.Name + `", `
	tmp += `"type": "` + CFdialog.Type + `", `
	tmp += `"ttl": ` +  CFdialog.Ttl + `, `
	tmp += `"proxied": ` +  CFdialog.ProxyS + `, `
	tmp += `"comment": "WIT DNS Control Panel"`
	tmp +=  `}`
	data := []byte(tmp)

	log.Println("http PUT url =", url)
	// log.Println("http PUT data =", data)
	// spew.Dump(data)
	pretty, _ := formatJSON(string(data))
	log.Println("http URL =", url)
	log.Println("http PUT data =", pretty)
	if (CFdialog.curlNode != nil) {
		CFdialog.curlNode.SetText("URL: " + url + "\n" + pretty)
	}

	return url, tmp
}

func curl(url string, tmp string) string {
	var authKey string = CFdialog.apiNode.S
	var email string = CFdialog.emailNode.S

	log.Println("curl() START")
	data := []byte(tmp)
	req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data))

	// Set headers
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Auth-Key", authKey)
	req.Header.Set("X-Auth-Email", email)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Println(err)
		return ""
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return ""
	}
	// log.Println("http PUT body =", body)
	// spew.Dump(body)

	log.Println("result =", string(body))
	log.Println("curl() END")
	pretty, _ := formatJSON(string(body))
	return pretty
}
