// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-2020 Datadog, Inc.

// +build ignore

// This program generates wrapper implementations of http.ResponseWriter that
// also satisfy http.Flusher, http.Pusher, http.CloseNotifier and http.Hijacker,
// based on whether or not the passed in http.ResponseWriter also satisfies
// them.

package main

import (
	"os"
	"text/template"

	"gopkg.in/DataDog/dd-trace-go.v1/contrib/internal/lists"
)

func main() {
	interfaces := []string{"Flusher", "Pusher", "CloseNotifier", "Hijacker"}
	var combos [][][]string
	for pick := len(interfaces); pick > 0; pick-- {
		combos = append(combos, lists.Combinations(interfaces, pick))
	}
	template.Must(template.New("").Parse(tpl)).Execute(os.Stdout, map[string]interface{}{
		"Interfaces":   interfaces,
		"Combinations": combos,
	})
}

var tpl = `// Code generated by make_responsewriter.go DO NOT EDIT

package httputil

import (
	"net/http"
	"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
)

// wrapResponseWriter wraps an underlying http.ResponseWriter so that it can
// trace the http response codes. It also checks for various http interfaces
// (Flusher, Pusher, CloseNotifier, Hijacker) and if the underlying
// http.ResponseWriter implements them it generates an unnamed struct with the
// appropriate fields.
//
// This code is generated because we have to account for all the permutations
// of the interfaces.
func wrapResponseWriter(w http.ResponseWriter, span ddtrace.Span) http.ResponseWriter {
{{- range .Interfaces }}
	h{{.}}, ok{{.}} := w.(http.{{.}})
{{- end }}

	w = newResponseWriter(w, span)
	switch {
{{- range .Combinations }}
	{{- range . }}
	case {{ range $i, $v := . }}{{ if gt $i 0 }} && {{ end }}ok{{ $v }}{{ end }}:
		w = struct {
			http.ResponseWriter
		{{- range . }}
			http.{{.}}
		{{- end }}
		} { w{{ range . }}, h{{.}}{{ end }} }
	{{- end }}
{{- end }}
	}

	return w
}
`
