// Copyright 2020 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 fuzz

import (
	"encoding/binary"
	"fmt"
	"math"
	"unsafe"
)

type mutator struct {
	r       mutatorRand
	scratch []byte // scratch slice to avoid additional allocations
}

func newMutator() *mutator {
	return &mutator{r: newPcgRand()}
}

func (m *mutator) rand(n int) int {
	return m.r.intn(n)
}

func (m *mutator) randByteOrder() binary.ByteOrder {
	if m.r.bool() {
		return binary.LittleEndian
	}
	return binary.BigEndian
}

// chooseLen chooses length of range mutation in range [1,n]. It gives
// preference to shorter ranges.
func (m *mutator) chooseLen(n int) int {
	switch x := m.rand(100); {
	case x < 90:
		return m.rand(min(8, n)) + 1
	case x < 99:
		return m.rand(min(32, n)) + 1
	default:
		return m.rand(n) + 1
	}
}

// mutate performs several mutations on the provided values.
func (m *mutator) mutate(vals []any, maxBytes int) {
	// TODO(katiehockman): pull some of these functions into helper methods and
	// test that each case is working as expected.
	// TODO(katiehockman): perform more types of mutations for []byte.

	// maxPerVal will represent the maximum number of bytes that each value be
	// allowed after mutating, giving an equal amount of capacity to each line.
	// Allow a little wiggle room for the encoding.
	maxPerVal := maxBytes/len(vals) - 100

	// Pick a random value to mutate.
	// TODO: consider mutating more than one value at a time.
	i := m.rand(len(vals))
	switch v := vals[i].(type) {
	case int:
		vals[i] = int(m.mutateInt(int64(v), maxInt))
	case int8:
		vals[i] = int8(m.mutateInt(int64(v), math.MaxInt8))
	case int16:
		vals[i] = int16(m.mutateInt(int64(v), math.MaxInt16))
	case int64:
		vals[i] = m.mutateInt(v, math.MaxInt64)
	case uint:
		vals[i] = uint(m.mutateUInt(uint64(v), maxUint))
	case uint16:
		vals[i] = uint16(m.mutateUInt(uint64(v), math.MaxUint16))
	case uint32:
		vals[i] = uint32(m.mutateUInt(uint64(v), math.MaxUint32))
	case uint64:
		vals[i] = m.mutateUInt(v, math.MaxUint64)
	case float32:
		vals[i] = float32(m.mutateFloat(float64(v), math.MaxFloat32))
	case float64:
		vals[i] = m.mutateFloat(v, math.MaxFloat64)
	case bool:
		if m.rand(2) == 1 {
			vals[i] = !v // 50% chance of flipping the bool
		}
	case rune: // int32
		vals[i] = rune(m.mutateInt(int64(v), math.MaxInt32))
	case byte: // uint8
		vals[i] = byte(m.mutateUInt(uint64(v), math.MaxUint8))
	case string:
		if len(v) > maxPerVal {
			panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v)))
		}
		if cap(m.scratch) < maxPerVal {
			m.scratch = append(make([]byte, 0, maxPerVal), v...)
		} else {
			m.scratch = m.scratch[:len(v)]
			copy(m.scratch, v)
		}
		m.mutateBytes(&m.scratch)
		vals[i] = string(m.scratch)
	case []byte:
		if len(v) > maxPerVal {
			panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v)))
		}
		if cap(m.scratch) < maxPerVal {
			m.scratch = append(make([]byte, 0, maxPerVal), v...)
		} else {
			m.scratch = m.scratch[:len(v)]
			copy(m.scratch, v)
		}
		m.mutateBytes(&m.scratch)
		vals[i] = m.scratch
	default:
		panic(fmt.Sprintf("type not supported for mutating: %T", vals[i]))
	}
}

