// +build OMIT

package mart

import (
	"bytes"
	"fmt"
	"math/rand"
	"net/http"
	"strconv"
	"strings"

	"appengine"
	"appengine/datastore"
	"appengine/delay"
	"appengine/mail"
	"appengine/user"

	"github.com/mjibson/appstats"
)

func init() {
	http.HandleFunc("/", front)
	http.Handle("/checkout", appstats.NewHandler(checkout))
	http.HandleFunc("/admin/populate", adminPopulate)
}

func front(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	fmt.Fprintf(w, "Hello, welcome to Gopher Mart!")
}

const (
	numItems = 100 // number of different items for sale

	appAdmin = "noreply@google.com" // an admin of this app, for sending mail
)

// Item represents an item for sale in Gopher Mart.
type Item struct {
	Name  string
	Price float64
}

func itemKey(c appengine.Context, i int) *datastore.Key {
	return datastore.NewKey(c, "Item", fmt.Sprintf("item%04d", i), 0, nil)
}

func checkout(c appengine.Context, w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	num, err := strconv.Atoi(r.FormValue("num"))
	if err == nil && (num < 1 || num > 30) {
		err = fmt.Errorf("%d out of range [1,30]", num)
	}
	if err != nil {
		http.Error(w, fmt.Sprintf("bad number of items: %v", err), http.StatusBadRequest)
		return
	}

	// Pick random items.
	keys := make([]*datastore.Key, num)
	for i := range keys {
		keys[i] = itemKey(c, rand.Intn(numItems))
	}

	// Batch get
	items := make([]Item, len(keys))
	if err := datastore.GetMulti(c, keys, items); err != nil {
		// ...
		http.Error(w, fmt.Sprintf("datastore.GetMulti: %v", err), http.StatusBadRequest) // OMIT
		return                                                                           // OMIT
	}

	// Print items.
	var b bytes.Buffer
	fmt.Fprintf(&b, "Here's what you bought:\n")
	var sum float64
	for _, item := range items {
		fmt.Fprintf(&b, "\t%s", item.Name)
		fmt.Fprint(&b, strings.Repeat("\t", (40-len(item.Name)+7)/8))
		fmt.Fprintf(&b, "$%5.2f\n", item.Price)
		sum += item.Price
	}
	fmt.Fprintln(&b, strings.Repeat("-", 55))
	fmt.Fprintf(&b, "\tTotal:\t\t\t\t\t$%.2f\n", sum)

	w.Write(b.Bytes())

	sendReceipt.Call(c, user.Current(c).Email, b.String())
}

var sendReceipt = delay.Func("send-receipt", func(c appengine.Context, dst, body string) {
	msg := &mail.Message{
		Sender:  appAdmin,
		To:      []string{dst},
		Subject: "Your Gopher Mart receipt",
		Body:    body,
	}
	if err := mail.Send(c, msg); err != nil {
		c.Errorf("mail.Send: %v", err)
	}
})

func adminPopulate(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	for i := range [numItems]struct{}{} { // r hates this. tee hee.
		key := itemKey(c, i)
		good := goods[rand.Intn(len(goods))]
		item := &Item{
			// TODO: vary names more
			Name:  fmt.Sprintf("%s %dg", good.name, i+1),
			Price: float64(rand.Intn(1999)+1) / 100,
		}
		if _, err := datastore.Put(c, key, item); err != nil {
			http.Error(w, err.Error(), 500)
			return
		}
	}
	fmt.Fprintf(w, "ok. %d items populated.", numItems)
}

var goods = [...]struct {
	name string
}{
	{"Gopher Bran"},
	{"Gopher Flakes"},
	{"Gopher Grease"},
	{"Gopher Litter"},
}
