// +build ignore

package main

import (
	"bytes"
	"go/format"
	"log"
	"os"
	"sort"
	"strings"
	"text/template"

	"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

const filename = `get_tag_gen.go`

var serviceNames = []string{
	"autoscaling",
	"batch",
	"dynamodb",
	"ec2",
	"ecs",
	"route53resolver",
}

type TemplateData struct {
	ServiceNames []string
}

func main() {
	// Always sort to reduce any potential generation churn
	sort.Strings(serviceNames)

	templateData := TemplateData{
		ServiceNames: serviceNames,
	}
	templateFuncMap := template.FuncMap{
		"ClientType":                        keyvaluetags.ServiceClientType,
		"ListTagsFunction":                  keyvaluetags.ServiceListTagsFunction,
		"ListTagsInputFilterIdentifierName": keyvaluetags.ServiceListTagsInputFilterIdentifierName,
		"ListTagsOutputTagsField":           keyvaluetags.ServiceListTagsOutputTagsField,
		"TagPackage":                        keyvaluetags.ServiceTagPackage,
		"TagResourceTypeField":              keyvaluetags.ServiceTagResourceTypeField,
		"TagTypeAdditionalBoolFields":       keyvaluetags.ServiceTagTypeAdditionalBoolFields,
		"TagTypeIdentifierField":            keyvaluetags.ServiceTagTypeIdentifierField,
		"Title":                             strings.Title,
	}

	tmpl, err := template.New("gettag").Funcs(templateFuncMap).Parse(templateBody)

	if err != nil {
		log.Fatalf("error parsing template: %s", err)
	}

	var buffer bytes.Buffer
	err = tmpl.Execute(&buffer, templateData)

	if err != nil {
		log.Fatalf("error executing template: %s", err)
	}

	generatedFileContents, err := format.Source(buffer.Bytes())

	if err != nil {
		log.Fatalf("error formatting generated file: %s", err)
	}

	f, err := os.Create(filename)

	if err != nil {
		log.Fatalf("error creating file (%s): %s", filename, err)
	}

	defer f.Close()

	_, err = f.Write(generatedFileContents)

	if err != nil {
		log.Fatalf("error writing to file (%s): %s", filename, err)
	}
}

var templateBody = `
// Code generated by generators/gettag/main.go; DO NOT EDIT.

package keyvaluetags

import (
	"github.com/aws/aws-sdk-go/aws"
{{- range .ServiceNames }}
	"github.com/aws/aws-sdk-go/service/{{ . }}"
{{- end }}
)

{{- range .ServiceNames }}

// {{ . | Title }}GetTag fetches an individual {{ . }} service tag for a resource.
// Returns whether the key exists, the key value, and any errors.
// This function will optimise the handling over {{ . | Title }}ListTags, if possible.
// The identifier is typically the Amazon Resource Name (ARN), although
// it may also be a different identifier depending on the service.
{{- if or ( . | TagTypeIdentifierField ) ( . | TagTypeAdditionalBoolFields) }}
func {{ . | Title }}GetTag(conn {{ . | ClientType }}, identifier string{{ if . | TagResourceTypeField }}, resourceType string{{ end }}, key string) (bool, *TagData, error) {
{{- else }}
func {{ . | Title }}GetTag(conn {{ . | ClientType }}, identifier string{{ if . | TagResourceTypeField }}, resourceType string{{ end }}, key string) (bool, *string, error) {
{{- end }}
	{{- if . | ListTagsInputFilterIdentifierName }}
	input := &{{ . | TagPackage  }}.{{ . | ListTagsFunction }}Input{
		Filters: []*{{ . | TagPackage  }}.Filter{
			{
				Name:   aws.String("{{ . | ListTagsInputFilterIdentifierName }}"),
				Values: []*string{aws.String(identifier)},
			},
			{
				Name:   aws.String("key"),
				Values: []*string{aws.String(key)},
			},
		},
	}

	output, err := conn.{{ . | ListTagsFunction }}(input)

	if err != nil {
		return false, nil, err
	}

	listTags := {{ . | Title }}KeyValueTags(output.{{ . | ListTagsOutputTagsField }}{{ if . | TagTypeIdentifierField }}, identifier{{ if . | TagResourceTypeField }}, resourceType{{ end }}{{ end }})
	{{- else }}
	listTags, err := {{ . | Title }}ListTags(conn, identifier{{ if . | TagResourceTypeField }}, resourceType{{ end }})

	if err != nil {
		return false, nil, err
	}
	{{- end }}

	{{ if or ( . | TagTypeIdentifierField ) ( . | TagTypeAdditionalBoolFields) }}
	return listTags.KeyExists(key), listTags.KeyTagData(key), nil
	{{- else }}
	return listTags.KeyExists(key), listTags.KeyValue(key), nil
	{{- end }}
}
{{- end }}
`
