// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"errors"
	"fmt"
	"http"
	"json"
	"log"
	"strconv"
	"url"
)

type param map[string]string

// dash runs the given method and command on the dashboard.
// If args is not nil, it is the query or post parameters.
// If resp is not nil, dash unmarshals the body as JSON into resp.
func dash(meth, cmd string, resp interface{}, args param) error {
	var r *http.Response
	var err error
	if *verbose {
		log.Println("dash", cmd, args)
	}
	cmd = "http://" + *dashboard + "/" + cmd
	vals := make(url.Values)
	for k, v := range args {
		vals.Add(k, v)
	}
	switch meth {
	case "GET":
		if q := vals.Encode(); q != "" {
			cmd += "?" + q
		}
		r, err = http.Get(cmd)
	case "POST":
		r, err = http.PostForm(cmd, vals)
	default:
		return fmt.Errorf("unknown method %q", meth)
	}
	if err != nil {
		return err
	}
	defer r.Body.Close()
	var buf bytes.Buffer
	buf.ReadFrom(r.Body)
	if resp != nil {
		if err = json.Unmarshal(buf.Bytes(), resp); err != nil {
			log.Printf("json unmarshal %#q: %s\n", buf.Bytes(), err)
			return err
		}
	}
	return nil
}

func dashStatus(meth, cmd string, args param) error {
	var resp struct {
		Status string
		Error  string
	}
	err := dash(meth, cmd, &resp, args)
	if err != nil {
		return err
	}
	if resp.Status != "OK" {
		return errors.New("/build: " + resp.Error)
	}
	return nil
}

// todo returns the next hash to build.
func (b *Builder) todo() (rev string, err error) {
	var resp []struct {
		Hash string
	}
	if err = dash("GET", "todo", &resp, param{"builder": b.name}); err != nil {
		return
	}
	if len(resp) > 0 {
		rev = resp[0].Hash
	}
	return
}

// recordResult sends build results to the dashboard
func (b *Builder) recordResult(buildLog string, hash string) error {
	return dash("POST", "build", nil, param{
		"builder": b.name,
		"key":     b.key,
		"node":    hash,
		"log":     buildLog,
	})
}

// packages fetches a list of package paths from the dashboard
func packages() (pkgs []string, err error) {
	var resp struct {
		Packages []struct {
			Path string
		}
	}
	err = dash("GET", "package", &resp, param{"fmt": "json"})
	if err != nil {
		return
	}
	for _, p := range resp.Packages {
		pkgs = append(pkgs, p.Path)
	}
	return
}

// updatePackage sends package build results and info dashboard
func (b *Builder) updatePackage(pkg string, ok bool, buildLog, info string) error {
	return dash("POST", "package", nil, param{
		"builder": b.name,
		"key":     b.key,
		"path":    pkg,
		"ok":      strconv.Btoa(ok),
		"log":     buildLog,
		"info":    info,
	})
}

// postCommit informs the dashboard of a new commit
func postCommit(key string, l *HgLog) error {
	return dashStatus("POST", "commit", param{
		"key":    key,
		"node":   l.Hash,
		"date":   l.Date,
		"user":   l.Author,
		"parent": l.Parent,
		"desc":   l.Desc,
	})
}

// dashboardCommit returns true if the dashboard knows about hash.
func dashboardCommit(hash string) bool {
	err := dashStatus("GET", "commit", param{"node": hash})
	if err != nil {
		log.Printf("check %s: %s", hash, err)
		return false
	}
	return true
}
