package main

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"sync"
	"time"

	"github.com/boltdb/bolt"
	oidc "github.com/coreos/go-oidc"
	"github.com/golang/glog"
	"github.com/gorilla/sessions"
	"golang.org/x/oauth2"
)

var (
	flagSOAPAddress       string
	flagSOAPUsername      string
	flagSOAPPassword      string
	flagListen            string
	flagSecret            string
	flagOAuthClientID     string
	flagOAuthClientSecret string
	flagOAuthRedirectURL  string
	flagDB                string
	flagMOTD              string
)

func init() {
	flag.Set("logtostderr", "true")
}

func main() {
	flag.StringVar(&flagSOAPAddress, "soap_address", "http://127.0.0.1:7878", "Address of AC SOAP server")
	flag.StringVar(&flagSOAPUsername, "soap_username", "test1", "SOAP username")
	flag.StringVar(&flagSOAPPassword, "soap_password", "", "SOAP password")
	flag.StringVar(&flagListen, "listen", "127.0.0.1:8080", "HTTP listen address")
	flag.StringVar(&flagSecret, "secret", "", "Cookie secret")
	flag.StringVar(&flagOAuthClientID, "oauth_client_id", "", "OAuth client ID")
	flag.StringVar(&flagOAuthClientSecret, "oauth_client_secret", "", "OAuth client secret")
	flag.StringVar(&flagOAuthRedirectURL, "oauth_redirect_url", "", "OAuth redirect URL")
	flag.StringVar(&flagDB, "db", "db.db", "Path to database")
	flag.StringVar(&flagMOTD, "motd", "", "Path to MOTD")
	flag.Parse()

	if flagSecret == "" {
		glog.Exitf("-secret must be set")
	}

	var err error
	var motd []byte
	if flagMOTD == "" {
		glog.Warningf("no MOTD defined, set -motd to get one")
	} else {
		motd, err = ioutil.ReadFile(flagMOTD)
		if err != nil {
			glog.Exitf("cannot read MOTD %q: %v", flagMOTD, err)
		}
	}

	db, err := bolt.Open(flagDB, 0600, nil)
	if err != nil {
		glog.Exitf("opening database failed: %v", err)
	}

	provider, err := oidc.NewProvider(context.Background(), "https://sso.hackerspace.pl")
	if err != nil {
		glog.Exitf("newprovider: %v", err)
	}
	oauth2Config := oauth2.Config{
		ClientID:     flagOAuthClientID,
		ClientSecret: flagOAuthClientSecret,
		RedirectURL:  flagOAuthRedirectURL,

		// Discovery returns the OAuth2 endpoints.
		Endpoint: provider.Endpoint(),

		// "openid" is a required scope for OpenID Connect flows.
		Scopes: []string{oidc.ScopeOpenID, "profile:read"},
	}

	err = db.Update(func(tx *bolt.Tx) error {
		for _, name := range []string{
			"emailToAccount",
		} {
			_, err := tx.CreateBucketIfNotExists([]byte(name))
			if err != nil {
				return fmt.Errorf("create bucket %q: %s", name, err)
			}
		}
		return nil
	})
	if err != nil {
		glog.Exitf("db setup failed: %v", err)
	}

	s := &server{
		db:     db,
		store:  sessions.NewCookieStore([]byte(flagSecret)),
		oauth2: &oauth2Config,
		motd:   string(motd),
	}

	http.HandleFunc("/", s.viewIndex)
	http.HandleFunc("/login", s.viewLogin)
	http.HandleFunc("/oauth", s.viewOauth)
	http.HandleFunc("/callback", s.viewOauthCallback)
	http.HandleFunc("/setup", s.viewOauthSetup)
	http.HandleFunc("/reset", s.viewReset)
	http.HandleFunc("/logout", s.viewLogout)

	err = http.ListenAndServe(flagListen, nil)
	if err != nil {
		glog.Exitf("ListenAndServe: %v", err)
	}
}

type server struct {
	db     *bolt.DB
	store  *sessions.CookieStore
	oauth2 *oauth2.Config
	motd   string

	onlineLock     sync.RWMutex
	onlineData     []playerinfo
	onlineDeadline time.Time
}

