// Copyright 2015 The Vanadium 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 java

import (
	"bytes"
	"fmt"
	"log"
	"path"

	"v.io/x/ref/lib/vdl/compile"
	"v.io/x/ref/lib/vdl/vdlutil"
)

const clientImplTmpl = header + `
// Source(s):  {{ .Source }}
package {{ .PackagePath }};

/**
 * Implementation of the {@link {{ .ServiceName }}Client} interface.
 */
final class {{ .ServiceName }}ClientImpl implements {{ .FullServiceName }}Client {
    private final io.v.v23.rpc.Client client;
    private final java.lang.String vName;

    {{/* Define fields to hold each of the embedded object impls*/}}
    {{ range $embed := .Embeds }}
    {{/* e.g. private final com.somepackage.ArithClient implArith; */}}
    private final {{ $embed.FullName }}Client impl{{ $embed.Name }};
    {{ end }}

    /**
     * Creates a new instance of {@link {{ .ServiceName }}ClientImpl}.
     *
     * @param client Vanadium client
     * @param vName  remote server name
     */
    public {{ .ServiceName }}ClientImpl(io.v.v23.rpc.Client client, java.lang.String vName) {
        this.client = client;
        this.vName = vName;
        {{/* Initialize the embeded impls */}}
        {{ range $embed := .Embeds }}
        {
            io.v.v23.Options opts = new io.v.v23.Options();
            opts.set(io.v.v23.OptionDefs.CLIENT, client);
            this.impl{{ $embed.Name }} = {{ $embed.FullName }}ClientFactory.get{{ $embed.Name }}Client(vName, opts);
        }
        {{ end }}
    }

    private io.v.v23.rpc.Client getClient(io.v.v23.context.VContext context) {
        return this.client != null ? client : io.v.v23.V.getClient(context);
    }

    // Methods from interface {{ .ServiceName }}Client.
{{/* Iterate over methods defined directly in the body of this service */}}
{{ range $method := .Methods }}
    {{/* The optionless overload simply calls the overload with options */}}
    @Override
    public {{ $method.RetType }} {{ $method.Name }}(io.v.v23.context.VContext _context{{ $method.DeclarationArgs }}) {
        return {{ $method.Name }}(_context{{ $method.CallingArgsLeadingComma }}, null);
    }
    @Override
    public {{ $method.RetType }} {{ $method.Name }}(final io.v.v23.context.VContext _context{{ $method.DeclarationArgs }}, io.v.v23.Options _opts) {
        {{/* Start the vanadium call */}}
        // Start the call.
        java.lang.Object[] _args = new java.lang.Object[]{ {{ $method.CallingArgs }} };
        java.lang.reflect.Type[] _argTypes = new java.lang.reflect.Type[]{ {{ $method.CallingArgTypes }} };
        final com.google.common.util.concurrent.ListenableFuture<io.v.v23.rpc.ClientCall> _callFuture = getClient(_context).startCall(_context, this.vName, "{{ $method.Name }}", _args, _argTypes, _opts);
        {{ if $method.NotStreaming }}
        return io.v.v23.VFutures.withUserLandChecks(_context, com.google.common.util.concurrent.Futures.transform(_callFuture, new com.google.common.util.concurrent.AsyncFunction<io.v.v23.rpc.ClientCall, {{ $method.OutArgType }}>() {
            @Override
            public com.google.common.util.concurrent.ListenableFuture<{{ $method.OutArgType }}> apply(final io.v.v23.rpc.ClientCall _call) throws Exception {
                {{ if $method.IsVoid }}
                java.lang.reflect.Type[] _resultTypes = new java.lang.reflect.Type[]{};

                {{ else }} {{/* else $method.IsVoid */}}
                java.lang.reflect.Type[] _resultTypes = new java.lang.reflect.Type[]{
                    {{ range $outArg := $method.OutArgs }}
                    {{ $outArg.ReflectType }},
                    {{ end }}
                };
                {{ end }} {{/* end if $method.IsVoid */}}
                // Finish the call.
                return com.google.common.util.concurrent.Futures.transform(_call.finish(_resultTypes), new com.google.common.base.Function<Object[], {{ $method.OutArgType }}>() {
                    @Override
                    public {{ $method.OutArgType }} apply(Object[] _results) {
                        {{ if $method.IsVoid }}
                            return null;
                        {{ else if $method.MultipleReturn }}
                        {{ $method.DeclaredObjectRetType }} _ret = new {{ $method.DeclaredObjectRetType }}();
                            {{ range $i, $outArg := $method.OutArgs }}
                        _ret.{{ $outArg.FieldName }} = ({{ $outArg.Type }})_results[{{ $i }}];
                            {{ end }} {{/* end range over outargs */}}
                        return _ret;
                        {{ else }} {{/* else if $method.MultipleReturn */}}
                        return ({{ $method.DeclaredObjectRetType }})_results[0];
                        {{ end }} {{/* end if $method.IsVoid */}}
                    }
                });
            }
        }));
        {{else }} {{/* else $method.NotStreaming */}}
        return new io.v.v23.vdl.ClientStream<{{ $method.SendType }}, {{ $method.RecvType }}, {{ $method.DeclaredObjectRetType }}>() {
             @Override
             public com.google.common.util.concurrent.ListenableFuture<Void> send(final {{ $method.SendType }} item) {
                 final java.lang.reflect.Type type = {{ $method.StreamSendReflectType }};
                 return io.v.v23.VFutures.withUserLandChecks(_context, com.google.common.util.concurrent.Futures.transform(_callFuture, new com.google.common.util.concurrent.AsyncFunction<io.v.v23.rpc.ClientCall, Void>() {
                     @Override
                     public com.google.common.util.concurrent.ListenableFuture<Void> apply(final io.v.v23.rpc.ClientCall _call) throws Exception {
                         return _call.send(item, type);
                     }
                 }));
             }
             @Override
             public com.google.common.util.concurrent.ListenableFuture<Void> close() {
                 return io.v.v23.VFutures.withUserLandChecks(_context, com.google.common.util.concurrent.Futures.transform(_callFuture, new com.google.common.util.concurrent.AsyncFunction<io.v.v23.rpc.ClientCall, Void>() {
                     @Override
                     public com.google.common.util.concurrent.ListenableFuture<Void> apply(final io.v.v23.rpc.ClientCall _call) throws Exception {
                         return _call.closeSend();
                     }
                 }));
             }
             @Override
             public com.google.common.util.concurrent.ListenableFuture<{{ $method.RecvType }}> recv() {
                 final java.lang.reflect.Type recvType = {{ $method.StreamRecvReflectType }};
                 return io.v.v23.VFutures.withUserLandChecks(_context, com.google.common.util.concurrent.Futures.transform(_callFuture, new com.google.common.util.concurrent.AsyncFunction<io.v.v23.rpc.ClientCall, {{ $method.RecvType }}>() {
                     @Override
                     public com.google.common.util.concurrent.ListenableFuture<{{ $method.RecvType }}> apply(final io.v.v23.rpc.ClientCall _call) throws Exception {
                         return com.google.common.util.concurrent.Futures.transform(_call.recv(recvType), new com.google.common.base.Function<Object, {{ $method.RecvType }}>() {
                             @Override
                             public {{ $method.RecvType }} apply(Object result) {
                                 return ({{ $method.RecvType }}) result;
                             }
                         });
                     }
                 }));
             }
             @Override
             public com.google.common.util.concurrent.ListenableFuture<{{ $method.DeclaredObjectRetType }}> finish() {
                 {{ if $method.IsVoid }}
                 final java.lang.reflect.Type[] resultTypes = new java.lang.reflect.Type[]{};
                 {{ else }} {{/* else $method.IsVoid */}}
                 final java.lang.reflect.Type[] resultTypes = new java.lang.reflect.Type[]{
                     {{ range $outArg := $method.OutArgs }}
                     {{ $outArg.ReflectType }},
                     {{ end }}
                 };
                 {{ end }} {{/* end if $method.IsVoid */}}
                 return io.v.v23.VFutures.withUserLandChecks(_context, com.google.common.util.concurrent.Futures.transform(_callFuture, new com.google.common.util.concurrent.AsyncFunction<io.v.v23.rpc.ClientCall, {{ $method.DeclaredObjectRetType }}>() {
                     @Override
                     public com.google.common.util.concurrent.ListenableFuture<{{ $method.DeclaredObjectRetType }}> apply(final io.v.v23.rpc.ClientCall _call) throws Exception {
                         return com.google.common.util.concurrent.Futures.transform(_call.finish(resultTypes), new com.google.common.base.Function<Object[], {{ $method.DeclaredObjectRetType }}>() {
                             @Override
                             public {{ $method.DeclaredObjectRetType }} apply(Object[] _results) {
                                 {{ if $method.IsVoid }}
                                 return null;
                                 {{ else if $method.MultipleReturn }}
                                 {{ $method.DeclaredObjectRetType }} _ret = new {{ $method.DeclaredObjectRetType }}();
                                 {{ range $i, $outArg := $method.OutArgs }}
                                     _ret.{{ $outArg.FieldName }} = ({{ $outArg.Type }})_results[{{ $i }}];
                                 {{ end }} {{/* end range over outargs */}}
                                 return _ret;
                                 {{ else }} {{/* else if $method.MultipleReturn */}}
                                 return ({{ $method.DeclaredObjectRetType }})_results[0];
                                 {{ end }} {{/* end if $method.IsVoid */}}
                             }
                         });
                     }
                 }));
             }
         };
         {{ end }}{{/* end if $method.NotStreaming */}}
     }
{{ end }}{{/* end range over methods */}}

{{/* Iterate over methods from embeded services and generate code to delegate the work */}}
{{ range $eMethod := .EmbedMethods }}
    @Override
    public {{ $eMethod.RetType }} {{ $eMethod.Name }}(io.v.v23.context.VContext _context{{ $eMethod.DeclarationArgs }}) {
        {{/* e.g. return this.implArith.cosine(context, [args]) */}}
        return this.impl{{ $eMethod.IfaceName }}.{{ $eMethod.Name }}(_context{{ $eMethod.CallingArgsLeadingComma }});
    }
    @Override
    public {{ $eMethod.RetType }} {{ $eMethod.Name }}(io.v.v23.context.VContext _context{{ $eMethod.DeclarationArgs }}, io.v.v23.Options _opts) {
        {{/* e.g. return this.implArith.cosine(_context, [args], options) */}}
        return this.impl{{ $eMethod.IfaceName }}.{{ $eMethod.Name }}(_context{{ $eMethod.CallingArgsLeadingComma }}, _opts);
    }
{{ end }}
}
`