func (m *mutator) mutateInt(v, maxValue int64) int64 {
	var max int64
	for {
		max = 100
		switch m.rand(2) {
		case 0:
			// Add a random number
			if v >= maxValue {
				continue
			}
			if v > 0 && maxValue-v < max {
				// Don't let v exceed maxValue
				max = maxValue - v
			}
			v += int64(1 + m.rand(int(max)))
			return v
		case 1:
			// Subtract a random number
			if v <= -maxValue {
				continue
			}
			if v < 0 && maxValue+v < max {
				// Don't let v drop below -maxValue
				max = maxValue + v
			}
			v -= int64(1 + m.rand(int(max)))
			return v
		}
	}
}

func (m *mutator) mutateUInt(v, maxValue uint64) uint64 {
	var max uint64
	for {
		max = 100
		switch m.rand(2) {
		case 0:
			// Add a random number
			if v >= maxValue {
				continue
			}
			if v > 0 && maxValue-v < max {
				// Don't let v exceed maxValue
				max = maxValue - v
			}

			v += uint64(1 + m.rand(int(max)))
			return v
		case 1:
			// Subtract a random number
			if v <= 0 {
				continue
			}
			if v < max {
				// Don't let v drop below 0
				max = v
			}
			v -= uint64(1 + m.rand(int(max)))
			return v
		}
	}
}

func (m *mutator) mutateFloat(v, maxValue float64) float64 {
	var max float64
	for {
		switch m.rand(4) {
		case 0:
			// Add a random number
			if v >= maxValue {
				continue
			}
			max = 100
			if v > 0 && maxValue-v < max {
				// Don't let v exceed maxValue
				max = maxValue - v
			}
			v += float64(1 + m.rand(int(max)))
			return v
		case 1:
			// Subtract a random number
			if v <= -maxValue {
				continue
			}
			max = 100
			if v < 0 && maxValue+v < max {
				// Don't let v drop below -maxValue
				max = maxValue + v
			}
			v -= float64(1 + m.rand(int(max)))
			return v
		case 2:
			// Multiply by a random number
			absV := math.Abs(v)
			if v == 0 || absV >= maxValue {
				continue
			}
			max = 10
			if maxValue/absV < max {
				// Don't let v go beyond the minimum or maximum value
				max = maxValue / absV
			}
			v *= float64(1 + m.rand(int(max)))
			return v
		case 3:
			// Divide by a random number
			if v == 0 {
				continue
			}
			v /= float64(1 + m.rand(10))
			return v
		}
	}
}

type byteSliceMutator func(*mutator, []byte) []byte

var byteSliceMutators = []byteSliceMutator{
	byteSliceRemoveBytes,
	byteSliceInsertRandomBytes,
	byteSliceDuplicateBytes,
	byteSliceOverwriteBytes,
	byteSliceBitFlip,
	byteSliceXORByte,
	byteSliceSwapByte,
	byteSliceArithmeticUint8,
	byteSliceArithmeticUint16,
	byteSliceArithmeticUint32,
	byteSliceArithmeticUint64,
	byteSliceOverwriteInterestingUint8,
	byteSliceOverwriteInterestingUint16,
	byteSliceOverwriteInterestingUint32,
	byteSliceInsertConstantBytes,
	byteSliceOverwriteConstantBytes,
	byteSliceShuffleBytes,
	byteSliceSwapBytes,
}

func (m *mutator) mutateBytes(ptrB *[]byte) {
	b := *ptrB
	defer func() {
		if unsafe.SliceData(*ptrB) != unsafe.SliceData(b) {
			panic("data moved to new address")
		}
		*ptrB = b
	}()

	for {
		mut := byteSliceMutators[m.rand(len(byteSliceMutators))]
		if mutated := mut(m, b); mutated != nil {
			b = mutated
			return
		}
	}
}

var (
	interesting8  = []int8{-128, -1, 0, 1, 16, 32, 64, 100, 127}
	interesting16 = []int16{-32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767}
	interesting32 = []int32{-2147483648, -100663046, -32769, 32768, 65535, 65536, 100663045, 2147483647}
)

const (
	maxUint = uint64(^uint(0))
	maxInt  = int64(maxUint >> 1)
)

func init() {
	for _, v := range interesting8 {
		interesting16 = append(interesting16, int16(v))
	}
	for _, v := range interesting16 {
		interesting32 = append(interesting32, int32(v))
	}
}
