// Copyright 2018 The Fuchsia 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 codegen

const protocolTmpl = `
{{- define "Params" -}}
  {{- range $index, $param := . -}}
    {{- if $index }}, {{ end -}}{{ $param.Type.Decl }} {{ $param.Name }}
  {{- end -}}
{{ end }}

{{/* Generate a parameter list (eg "int foo, String baz") with AsyncDecl types */}}
{{- define "AsyncParams" -}}
  {{- range $index, $param := . -}}
    {{- if $index }}, {{ end -}}{{ $param.Type.Decl }} {{ $param.Name }}
  {{- end -}}
{{ end }}

{{- define "AsyncReturn" -}}
{{- if .HasResponse -}}
$async.Future<{{ .AsyncResponseType }}>
{{- else -}}
$async.Future<void>
{{- end -}}
{{- end -}}

{{- define "ForwardParams" -}}
{{ range $index, $param := . }}{{ if $index }}, {{ end }}{{ $param.Name }}{{ end }}
{{- end -}}

{{/*
  Decode a method response message.
  The current object is the method (ir.Method).
  The Dart local variables are:
    List<$fidl.MemberType> $types - the table for the response.
    $fidl.Message $message - the message being decoded.
  This template expands to an expression so it can be assigned or passed as an argument.
*/}}
{{- define "DecodeResponse" -}}
  {{- if .Response.HasError }}
    $fidl.decodeMessage($message, {{ .TypeSymbol }}.decodeResponseInlineSize(), $types[0])
  {{- else }}
    {{- if .AsyncResponseClass -}}
      $fidl.decodeMessageWithCallback<{{ .AsyncResponseClass }}>(
				$message,
				{{ .TypeSymbol }}.decodeResponseInlineSize(),
				($fidl.Decoder decoder) {
					return {{ .AsyncResponseClass }}(
						{{- range $index, $response := .Response.WireParameters }}
							$types[{{ $index }}].decode(decoder, $fidl.kMessageHeaderSize, 1),
						{{- end -}}
					);
				}
      )
    {{- else -}}
      {{- if .Response.WireParameters -}}
        $fidl.decodeMessage($message, {{ .TypeSymbol }}.decodeResponseInlineSize(), $types[0])
      {{- else -}}
        null
      {{- end -}}
    {{- end -}}
  {{- end -}}
{{ end -}}


{{/*
  Encode a method response message.
  The current object is the method (ir.Method).
  The Dart local variables are:
    List<$fidl.MemberType> $types - the table for the response.
    $fidl.Encoder $encoder - the encoder for the message.
    $response - the Dart response type.
  This template expands to a statement.
*/}}
{{- define "EncodeResponse" -}}
  {{- if (and .AsyncResponseClass (not .Response.HasError)) -}}
		$fidl.encodeMessageWithCallback(
			$encoder,
			{{ .TypeSymbol }}.encodingResponseInlineSize(),
			() {
				{{- range $index, $response := .Response.WireParameters }}
					$types[{{ $index }}].encode($encoder, $response.{{ .Name }}, $fidl.kMessageHeaderSize, 1);
				{{- end -}}
			}
		);
  {{- else -}}
    {{- if .Response.WireParameters -}}
			$fidl.encodeMessage($encoder, {{ .TypeSymbol }}.encodingResponseInlineSize(), $types[0], $response);
    {{- end -}}
  {{- end -}}
{{ end -}}

{{- define "InterfaceAsyncDeclaration" -}}

{{ range .Methods }}
// {{ .Name }}: {{ if .HasRequest }}({{ template "AsyncParams" .Request }}){{ end -}}
                {{- if .HasResponse }} -> ({{ template "AsyncParams" .Response.MethodParameters }}){{ end }}
const int {{ .OrdinalName }} = {{ .Ordinal | printf "%#x" }};
const $fidl.MethodType {{ .TypeSymbol }} = {{ .TypeExpr }};
{{- end }}

{{- range .Methods }}
  {{- if .AsyncResponseClass }}
class {{ .AsyncResponseClass }} {
    {{- range .Response.MethodParameters }}
  final {{ .Type.Decl }} {{ .Name }};
    {{- end }}
  {{ .AsyncResponseClass }}(
    {{- range .Response.MethodParameters }}
      this.{{ .Name }},
    {{- end -}}
    );
}
  {{- end }}
{{- end }}


{{- range .Doc }}
///{{ . -}}
{{- end }}
abstract class {{ .Name }} 
{{- if .ServiceName }}
      extends $fidl.Service
{{- end }}
      {
  {{- if .ServiceName }}
    static const String $serviceName = {{ .ServiceName }};
    @override
  {{- end }}
  $fidl.ServiceData? get $serviceData => {{ .ServiceData }}();

{{- range .Methods }}
  {{- if .HasRequest }}
    {{- range .Doc }}
    ///{{ . -}}
    {{- end }}
    {{ template "AsyncReturn" . }} {{ .Name }}({{ template "AsyncParams" .Request }})
    {{- if .Transitional }}
      { return $async.Future.error(UnimplementedError(), StackTrace.current); }
    {{- else }}
      ;
    {{- end }}
  {{- else }}
    {{- range .Doc }}
    ///{{ . -}}
    {{- end }}
    $async.Stream<{{ .AsyncResponseType}}>? get {{ .Name }}
    {{- if .Transitional }}
      { return $async.Stream.empty(); }
    {{- else }}
      ;
    {{- end }}
  {{- end }}
{{- end }}
}

// TODO: Remove ServiceData for non-service
class {{ .ServiceData }} implements $fidl.ServiceData<{{ .Name }}> {

  const {{ .ServiceData }}();

  @override
  String getName() {
    {{- if .ServiceName }}
    return {{ .Name }}.$serviceName;
    {{- else }}
    return "";
    {{- end }}
  }

  @override
  $fidl.AsyncBinding getBinding() {
    return {{ .BindingName }}();
  }
}

{{- range .Doc }}
///{{ . -}}
{{- end }}
class {{ .ProxyName }} extends $fidl.AsyncProxy<{{ .Name }}>
    implements {{ .Name }} {
  {{ .ProxyName }}() : super($fidl.AsyncProxyController<{{ .Name }}>(
      {{- if .ServiceName }}
        $serviceName: {{ .ServiceName }},
      {{- end }}
      $interfaceName: r'{{ .Name }}')
    ) {
    ctrl.onResponse = _handleResponse;

    {{- if .HasEvents }}
      ctrl.whenClosed.then((_) {
        {{- range .Methods }}
          {{- if not .HasRequest }}
            {{- if .HasResponse }}
              _{{ .Name }}EventStreamController.close();
            {{- end }}
          {{- end }}
        {{- end }}
      }, onError: (_) { });
    {{- end }}
  }

  {{- if .ServiceName }}
    @override
    $fidl.ServiceData get $serviceData => {{ .ServiceData }}();
  {{- else }}
    @override
    Null get $serviceData => null;
  {{- end }}

  void _handleEvent($fidl.IncomingMessage $message) {
    switch ($message.ordinal) {
{{- range .Methods }}
{{- if not .HasRequest }}
  {{- if .HasResponse }}
      case {{ .OrdinalName }}:
        final String _name = {{ .TypeSymbol }}.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response!;
          _{{ .Name }}EventStreamController.add(
            {{- template "DecodeResponse" . -}}
          );
        } catch(_e) {
          ctrl.proxyError($fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
  {{- end }}
{{- end }}
{{- end }}
      default:
        ctrl.proxyError($fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

  void _handleResponse($fidl.IncomingMessage $message) {
    final int $txid = $message.txid;
    if ($txid == 0) {
      _handleEvent($message);
      return;
    }
    final $async.Completer? $completer = ctrl.getCompleter($txid);
    if ($completer == null) {
      $message.closeHandles();
      return;
    }
    switch ($message.ordinal) {
{{- range .Methods }}
  {{- if .HasRequest }}
    {{- if .HasResponse }}
      case {{ .OrdinalName }}:
        final String _name = {{ .TypeSymbol }}.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response!;
          // ignore: prefer_const_declarations
          final $response = {{- template "DecodeResponse" . -}};
          {{ if .Response.HasError }}
            if ($response.$tag == {{ .Response.ResultType.TagName }}.response) {
              {{ if .AsyncResponseClass }}
                $completer.complete(
                  {{ .AsyncResponseClass }}(
                  {{ range $param := .Response.MethodParameters }}
                    $response.response.{{ $param.Name }},
                  {{ end }}
                  ));
              {{ else }}
                {{ if (eq .AsyncResponseType "void") }}
                  $completer.complete(null);
                {{ else }}
                  $completer.complete($response.response.{{ (index .Response.MethodParameters 0).Name }});
                {{ end }}
              {{ end }}
            } else {
              $completer.completeError($fidl.MethodException($response.err));
            }
          {{ else }}
            $completer.complete($response);
          {{ end }}
        } catch(_e) {
          ctrl.proxyError($fidl.FidlError('Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
    {{- end }}
  {{- end }}
{{- end }}
      default:
        ctrl.proxyError($fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

{{- range .Methods }}
  {{- if .HasRequest }}
    {{- range .Doc }}
    ///{{ . -}}
    {{- end }}
    @override
    {{ template "AsyncReturn" . }} {{ .Name }}({{ template "AsyncParams" .Request }}) async {
      if (!ctrl.isBound) {
        return $async.Future.error($fidl.FidlStateException('Proxy<${ctrl.$interfaceName}> is closed.'), StackTrace.current);
      }

      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader({{ .OrdinalName }}, 0);
      {{- if .Request }}
        final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.request!;
				$fidl.encodeMessageWithCallback(
					$encoder,
					{{ .TypeSymbol }}.encodingRequestInlineSize(),
					() {
						{{- range $index, $request := .Request }}
							$types[{{ $index }}].encode($encoder, {{ .Name }}, $fidl.kMessageHeaderSize, 1);
						{{- end -}}
					}
				);
      {{- end }}

      {{- if .HasResponse }}
        final $completer = $async.Completer<{{ .AsyncResponseType }}>();
        ctrl.sendMessageWithResponse($encoder.message, $completer);
        return $completer.future;
      {{- else }}
        return $async.Future.sync(() {
          ctrl.sendMessage($encoder.message);
        });
      {{- end }}
    }
  {{ else }}
    final _{{ .Name }}EventStreamController = $async.StreamController<{{ .AsyncResponseType }}>.broadcast();
    {{- range .Doc }}
    ///{{ . -}}
    {{- end }}
    @override
    $async.Stream<{{ .AsyncResponseType }}> get {{ .Name }} => _{{ .Name }}EventStreamController.stream;
  {{ end }}
{{- end }}
}

class {{ .BindingName }} extends $fidl.AsyncBinding<{{ .Name }}> {
  {{ .BindingName }}() : super(r"{{ .Name }}")
  {{- if .HasEvents }} {
    final List<$async.StreamSubscription<dynamic>> $subscriptions = [];
    void $unsubscribe() {
      for (final $sub in $subscriptions) {
        $sub.cancel();
      }
      $subscriptions.clear();
    }
    whenBound.then((_) {
      final impl = this.impl;
      if (impl != null) {
        {{- range .Methods }}
          {{- if not .HasRequest }}
            final _{{ .Name }}_stream = impl.{{ .Name }};
            if (_{{ .Name }}_stream != null) {
              $subscriptions.add(_{{ .Name }}_stream.listen(($response) {
                final $fidl.Encoder $encoder = $fidl.Encoder();
                $encoder.encodeMessageHeader({{ .OrdinalName }}, 0);
                final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response!;
                {{ template "EncodeResponse" . }}
                sendMessage($encoder.message);
              }));
            }
          {{- end }}
        {{- end }}
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }
  {{- else -}}
    ;
  {{- end }}

  @override
  void handleMessage($fidl.IncomingMessage $message, $fidl.OutgoingMessageSink $respond) {
    switch ($message.ordinal) {
    {{- range .Methods }}
      {{- if .HasRequest }}
          case {{ .OrdinalName }}:
            final String _name = {{ .TypeSymbol }}.name;
            try {
              Timeline.startSync(_name);
              final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.request!;
							// ignore: prefer_const_declarations
							final _impl = impl!;
							final {{ template "AsyncReturn" . }} $future = $fidl.decodeMessageWithCallback<{{ template "AsyncReturn" . }}>(
								$message,
								{{ .TypeSymbol }}.decodeRequestInlineSize(),
								($fidl.Decoder decoder) {
									return _impl.{{ .Name }}(
										{{- range $index, $request := .Request }}
											$types[{{ $index }}].decode(decoder, $fidl.kMessageHeaderSize, 1),
										{{- end }}
									);
								}
							);

              {{- if .HasResponse }}
                $future
                {{ if .Response.HasError }}
                .then(($responseValue) {
                  {{ if .AsyncResponseClass }}
                    return {{ .Response.ResultType.Name }}.withResponse(
                      {{ .Response.ValueType.Decl }}(
                      {{ range $param := .Response.MethodParameters }}
                        {{ $param.Name }}: $responseValue.{{ $param.Name }},
                      {{ end }}
                      ));
                  {{ else }}
                    return {{ .Response.ResultType.Name }}.withResponse(
                      {{ .Response.ValueType.Decl }}(
                        {{ if (ne .AsyncResponseType "void") }}
                          {{ (index .Response.MethodParameters 0).Name }}: $responseValue
                        {{ end }}
                        ));
                  {{ end }}
                }, onError: ($error) {
                  if ($error is $fidl.MethodException) {
                    return {{ .Response.ResultType.Name }}.withErr($error.value);
                  } else {
                    return Future.error($error, StackTrace.current);
                  }
                })
                {{ end }}
                .then(($response) {
                  final $fidl.Encoder $encoder = $fidl.Encoder();
                  $encoder.encodeMessageHeader({{ .OrdinalName }}, $message.txid);
                  {{- if .Response.WireParameters }}
                    final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response!;
                    {{ template "EncodeResponse" . -}}
                  {{- end }}
                  $respond($encoder.message);
                }, onError: (_e) {
                  close();
                  print('Exception handling method call $_name: $_e');
                });
              {{- end }}
            } catch(_e) {
              close();
              print('Exception handling method call $_name: $_e');
              rethrow;
            } finally {
              Timeline.finishSync();
            }
            break;
      {{- end }}
    {{- end }}
      default:
        throw $fidl.FidlError(r'Unexpected message name for {{ .BindingName }}');
    }
  }
}

{{ end }}



{{- define "InterfaceTestDeclaration" -}}

class {{ .Name }}$TestBase extends {{ .Name }} {
  {{- $protocolName := .Name }}
  {{- range .Methods }}
  {{- $exceptionMessage := printf "r'%s not implemented on %s test base. Please implement.'"  .Name  $protocolName }}
  @override
  {{- if .HasRequest }}
  {{ template "AsyncReturn" . }} {{ .Name }}({{ template "AsyncParams" .Request }}) {
    return $async.Future.error(UnimplementedError({{ $exceptionMessage }}), StackTrace.current);
  }
  {{- else }}
  $async.Stream<{{ .AsyncResponseType }}> get {{ .Name }} {
    return $async.Stream.fromFuture($async.Future.error(UnimplementedError({{ $exceptionMessage }}), StackTrace.current));
  }
  {{- end }}
{{- end }}

}

{{ end }}

`
