package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"text/template"
)

type listItem struct {
	Name   string
	Suffix string
}

var list = []listItem{
	{Name: "Buffersink"},
	{Name: "Buffersrc"},
	{Name: "CodecContext"},
	{Name: "CodecContext", Suffix: "2"},
	{Name: "CodecHardwareConfigMethod"},
	{Name: "Dictionary"},
	{Name: "Disposition"},
	{Name: "ErrorRecognition"},
	{Name: "Filter"},
	{Name: "FilterCommand"},
	{Name: "FormatContext"},
	{Name: "FormatContextCtx"},
	{Name: "FormatEvent"},
	{Name: "IOContext"},
	{Name: "IOFormat"},
	{Name: "OptionSearch"},
	{Name: "Packet"},
	{Name: "PixelFormatDescriptor"},
	{Name: "Seek"},
	{Name: "SoftwareScaleContext"},
	{Name: "StreamEvent"},
}

var tmpl = `// Code generated by astiav. DO NOT EDIT.
package astiav

import (
	"github.com/asticode/go-astikit"
)
{{ range $val := . }}
type {{ $val.Name }}Flags{{ $val.Suffix }} astikit.BitFlags

func New{{ $val.Name }}Flags{{ $val.Suffix }}(fs ...{{ $val.Name }}Flag{{ $val.Suffix }}) {{ $val.Name }}Flags{{ $val.Suffix }} {
	o := {{ $val.Name }}Flags{{ $val.Suffix }}(0)
	for _, f := range fs {
		o = o.Add(f)
	}
	return o
}

func (fs {{ $val.Name }}Flags{{ $val.Suffix }}) Add(f {{ $val.Name }}Flag{{ $val.Suffix }}) {{ $val.Name }}Flags{{ $val.Suffix }} {
	return {{ $val.Name }}Flags{{ $val.Suffix }}(astikit.BitFlags(fs).Add(uint64(f)))
}

func (fs {{ $val.Name }}Flags{{ $val.Suffix }}) Del(f {{ $val.Name }}Flag{{ $val.Suffix }}) {{ $val.Name }}Flags{{ $val.Suffix }} {
	return {{ $val.Name }}Flags{{ $val.Suffix }}(astikit.BitFlags(fs).Del(uint64(f)))
}

func (fs {{ $val.Name }}Flags{{ $val.Suffix }}) Has(f {{ $val.Name }}Flag{{ $val.Suffix }}) bool { return astikit.BitFlags(fs).Has(uint64(f)) }
{{ end }}`

var tmplTest = `// Code generated by astiav. DO NOT EDIT.
package astiav
import (
	"testing"

	"github.com/stretchr/testify/require"
)
{{ range $val := . }}
func Test{{ $val.Name }}Flags{{ $val.Suffix }}(t *testing.T) {
	fs := New{{ $val.Name }}Flags{{ $val.Suffix }}({{ $val.Name }}Flag{{ $val.Suffix }}(1))
	require.True(t, fs.Has({{ $val.Name }}Flag{{ $val.Suffix }}(1)))
	fs = fs.Add({{ $val.Name }}Flag{{ $val.Suffix }}(2))
	require.True(t, fs.Has({{ $val.Name }}Flag{{ $val.Suffix }}(2)))
	fs = fs.Del({{ $val.Name }}Flag{{ $val.Suffix }}(2))
	require.False(t, fs.Has({{ $val.Name }}Flag{{ $val.Suffix }}(2)))
}
{{ end }}`

func main() {
	dir, err := os.Getwd()
	if err != nil {
		log.Fatal(fmt.Errorf("main: getting working directory failed: %w", err))
	}

	f, err := os.Create(filepath.Join(dir, "flags.go"))
	if err != nil {
		log.Fatal(fmt.Errorf("main: creating file failed: %w", err))
	}
	defer f.Close()

	if err = template.Must(template.New("tmpl").Parse(tmpl)).Execute(f, list); err != nil {
		log.Fatal(fmt.Errorf("main: executing template failed: %w", err))
	}

	ft, err := os.Create(filepath.Join(dir, "flags_test.go"))
	if err != nil {
		log.Fatal(fmt.Errorf("main: creating test file failed: %w", err))
	}
	defer ft.Close()

	if err = template.Must(template.New("tmpl").Parse(tmplTest)).Execute(ft, list); err != nil {
		log.Fatal(fmt.Errorf("main: executing template failed: %w", err))
	}
}
