// 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"
	"fmt"
	"http"
	"json"
	"log"
	"os"
	"strconv"
)

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) os.Error {
	var r *http.Response
	var err os.Error
	if *verbose {
		log.Println("dash", cmd, args)
	}
	cmd = "http://" + *dashboard + "/" + cmd
	switch meth {
	case "GET":
		if args != nil {
			m := make(map[string][]string)
			for k, v := range args {
				m[k] = []string{v}
			}
			cmd += "?" + http.EncodeQuery(m)
		}
		r, err = http.Get(cmd)
	case "POST":
		r, err = http.PostForm(cmd, args)
	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) os.Error {
	var resp struct {
		Status string
		Error  string
	}
	err := dash(meth, cmd, &resp, args)
	if err != nil {
		return err
	}
	if resp.Status != "OK" {
		return os.NewError("/build: " + resp.Error)
	}
	return nil
}

// todo returns the next hash to build.
func (b *Builder) todo() (rev string, err os.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) os.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 os.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 to the dashboard
func (b *Builder) updatePackage(pkg string, state bool, buildLog, info string, hash string) os.Error {
	return dash("POST", "package", nil, param{
		"builder": b.name,
		"key":     b.key,
		"path":    pkg,
		"state":   strconv.Btoa(state),
		"log":     buildLog,
		"info":    info,
		"go_rev":  hash[:12],
	})
}

// postCommit informs the dashboard of a new commit
func postCommit(key string, l *HgLog) os.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
}
