// 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"
	"go/ast"
	"go/printer"
	"go/token"
	"os"
	"strings"
)

// godefs returns the output for -godefs mode.
func (p *Package) godefs(f *File, srcfile string) string {
	var buf bytes.Buffer

	fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n")
	fmt.Fprintf(&buf, "// %s\n", strings.Join(os.Args, " "))
	fmt.Fprintf(&buf, "\n")

	override := make(map[string]string)

	// Allow source file to specify override mappings.
	// For example, the socket data structures refer
	// to in_addr and in_addr6 structs but we want to be
	// able to treat them as byte arrays, so the godefs
	// inputs in package syscall say
	//
	//	// +godefs map struct_in_addr [4]byte
	//	// +godefs map struct_in_addr6 [16]byte
	//
	for _, g := range f.Comments {
		for _, c := range g.List {
			i := strings.Index(c.Text, "+godefs map")
			if i < 0 {
				continue
			}
			s := strings.TrimSpace(c.Text[i+len("+godefs map"):])
			i = strings.Index(s, " ")
			if i < 0 {
				fmt.Fprintf(os.Stderr, "invalid +godefs map comment: %s\n", c.Text)
				continue
			}
			override["_Ctype_"+strings.TrimSpace(s[:i])] = strings.TrimSpace(s[i:])
		}
	}
	for _, n := range f.Name {
		if s := override[n.Go]; s != "" {
			override[n.Mangle] = s
		}
	}

	// Otherwise, if the source file says type T C.whatever,
	// use "T" as the mangling of C.whatever,
	// except in the definition (handled at end of function).
	refName := make(map[*ast.Expr]*Name)
	for _, r := range f.Ref {
		refName[r.Expr] = r.Name
	}
	for _, d := range f.AST.Decls {
		d, ok := d.(*ast.GenDecl)
		if !ok || d.Tok != token.TYPE {
			continue
		}
		for _, s := range d.Specs {
			s := s.(*ast.TypeSpec)
			n := refName[&s.Type]
			if n != nil && n.Mangle != "" {
				override[n.Mangle] = s.Name.Name
			}
		}
	}

	// Extend overrides using typedefs:
	// If we know that C.xxx should format as T
	// and xxx is a typedef for yyy, make C.yyy format as T.
	for typ, def := range typedef {
		if new := override[typ]; new != "" {
			if id, ok := def.(*ast.Ident); ok {
				override[id.Name] = new
			}
		}
	}

	// Apply overrides.
	for old, new := range override {
		if id := goIdent[old]; id != nil {
			id.Name = new
		}
	}

	// Any names still using the _C syntax are not going to compile,
	// although in general we don't know whether they all made it
	// into the file, so we can't warn here.
	//
	// The most common case is union types, which begin with
	// _Ctype_union and for which typedef[name] is a Go byte
	// array of the appropriate size (such as [4]byte).
	// Substitute those union types with byte arrays.
	for name, id := range goIdent {
		if id.Name == name && strings.Contains(name, "_Ctype_union") {
			if def := typedef[name]; def != nil {
				id.Name = gofmt(def)
			}
		}
	}

	conf.Fprint(&buf, fset, f.AST)

	return buf.String()
}

// cdefs returns the output for -cdefs mode.
// The easiest way to do this is to translate the godefs Go to C.
func (p *Package) cdefs(f *File, srcfile string) string {
	godefsOutput := p.godefs(f, srcfile)

	lines := strings.Split(godefsOutput, "\n")
	lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"

	for i, line := range lines {
		lines[i] = strings.TrimSpace(line)
	}

	var out bytes.Buffer
	printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) }

	didTypedef := false
	for i := 0; i < len(lines); i++ {
		line := lines[i]

		// Delete
		//	package x
		if strings.HasPrefix(line, "package ") {
			continue
		}

		// Convert
		//	const (
		//		A = 1
		//		B = 2
		//	)
		//
		// to
		//
		//	enum {
		//		A = 1,
		//		B = 2,
		//	};
		if line == "const (" {
			printf("enum {\n")
			for i++; i < len(lines) && lines[i] != ")"; i++ {
				line = lines[i]
				if line != "" {
					printf("\t%s,", line)
				}
				printf("\n")
			}
			printf("};\n")
			continue
		}

		// Convert
		//	const A = 1
		// to
		//	enum { A = 1 };
		if strings.HasPrefix(line, "const ") {
			printf("enum { %s };\n", line[len("const "):])
			continue
		}

		// On first type definition, typedef all the structs
		// in case there are dependencies between them.
		if !didTypedef && strings.HasPrefix(line, "type ") {
			didTypedef = true
			for _, line := range lines {
				line = strings.TrimSpace(line)
				if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
					s := line[len("type ") : len(line)-len(" struct {")]
					printf("typedef struct %s %s;\n", s, s)
				}
			}
			printf("\n")
			printf("#pragma pack on\n")
			printf("\n")
		}

		// Convert
		//	type T struct {
		//		X int64
		//		Y *int32
		//		Z [4]byte
		//	}
		//
		// to
		//
		//	struct T {
		//		int64 X;
		//		int32 *Y;
		//		byte Z[4];
		//	}
		if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
			s := line[len("type ") : len(line)-len(" struct {")]
			printf("struct %s {\n", s)
			for i++; i < len(lines) && lines[i] != "}"; i++ {
				line := lines[i]
				if line != "" {
					f := strings.Fields(line)
					if len(f) != 2 {
						fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line)
						nerrors++
						continue
					}
					printf("\t%s;", cdecl(f[0], f[1]))
				}
				printf("\n")
			}
			printf("};\n")
			continue
		}

		// Convert
		//	type T int
		// to
		//	typedef int T;
		if strings.HasPrefix(line, "type ") {
			f := strings.Fields(line[len("type "):])
			if len(f) != 2 {
				fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line)
				nerrors++
				continue
			}
			printf("typedef\t%s;\n", cdecl(f[0], f[1]))
			continue
		}

		printf("%s\n", line)
	}

	if didTypedef {
		printf("\n")
		printf("#pragma pack off\n")
	}

	return out.String()
}

// cdecl returns the C declaration for the given Go name and type.
// It only handles the specific cases necessary for converting godefs output.
func cdecl(name, typ string) string {
	// X *[0]byte -> X *void
	if strings.HasPrefix(typ, "*[0]") {
		typ = "*void"
	}
	// X *byte -> *X byte
	if strings.HasPrefix(typ, "*") {
		name = "*" + name
		typ = typ[1:]
	}
	// X [4]byte -> X[4] byte
	if strings.HasPrefix(typ, "[") {
		i := strings.Index(typ, "]") + 1
		name = name + typ[:i]
		typ = typ[i:]
	}
	// X T -> T X
	// Handle the special case: 'unsafe.Pointer' is 'void *'
	if typ == "unsafe.Pointer" {
		typ = "void"
		name = "*" + name
	}
	return typ + "\t" + name
}

var gofmtBuf bytes.Buffer

// gofmt returns the gofmt-formatted string for an AST node.
func gofmt(n interface{}) string {
	gofmtBuf.Reset()
	err := printer.Fprint(&gofmtBuf, fset, n)
	if err != nil {
		return "<" + err.Error() + ">"
	}
	return gofmtBuf.String()
}
