package gen

var replayTemplate = `//Create{{.Name}}Consumer is a method that builds a replayer that writes to a {{.Name}} object from
//kinesis.
func Create{{.Name}}Consumer(inner {{.Name}}, logLevel comparison.LogLevel, comparePreprocessor comparison.ComparePreprocessor
    {{- if .AcceptErrorCheck -}}
        , errCheck migration.ErrorCheck
    {{- end -}}
) migration.Replayer {
    return &consumer_{{.Name}}{
        inner: inner,
        logLevel: logLevel,
        comparePreprocessor: comparePreprocessor,
        errCheck: 
            {{- if .AcceptErrorCheck -}}
                errCheck
            {{- else -}}
                &migration.DefaultErrorCheck{}
            {{- end}},
    }
}

type consumer_{{.Name}} struct {
    inner {{.Name}}
    errCheck migration.ErrorCheck
    logLevel comparison.LogLevel
    comparePreprocessor comparison.ComparePreprocessor
}

//InterfaceName returns the name to use in stats & other places
func (self *consumer_{{.Name}}) InterfaceName() string {
    return "{{.Name}}"
}

func (self *consumer_{{.Name}}) LogLevel() comparison.LogLevel {
    return self.logLevel
}

func (self *consumer_{{.Name}}) ComparePreprocessor() comparison.ComparePreprocessor {
    return self.comparePreprocessor
}

//ReplayCall receives a context, method name, and serialized kinesis record and replays the call that caused
//the kinesis record to be written.  It will then return the original and replay call results so that they
//can be compared.
func (self *consumer_{{.Name}}) ReplayCall(context context.Context, methodName string, json []byte) ([]interface{}, error) {
    switch(methodName) {
        {{range .Methods -}}
            {{- if not .Ignore -}}
                case "{{.Name}}": {
                    //Replay a {{.Name}} call
                    return self.Replay{{.Name}}Call(context, json)
                }       
            {{end -}}
        {{- end -}}
        default: {
            return []interface{}{}, fmt.Errorf("Unknown method '{{.Name}}.%s'- has the interface definition changed?", methodName)
        }
    }
}

{{- $intfc := .Name}}
{{range .Methods -}}
    {{- $mthd := .Name -}}
    {{- if not .Ignore}}
        //{{$intfc}}{{.Name}}Message represents a deserialized kinesis replay record
        //for the {{.Name}} method
        type {{$intfc}}{{.Name}}Message struct {
            {{range $index, $param := .Params -}}
                {{- if not .IsContext -}}
                    Param_{{$param.Name}} {{$param.Type}}
                {{- end}}
            {{end}}
        }
        func (self *consumer_{{$intfc}}) Replay{{.Name}}Call(context context.Context, jsonData []byte) (newResults []interface{}, err error) {
            
            //Initialize old & new results, and the value to deserialize to
            newResults = []interface{}{}
            deserializedMessage := {{$intfc}}{{.Name}}Message{}

            //Deserialize kinesis record to struct
            err = json.Unmarshal(jsonData, &deserializedMessage)
            if err != nil {
                log.Fatalln(err)
                return
            }

            //Replay
            {{range $index, $result := .Results -}}
                {{- if $index}}, {{end -}}
                retVal{{add $index 1 -}}
            {{- end -}}
            {{- if len .Results}} := {{end -}}
            self.inner.{{.Name}}(
                {{- range $index, $param := .Params -}}
                    {{- if .IsContext -}}
                        context,
                    {{- else -}}
                        deserializedMessage.Param_{{- $param.Name -}},
                    {{- end}}
                {{end -}}
            )
            
            {{range $index, $result := .Results}}
                {{- if $result.IsError -}}
                    //Bail if the replay had a serious error
                    if retVal{{add $index 1}} != nil && self.errCheck.SeriousError(retVal{{add $index 1}}) {
                        err = retVal{{add $index 1}}
                        return
                    }
                {{- end -}}
            {{- end}}
            
            //If the replay worked out, record the results
            newResults = []interface{}{
                {{- range $index, $result := .Results -}}
                    {{- if $index}}, {{end -}}
                    retVal{{add $index 1}}
                {{- end -}}
            }
            return
        }
    {{end -}}
{{- end -}}
`