type clientImplMethodOutArg struct {
	FieldName   string
	ReflectType string
	Type        string
}

type clientImplMethod struct {
	CallingArgs             string
	CallingArgTypes         string
	CallingArgsLeadingComma string
	DeclarationArgs         string
	DeclaredObjectRetType   string
	IsVoid                  bool
	MultipleReturn          bool
	Name                    string
	NotStreaming            bool
	OutArgs                 []clientImplMethodOutArg
	OutArgType              string
	StreamRecvReflectType   string
	RecvType                string
	RetType                 string
	StreamSendReflectType   string
	SendType                string
	ServiceName             string
}

type clientImplEmbedMethod struct {
	CallingArgsLeadingComma string
	DeclarationArgs         string
	IfaceName               string
	Name                    string
	RetType                 string
}

type clientImplEmbed struct {
	Name     string
	FullName string
}

func processClientImplMethod(iface *compile.Interface, method *compile.Method, env *compile.Env) clientImplMethod {
	outArgs := make([]clientImplMethodOutArg, len(method.OutArgs))
	for i := 0; i < len(method.OutArgs); i++ {
		if method.OutArgs[i].Name != "" {
			outArgs[i].FieldName = vdlutil.FirstRuneToLower(method.OutArgs[i].Name)
		} else {
			outArgs[i].FieldName = fmt.Sprintf("ret%d", i+1)
		}
		outArgs[i].Type = javaType(method.OutArgs[i].Type, true, env)
		outArgs[i].ReflectType = javaReflectType(method.OutArgs[i].Type, env)
	}
	return clientImplMethod{
		CallingArgs:             javaCallingArgStr(method.InArgs, false),
		CallingArgTypes:         javaCallingArgTypeStr(method.InArgs, env),
		CallingArgsLeadingComma: javaCallingArgStr(method.InArgs, true),
		DeclarationArgs:         javaDeclarationArgStr(method.InArgs, env, true),
		DeclaredObjectRetType:   clientInterfaceNonStreamingOutArg(iface, method, true, env),
		IsVoid:                  len(method.OutArgs) < 1,
		MultipleReturn:          len(method.OutArgs) > 1,
		Name:                    vdlutil.FirstRuneToLower(method.Name),
		NotStreaming:            !isStreamingMethod(method),
		OutArgs:                 outArgs,
		OutArgType:              clientInterfaceOutArg(iface, method, true, env),
		StreamRecvReflectType:   javaReflectType(method.OutStream, env),
		RecvType:                javaType(method.OutStream, true, env),
		RetType:                 clientInterfaceRetType(iface, method, env),
		StreamSendReflectType:   javaReflectType(method.InStream, env),
		SendType:                javaType(method.InStream, true, env),
		ServiceName:             vdlutil.FirstRuneToUpper(iface.Name),
	}
}

