//+build ignore

package main

import (
	"bytes"
	"compress/gzip"
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"code.justin.tv/rhys/nursery/profile"
	"github.com/golang/protobuf/proto"
	"rsc.io/perf2pprof/pprof"
)

func main() {
	r := os.Stdin

	gz, err := ioutil.ReadAll(r)
	if err != nil {
		log.Fatalf("read err=%q", err)
	}

	rd, err := gzip.NewReader(bytes.NewReader(gz))
	if err != nil {
		log.Fatalf("gzip err=%q", err)
	}

	buf, err := ioutil.ReadAll(rd)
	if err != nil {
		log.Fatalf("gzip err=%q", err)
	}

	rsc, err := pprof.Parse(bytes.NewReader(gz))
	if err != nil {
		log.Fatalf("pprof err=%q", err)
	}

	var p profile.Profile

	err = proto.Unmarshal(buf, &p)
	if err != nil {
		log.Fatalf("proto err=%q", err)
	}

	// log.Printf("rsc=%q", rsc.DropFrames)
	_ = rsc

	printUnknown("Profile", p.XXX_unrecognized)
	for _, p := range p.Function {
		printUnknown("Function", p.XXX_unrecognized)
	}
	for _, p := range p.Location {
		printUnknown("Location", p.XXX_unrecognized)
		for _, p := range p.Line {
			printUnknown("Line", p.XXX_unrecognized)
		}
	}
	for _, p := range p.Mapping {
		printUnknown("Mapping", p.XXX_unrecognized)
	}
	for _, p := range p.Sample {
		printUnknown("Sample", p.XXX_unrecognized)
		for _, p := range p.XLabel {
			printUnknown("Label", p.XXX_unrecognized)
		}
	}
	for _, p := range p.SampleType {
		printUnknown("SampleType", p.XXX_unrecognized)
	}

	// log.Printf("rsc=%d p=%d", rsc.DurationNanos, p.GetDurationNanos())
	// for _, f := range p.GetFunction() {
	// 	log.Printf("id=%d file=%d line=%d name=%d systemname=%d",
	// 		f.GetId(), f.GetXFilename(), f.GetStartLine(), f.GetXName(), f.GetXSystemName())
	// }
	for i, s := range p.StringTable {
		log.Printf("id=%d string=%q", i, s)
	}

	//

	var p2 profile.Profile

	p2.DurationNanos = proto.Int64(1000000000)

	buf2, err := proto.Marshal(&p2)
	if err != nil {
		log.Fatalf("marshal err=%q", err)
	}
	log.Printf("len1=%d len2=%d", len(buf), len(buf2))

	//

	// var rsc3 pprof.Profile
	p3, err := convert(rsc)
	if err != nil {
		log.Fatalf("convert err=%q", err)
	}
	log.Printf("p3:\n%s", proto.MarshalTextString(p3))
}

func printUnknown(name string, buf []byte) {
	x, n := proto.DecodeVarint(buf)
	if n <= 0 {
		return
	}

	prefix := buf[n:]
	if l := 40; len(prefix) > l {
		prefix = prefix[:l]
	}

	var wire string
	switch x := x & 0x7; x {
	case 0:
		wire = "varint"
	case 1:
		wire = "64bit"
	case 2:
		wire = "length"
	case 5:
		wire = "32bit"
	default:
		wire = fmt.Sprintf("unknown-%d", x)
	}

	log.Printf("name=%q id=%d b=%q prefix=%q", name, x>>3, wire, prefix)
}

func stringIndex(p *profile.Profile, str string) int {
	for i, s := range p.StringTable {
		if str == s {
			return i
		}
	}
	p.StringTable = append(p.StringTable, str)
	return len(p.StringTable) - 1
}

func convert(rsc *pprof.Profile) (*profile.Profile, error) {
	var p profile.Profile
	var buf bytes.Buffer
	err := rsc.Write(&buf)
	if err != nil {
		return nil, err
	}
	r, err := gzip.NewReader(&buf)
	if err != nil {
		return nil, err
	}
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}
	err = proto.Unmarshal(b, &p)
	if err != nil {
		return nil, err
	}
	return &p, nil
}
