// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

// +build golangorg

// Package short implements a simple URL shortener, serving an administrative
// interface at /s and shortened urls from /s/key.
// It is designed to run only on the instance of godoc that serves golang.org.
package short

// TODO(adg): collect statistics on URL visits

import (
	"context"
	"errors"
	"fmt"
	"html/template"
	"io"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"strings"

	"cloud.google.com/go/datastore"
	"golang.org/x/website/internal/memcache"
	"google.golang.org/appengine/user"
)

const (
	prefix  = "/s"
	kind    = "Link"
	baseURL = "https://golang.org" + prefix
)

// Link represents a short link.
type Link struct {
	Key, Target string
}

var validKey = regexp.MustCompile(`^[a-zA-Z0-9-_.]+$`)

type server struct {
	datastore *datastore.Client
	memcache  *memcache.CodecClient
}

func RegisterHandlers(mux *http.ServeMux, dc *datastore.Client, mc *memcache.Client) {
	s := server{dc, mc.WithCodec(memcache.JSON)}
	mux.HandleFunc(prefix+"/", s.linkHandler)

	// TODO(cbro): move storage of the links to a text file in Gerrit.
	// Disable the admin handler until that happens, since GAE Flex doesn't support
	// the "google.golang.org/appengine/user" package.
	// See golang.org/issue/29988 and golang.org/issue/27205#issuecomment-418673218.
	// mux.HandleFunc(prefix, adminHandler)
	mux.HandleFunc(prefix, func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusForbidden)
		io.WriteString(w, "Link creation temporarily unavailable. See golang.org/issue/29988.")
	})
}

// linkHandler services requests to short URLs.
//   http://golang.org/s/key[/remaining/path]
// It consults memcache and datastore for the Link for key.
// It then sends a redirects or an error message.
// If the remaining path part is not empty, the redirects
// will be the relative path from the resolved Link.
func (h server) linkHandler(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	key, remainingPath, err := extractKey(r)
	if err != nil { // invalid key or url
		http.Error(w, "not found", http.StatusNotFound)
		return
	}

	var link Link
	if err := h.memcache.Get(ctx, cacheKey(key), &link); err != nil {
		k := datastore.NameKey(kind, key, nil)
		err = h.datastore.Get(ctx, k, &link)
		switch err {
		case datastore.ErrNoSuchEntity:
			http.Error(w, "not found", http.StatusNotFound)
			return
		default: // != nil
			log.Printf("ERROR %q: %v", key, err)
			http.Error(w, "internal server error", http.StatusInternalServerError)
			return
		case nil:
			item := &memcache.Item{
				Key:    cacheKey(key),
				Object: &link,
			}
			if err := h.memcache.Set(ctx, item); err != nil {
				log.Printf("WARNING %q: %v", key, err)
			}
		}
	}

	target := link.Target
	if remainingPath != "" {
		target += remainingPath
	}
	http.Redirect(w, r, target, http.StatusFound)
}

func extractKey(r *http.Request) (key, remainingPath string, err error) {
	path := r.URL.Path
	if !strings.HasPrefix(path, prefix+"/") {
		return "", "", errors.New("invalid path")
	}

	key, remainingPath = path[len(prefix)+1:], ""
	if slash := strings.Index(key, "/"); slash > 0 {
		key, remainingPath = key[:slash], key[slash:]
	}

	if !validKey.MatchString(key) {
		return "", "", errors.New("invalid key")
	}
	return key, remainingPath, nil
}

var adminTemplate = template.Must(template.New("admin").Parse(templateHTML))

// adminHandler serves an administrative interface.
func (h server) adminHandler(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	if !user.IsAdmin(ctx) {
		http.Error(w, "forbidden", http.StatusForbidden)
		return
	}

	var newLink *Link
	var doErr error
	if r.Method == "POST" {
		key := r.FormValue("key")
		switch r.FormValue("do") {
		case "Add":
			newLink = &Link{key, r.FormValue("target")}
			doErr = h.putLink(ctx, newLink)
		case "Delete":
			k := datastore.NameKey(kind, key, nil)
			doErr = h.datastore.Delete(ctx, k)
		default:
			http.Error(w, "unknown action", http.StatusBadRequest)
		}
		err := h.memcache.Delete(ctx, cacheKey(key))
		if err != nil && err != memcache.ErrCacheMiss {
			log.Printf("WARNING %q: %v", key, err)
		}
	}

	var links []*Link
	q := datastore.NewQuery(kind).Order("Key")
	if _, err := h.datastore.GetAll(ctx, q, &links); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		log.Printf("ERROR %v", err)
		return
	}

	// Put the new link in the list if it's not there already.
	// (Eventual consistency means that it might not show up
	// immediately, which might be confusing for the user.)
	if newLink != nil && doErr == nil {
		found := false
		for i := range links {
			if links[i].Key == newLink.Key {
				found = true
				break
			}
		}
		if !found {
			links = append([]*Link{newLink}, links...)
		}
		newLink = nil
	}

	var data = struct {
		BaseURL string
		Prefix  string
		Links   []*Link
		New     *Link
		Error   error
	}{baseURL, prefix, links, newLink, doErr}
	if err := adminTemplate.Execute(w, &data); err != nil {
		log.Printf("ERROR adminTemplate: %v", err)
	}
}

// putLink validates the provided link and puts it into the datastore.
func (h server) putLink(ctx context.Context, link *Link) error {
	if !validKey.MatchString(link.Key) {
		return errors.New("invalid key; must match " + validKey.String())
	}
	if _, err := url.Parse(link.Target); err != nil {
		return fmt.Errorf("bad target: %v", err)
	}
	k := datastore.NameKey(kind, link.Key, nil)
	_, err := h.datastore.Put(ctx, k, link)
	return err
}

// cacheKey returns a short URL key as a memcache key.
func cacheKey(key string) string {
	return "link-" + key
}