var (
	tLogin = template.Must(template.New("login").Parse(`<html>
<title>super wow - who are you?</title>
<body>
<pre>

 ___ _   _ _ __   ___ _ __  __      _______      __
/ __| | | | '_ \ / _ \ '__| \ \ /\ / / _ \ \ /\ / /
\__ \ |_| | |_) |  __/ |     \ V  V / (_) \ V  V /
|___/\__,_| .__/ \___|_|      \_/\_/ \___/ \_/\_/
          |_|
 _         _       _             _           _       _
| | _____ | | ___ (_)___ _ _ __ | | _____   | |_   _| |__
| |/ / _ \| |/ _ \_  / _' | '_ \| |/ / _ \  | | | | | '_ \
|   < (_) | |  __// / (_| | | | |   < (_) | | | |_| | |_) |
|_|\_\___/|_|\___/___\__,_|_| |_|_|\_\___/  |_|\__,_|_.__/

 _         _                    __
| | _____ | | ___  __ _  ___    \ \
| |/ / _ \| |/ _ \/ _' |/ _ \  (_) |
|   < (_) | |  __/ (_| | (_) |  _| |
|_|\_\___/|_|\___|\__, |\___/  (_) |
                  |___/         /_/

</pre>
<a href="/oauth">Sign in (or create new account) with HSWAW SSO</a>.<br/>

<p>
Not a hswaw member? Talk to q3k.
</p>
</body>`))
	tSetup = template.Must(template.New("setup").Parse(`<html>
<title>super wow - setup account</title>
<body>
<b>hi, please provide details for your new WoW account</b><br/>
pick any username you want, pick a 3-16 character password that isn't the same as your sso password (duh)<br />
(this isn't your character name, this will only be used to log into WoW)
{{ if .Error }}
<br /><b>error</b>: {{ .Error }}<br />
{{ end }}
<form method="post" action="/setup">
username:<input name="username" value={{ .Username }}></input><br/>
password:<input name="password" type="password"></input><br/>
<input type=submit value="create account"/>
</form>
</body>`))
	tIndex = template.Must(template.New("index").Parse(`<html>
<title>super wow</title>
<style type="text/css">
    body {
        background-color: #fff;
    }
    table, th, td {
        background-color: #eee;
        padding: 0.2em 0.4em 0.2em 0.4em;
    }
    table th {
        background-color: #c0c0c0;
    }
    table {
        background-color: #fff;
        border-spacing: 0.2em;
    }
</style>
<body>
<b>Hello, {{ .Username }}.</b></br>
<a href="/logout">Log out.</a><br />
{{ .MOTD }}
<p>
Your account name is {{ .Username }}. Use the password that you entered when logging in via SSO for the first time, or <form action="/reset" method="POST"><input name="password" type="password" /><input type="submit" value="set a new password"/>.</form>
</p>
<b>Currently in-game:</b>
<table>
<tr><th>Account</th><th>Character</th></tr>
{{ range .Online }}
<tr><td>{{ .Account }}</td><td>{{ .Character }}</td></tr>
{{ end }}
</table>
</body>`))
)

func (s *server) session(r *http.Request) *sessions.Session {
	session, _ := s.store.Get(r, sessionName)
	return session
}

func (s *server) sessionGet(r *http.Request, k string) string {
	v, ok := s.session(r).Values[k]
	if !ok {
		return ""
	}
	v2, ok := v.(string)
	if !ok {
		return ""
	}
	return v2
}

func (s *server) sessionPut(w http.ResponseWriter, r *http.Request, k, v string) {
	session := s.session(r)
	session.Values[k] = v
	session.Save(r, w)
}

func (s *server) online(ctx context.Context) []playerinfo {
	s.onlineLock.RLock()
	if s.onlineData == nil || time.Now().After(s.onlineDeadline) {
		s.onlineLock.RUnlock()
		s.onlineLock.Lock()
		data, err := onlinelist(ctx)
		if err != nil {
			glog.Errorf("onlinelist fatch failed: %v", err)
			s.onlineDeadline = time.Now().Add(10 * time.Second)
		} else {
			s.onlineData = data
			s.onlineDeadline = time.Now().Add(60 * time.Second)
		}
		s.onlineLock.Unlock()
		s.onlineLock.RLock()
	}

	res := make([]playerinfo, len(s.onlineData))
	for i, pi := range s.onlineData {
		res[i] = pi
	}
	s.onlineLock.RUnlock()
	return res
}

func (s *server) viewIndex(w http.ResponseWriter, r *http.Request) {
	account := s.sessionGet(r, "account")
	if account == "" {
		http.Redirect(w, r, "/login", 302)
		return
	}
	err := tIndex.Execute(w, map[string]interface{}{
		"Username": account,
		"Online":   s.online(r.Context()),
		"MOTD":     template.HTML(s.motd),
	})
	if err != nil {
		glog.Errorf("/: %v", err)
		return
	}
}

const sessionName = "wow"

func (s *server) viewLogin(w http.ResponseWriter, r *http.Request) {
	account := s.sessionGet(r, "account")
	if account != "" {
		http.Redirect(w, r, "/", 302)
		return
	}
	err := tLogin.Execute(w, nil)
	if err != nil {
		glog.Errorf("/login: %v", err)
		return
	}
}

func (s *server) viewOauth(w http.ResponseWriter, r *http.Request) {
	stateBytes := make([]byte, 8)
	_, err := rand.Read(stateBytes)
	if err != nil {
		glog.Errorf("/oauth: random: %v", err)
		return
	}
	state := hex.EncodeToString(stateBytes)
	s.sessionPut(w, r, "ostate", state)
	url := s.oauth2.AuthCodeURL(state)
	http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}

