// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package prog

import (
	"fmt"
	"math/rand"
	"sort"
)

// Target describes target OS/arch pair.
type Target struct {
	OS         string
	Arch       string
	Revision   string // unique hash representing revision of the descriptions
	PtrSize    uint64
	PageSize   uint64
	DataOffset uint64

	Syscalls  []*Syscall
	Resources []*ResourceDesc
	Structs   []*KeyedStruct
	Consts    []ConstValue

	// Syscall used by MakeMmap.
	// It has some special meaning because there are usually too many of them.
	MmapSyscall *Syscall

	// MakeMmap creates call that maps [start, start+npages) page range.
	MakeMmap func(start, npages uint64) *Call

	// AnalyzeMmap analyzes the call c regarding mapping/unmapping memory.
	// If it maps/unmaps any memory returns [start, start+npages) range,
	// otherwise returns npages = 0.
	AnalyzeMmap func(c *Call) (start, npages uint64, mapped bool)

	// SanitizeCall neutralizes harmful calls.
	SanitizeCall func(c *Call)

	// SpecialStructs allows target to do custom generation/mutation for some struct types.
	// Map key is struct name for which custom generation/mutation is required.
	// Map value is custom generation/mutation function that will be called
	// for the corresponding structs. g is helper object that allows generate random numbers,
	// allocate memory, etc. typ is the struct type. old is the old value of the struct
	// for mutation, or nil for generation. The function returns a new value of the struct,
	// and optionally any calls that need to be inserted before the arg reference.
	SpecialStructs map[string]func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)

	// Special strings that can matter for the target.
	// Used as fallback when string type does not have own dictionary.
	StringDictionary []string

	// Filled by prog package:
	SyscallMap  map[string]*Syscall
	ConstMap    map[string]uint64
	resourceMap map[string]*ResourceDesc
	// Maps resource name to a list of calls that can create the resource.
	resourceCtors map[string][]*Syscall
}

var targets = make(map[string]*Target)

func RegisterTarget(target *Target, initArch func(target *Target)) {
	key := target.OS + "/" + target.Arch
	if targets[key] != nil {
		panic(fmt.Sprintf("duplicate target %v", key))
	}
	target.SanitizeCall = func(c *Call) {}
	initTarget(target)
	initArch(target)
	target.ConstMap = nil // currently used only by initArch
	targets[key] = target
}

func GetTarget(OS, arch string) (*Target, error) {
	key := OS + "/" + arch
	target := targets[key]
	if target == nil {
		var supported []string
		for _, t := range targets {
			supported = append(supported, fmt.Sprintf("%v/%v", t.OS, t.Arch))
		}
		sort.Strings(supported)
		return nil, fmt.Errorf("unknown target: %v (supported: %v)", key, supported)
	}
	return target, nil
}

func AllTargets() []*Target {
	var res []*Target
	for _, t := range targets {
		res = append(res, t)
	}
	sort.Slice(res, func(i, j int) bool {
		if res[i].OS != res[j].OS {
			return res[i].OS < res[j].OS
		}
		return res[i].Arch < res[j].Arch
	})
	return res
}

func initTarget(target *Target) {
	target.ConstMap = make(map[string]uint64)
	for _, c := range target.Consts {
		target.ConstMap[c.Name] = c.Value
	}

	target.resourceMap = make(map[string]*ResourceDesc)
	for _, res := range target.Resources {
		target.resourceMap[res.Name] = res
	}

	keyedStructs := make(map[StructKey]*StructDesc)
	for _, desc := range target.Structs {
		keyedStructs[desc.Key] = desc.Desc
	}
	target.Structs = nil

	target.SyscallMap = make(map[string]*Syscall)
	for _, c := range target.Syscalls {
		target.SyscallMap[c.Name] = c
		ForeachType(c, func(t0 Type) {
			switch t := t0.(type) {
			case *ResourceType:
				t.Desc = target.resourceMap[t.TypeName]
				if t.Desc == nil {
					panic("no resource desc")
				}
			case *StructType:
				t.StructDesc = keyedStructs[t.Key]
				if t.StructDesc == nil {
					panic("no struct desc")
				}
			case *UnionType:
				t.StructDesc = keyedStructs[t.Key]
				if t.StructDesc == nil {
					panic("no union desc")
				}
			}
		})
	}

	target.resourceCtors = make(map[string][]*Syscall)
	for _, res := range target.Resources {
		target.resourceCtors[res.Name] = target.calcResourceCtors(res.Kind, false)
	}
}

type Gen struct {
	r *randGen
	s *state
}

func (g *Gen) Rand() *rand.Rand {
	return g.r.Rand
}

func (g *Gen) NOutOf(n, outOf int) bool {
	return g.r.nOutOf(n, outOf)
}

func (g *Gen) Alloc(ptrType Type, data Arg) (Arg, []*Call) {
	return g.r.addr(g.s, ptrType, data.Size(), data)
}

func (g *Gen) GenerateArg(typ Type, pcalls *[]*Call) Arg {
	arg, calls := g.r.generateArg(g.s, typ)
	*pcalls = append(*pcalls, calls...)
	return arg
}
