// Copyright 2018 Serge Bazanski
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Based off github.com/youtube/doorman/blob/master/go/status/status.go

// Copyright 2016 Google, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package statusz

import (
	"bytes"
	"context"
	"crypto/sha256"
	"fmt"
	"html"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"sync"
	"time"

	"github.com/golang/glog"
)

var (
	binaryName  = filepath.Base(os.Args[0])
	binaryHash  string
	hostname    string
	username    string
	serverStart = time.Now()

	lock     sync.Mutex
	sections []section
	tmpl     = template.Must(reparse(nil))
	funcs    = make(template.FuncMap)

	GitCommit      = "unknown"
	GitVersion     = "unknown"
	Builder        = "unknown"
	BuildTimestamp = "0"
	// mirko populates this
	PublicAddress = "#"

	DefaultMux = true
)

type section struct {
	Banner   string
	Fragment string
	F        func() interface{}
}

var statusHTML = `<!DOCTYPE html>
<html>
<head>
<title>Status for {{.BinaryName}}</title>
<style>
body {
background: #fff;
}
h1 {
font-family: sans-serif;
clear: both;
width: 100%;
text-align: center;
font-size: 120%;
padding-top: 0.3em;
padding-bottom: 0.3em;
background: #eeeeff;
margin-top: 1em;
}
.lefthand {
float: left;
width: 80%;
}
.righthand {
text-align: right;
}
</style>
</head>
<h1>Status for {{.BinaryName}}</h1>
<div>
<div class=lefthand>
Started: {{.StartTime}} -- up {{.Up}}<br>
Built on {{.BuildTime}}<br>
Built at {{.Builder}}<br>
Built from git checkout <a href="https://gerrit.hackerspace.pl/plugins/gitiles/hscloud/+/{{.GitCommit}}">{{.GitVersion}}</a><br>
SHA256 {{.BinaryHash}}<br>
</div>
<div class=righthand>
Running as {{.Username}} on <a href="{{.PublicAddress}}">{{.Hostname}}</a><br>
Load {{.LoadAvg}}<br>
View <a href=/debug/status>status</a>,
	<a href=/debug/requests>requests</a>,
	<a href=/debug/pprof>profile</a>
</div>
<div style="clear: both;"> </div>
</div>`

func reparse(sections []section) (*template.Template, error) {
	var buf bytes.Buffer

	io.WriteString(&buf, `{{define "status"}}`)
	io.WriteString(&buf, statusHTML)

	for i, sec := range sections {
		fmt.Fprintf(&buf, "<h1>%s</h1>\n", html.EscapeString(sec.Banner))
		fmt.Fprintf(&buf, "{{$sec := index .Sections %d}}\n", i)
		fmt.Fprintf(&buf, `{{template "sec-%d" call $sec.F}}`+"\n", i)
	}
	fmt.Fprintf(&buf, `</html>`)
	io.WriteString(&buf, "{{end}}\n")

	for i, sec := range sections {
		fmt.Fprintf(&buf, `{{define "sec-%d"}}%s{{end}}\n`, i, sec.Fragment)
	}
	return template.New("").Funcs(funcs).Parse(buf.String())
}

func StatusHandler(w http.ResponseWriter, r *http.Request) {
	lock.Lock()
	defer lock.Unlock()

	buildTime := time.Unix(0, 0)
	if buildTimeNum, err := strconv.Atoi(BuildTimestamp); err == nil {
		buildTime = time.Unix(int64(buildTimeNum), 0)
	}

	data := struct {
		Sections      []section
		BinaryName    string
		BinaryHash    string
		GitVersion    string
		GitCommit     string
		Builder       string
		BuildTime     string
		Hostname      string
		Username      string
		StartTime     string
		Up            string
		LoadAvg       string
		PublicAddress string
	}{
		Sections:      sections,
		BinaryName:    binaryName,
		BinaryHash:    binaryHash,
		GitVersion:    GitVersion,
		GitCommit:     GitCommit,
		Builder:       Builder,
		BuildTime:     fmt.Sprintf("%s (%d)", buildTime.Format(time.RFC1123), buildTime.Unix()),
		Hostname:      hostname,
		Username:      username,
		StartTime:     serverStart.Format(time.RFC1123),
		Up:            time.Since(serverStart).String(),
		LoadAvg:       loadAverage(),
		PublicAddress: PublicAddress,
	}

	if err := tmpl.ExecuteTemplate(w, "status", data); err != nil {
		glog.Errorf("servenv: couldn't execute template: %v", err)
	}
}

func init() {
	var err error
	hostname, err = os.Hostname()
	if err != nil {
		glog.Fatalf("os.Hostname: %v", err)
	}

	user, err := user.Current()
	if err != nil {
		log.Printf("user.Current: %v", err)
		username = "UNKNOWN"
	} else {
		username = fmt.Sprintf("%s (%s)", user.Username, user.Uid)
	}

	exec, err := os.Executable()
	if err == nil {
		f, err := os.Open(exec)
		if err == nil {
			h := sha256.New()
			if _, err := io.Copy(h, f); err != nil {
				glog.Fatalf("io.Copy: %v", err)
			}
			binaryHash = fmt.Sprintf("%x", h.Sum(nil))
		} else {
			glog.Errorf("Could not get SHA256 of binary: os.Open(%q): %v", exec, err)
			binaryHash = "could not read executable"
		}
	} else {
		glog.Errorf("Could not get SHA256 of binary: os.Executable(): %v", err)
		binaryHash = "could not get executable"
	}

	if DefaultMux {
		http.HandleFunc("/debug/status", StatusHandler)
	}
}

// AddStatusPart adds a new section to status. frag is used as a
// subtemplate of the template used to render /debug/status, and will
// be executed using the value of invoking f at the time of the
// /debug/status request. frag is parsed and executed with the
// html/template package. Functions registered with AddStatusFuncs
// may be used in the template.
func AddStatusPart(banner, frag string, f func(context.Context) interface{}) {
	lock.Lock()
	defer lock.Unlock()

	secs := append(sections, section{
		Banner:   banner,
		Fragment: frag,
		F:        func() interface{} { return f(context.Background()) },
	})

	var err error
	tmpl, err = reparse(secs)
	if err != nil {
		secs[len(secs)-1] = section{
			Banner:   banner,
			Fragment: "<code>bad status template: {{.}}</code>",
			F:        func() interface{} { return err },
		}
	}
	tmpl, _ = reparse(secs)
	sections = secs
}

// AddStatusSection registers a function that generates extra
// information for /debug/status. If banner is not empty, it will be
// used as a header before the information. If more complex output
// than a simple string is required use AddStatusPart instead.
func AddStatusSection(banner string, f func(context.Context) string) {
	AddStatusPart(banner, `{{.}}`, func(ctx context.Context) interface{} { return f(ctx) })
}
