// 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.Go.(*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 := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " 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()
}