func processClientImplEmbedMethod(iface *compile.Interface, embedMethod *compile.Method, env *compile.Env) clientImplEmbedMethod {
	return clientImplEmbedMethod{
		CallingArgsLeadingComma: javaCallingArgStr(embedMethod.InArgs, true),
		DeclarationArgs:         javaDeclarationArgStr(embedMethod.InArgs, env, true),
		IfaceName:               vdlutil.FirstRuneToUpper(iface.Name),
		Name:                    vdlutil.FirstRuneToLower(embedMethod.Name),
		RetType:                 clientInterfaceRetType(iface, embedMethod, env),
	}
}

// genJavaClientImplFile generates a client impl for the specified interface.
func genJavaClientImplFile(iface *compile.Interface, env *compile.Env) JavaFileInfo {
	embeds := []clientImplEmbed{}
	for _, embed := range allEmbeddedIfaces(iface) {
		embeds = append(embeds, clientImplEmbed{
			Name:     vdlutil.FirstRuneToUpper(embed.Name),
			FullName: javaPath(javaGenPkgPath(path.Join(embed.File.Package.GenPath, vdlutil.FirstRuneToUpper(embed.Name)))),
		})
	}
	embedMethods := []clientImplEmbedMethod{}
	for _, embedMao := range dedupedEmbeddedMethodAndOrigins(iface) {
		embedMethods = append(embedMethods, processClientImplEmbedMethod(embedMao.Origin, embedMao.Method, env))
	}
	methods := make([]clientImplMethod, len(iface.Methods))
	for i, method := range iface.Methods {
		methods[i] = processClientImplMethod(iface, method, env)
	}
	javaServiceName := vdlutil.FirstRuneToUpper(iface.Name)
	data := struct {
		FileDoc         string
		EmbedMethods    []clientImplEmbedMethod
		Embeds          []clientImplEmbed
		FullServiceName string
		Methods         []clientImplMethod
		PackagePath     string
		ServiceName     string
		Source          string
	}{
		FileDoc:         iface.File.Package.FileDoc,
		EmbedMethods:    embedMethods,
		Embeds:          embeds,
		FullServiceName: javaPath(interfaceFullyQualifiedName(iface)),
		Methods:         methods,
		PackagePath:     javaPath(javaGenPkgPath(iface.File.Package.GenPath)),
		ServiceName:     javaServiceName,
		Source:          iface.File.BaseName,
	}
	var buf bytes.Buffer
	err := parseTmpl("client impl", clientImplTmpl).Execute(&buf, data)
	if err != nil {
		log.Fatalf("vdl: couldn't execute client impl template: %v", err)
	}
	return JavaFileInfo{
		Name: javaServiceName + "ClientImpl.java",
		Data: buf.Bytes(),
	}
}