func (s *server) viewOauthCallback(w http.ResponseWriter, r *http.Request) {
	if r.FormValue("errors") != "" {
		fmt.Fprintf(w, "Errors: %s", r.FormValue("errors"))
		return
	}
	state := s.sessionGet(r, "ostate")
	if state == "" {
		glog.Errorf("No state")
		http.Redirect(w, r, "/", 302)
		return
	}
	if state != r.FormValue("state") {
		glog.Errorf("Invalid state")
		http.Redirect(w, r, "/", 302)
		return
	}
	oauth2Token, err := s.oauth2.Exchange(r.Context(), r.FormValue("code"))
	if err != nil {
		glog.Errorf("Exchange failed: %v", err)
		http.Redirect(w, r, "/", 302)
		return
	}
	client := s.oauth2.Client(r.Context(), oauth2Token)
	res, err := client.Get("https://sso.hackerspace.pl/api/1/userinfo")
	if err != nil {
		glog.Errorf("Userinfo failed: %v", err)
		http.Redirect(w, r, "/", 302)
		return
	}
	defer res.Body.Close()
	data, _ := ioutil.ReadAll(res.Body)

	ui := userinfo{}
	err = json.Unmarshal(data, &ui)
	if err != nil || ui.Email == "" {
		glog.Errorf("Userinfo unarshal failed: %v", err)
		http.Redirect(w, r, "/", 302)
		return
	}

	account, err := s.accountForEmail(ui.Email)
	if err != nil {
		glog.Errorf("account get failed: %v", err)
		http.Redirect(w, r, "/", 302)
		return
	}
	if account != "" {
		s.sessionPut(w, r, "account", account)
		http.Redirect(w, r, "/", 302)
	} else {
		s.sessionPut(w, r, "email", ui.Email)
		http.Redirect(w, r, "/setup", 302)
	}
}

func (s *server) viewOauthSetup(w http.ResponseWriter, r *http.Request) {
	email := s.sessionGet(r, "email")
	if email == "" {
		glog.Errorf("No email")
		http.Redirect(w, r, "/", 302)
		return
	}

	if r.Method == "GET" {
		tSetup.Execute(w, nil)
		return
	}

	username := r.FormValue("username")
	password := r.FormValue("password")
	if !reAccount.MatchString(username) {
		tSetup.Execute(w, map[string]string{
			"Username": username,
			"Error":    "Invalid username - must be 3-16 a-z 0-9 - _",
		})
		return
	}
	if !rePassword.MatchString(password) {
		tSetup.Execute(w, map[string]string{
			"Username": username,
			"Error":    "Invalid password - must be 3-16 a-z A-Z 0-9 - _",
		})
		return
	}

	// this races. ugh. no way to list users. yolo.
	err := createAccount(r.Context(), username, password)
	if err != nil {
		tSetup.Execute(w, map[string]string{
			"Username": username,
			"Error":    "Account already exists, pick a different username",
		})
		return
	}

	err = s.db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("emailToAccount"))
		v := string(b.Get([]byte(email)))
		if v != "" {
			s.sessionPut(w, r, "account", v)
			http.Redirect(w, r, "/", 302)
			return nil
		}
		b.Put([]byte(email), []byte(username))
		s.sessionPut(w, r, "account", username)
		http.Redirect(w, r, "/", 302)
		return nil
	})
	if err != nil {
		glog.Errorf("setup tx: %v", err)
		http.Redirect(w, r, "/", 302)
	}
}
func (s *server) viewReset(w http.ResponseWriter, r *http.Request) {
	account := s.sessionGet(r, "account")
	if account == "" {
		glog.Errorf("No account")
		http.Redirect(w, r, "/", 302)
		return
	}

	password := r.FormValue("password")
	if !rePassword.MatchString(password) {
		fmt.Fprintf(w, "pick a 3-16 password with not too many special chars")
		return
	}

	// this races. ugh. no way to list users. yolo.
	err := ensureAccount(r.Context(), account, password)
	if err != nil {
		glog.Errorf("ensureAccount(%q, _): %v", account, err)
		fmt.Fprintf(w, "something went wrong, lol")
		return
	}
	fmt.Fprintf(w, "new password set.")
}

func (s *server) viewLogout(w http.ResponseWriter, r *http.Request) {
	s.sessionPut(w, r, "account", "")
	s.sessionPut(w, r, "email", "")
	http.Redirect(w, r, "/", 302)
}

func (s *server) accountForEmail(email string) (string, error) {
	res := ""
	err := s.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("emailToAccount"))
		v := b.Get([]byte(email))
		res = string(v)
		return nil
	})
	return res, err
}

type userinfo struct {
	Email string `json:"email"`
}
