// Copyright 2013 The Flutter 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 io.flutter.plugin.common;

import androidx.annotation.NonNull;
import io.flutter.plugin.common.StandardMessageCodec.ExposedByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * A {@link MethodCodec} using the Flutter standard binary encoding.
 *
 * <p>This codec is guaranteed to be compatible with the corresponding <a
 * href="https://api.flutter.dev/flutter/services/StandardMethodCodec-class.html">StandardMethodCodec</a>
 * on the Dart side. These parts of the Flutter SDK are evolved synchronously.
 *
 * <p>Values supported as method arguments and result payloads are those supported by {@link
 * StandardMessageCodec}.
 */
public final class StandardMethodCodec implements MethodCodec {
  public static final StandardMethodCodec INSTANCE =
      new StandardMethodCodec(StandardMessageCodec.INSTANCE);
  private final StandardMessageCodec messageCodec;

  /** Creates a new method codec based on the specified message codec. */
  public StandardMethodCodec(@NonNull StandardMessageCodec messageCodec) {
    this.messageCodec = messageCodec;
  }

  @Override
  @NonNull
  public ByteBuffer encodeMethodCall(@NonNull MethodCall methodCall) {
    final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
    messageCodec.writeValue(stream, methodCall.method);
    messageCodec.writeValue(stream, methodCall.arguments);
    final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
    buffer.put(stream.buffer(), 0, stream.size());
    return buffer;
  }

  @Override
  @NonNull
  public MethodCall decodeMethodCall(@NonNull ByteBuffer methodCall) {
    methodCall.order(ByteOrder.nativeOrder());
    final Object method = messageCodec.readValue(methodCall);
    final Object arguments = messageCodec.readValue(methodCall);
    if (method instanceof String && !methodCall.hasRemaining()) {
      return new MethodCall((String) method, arguments);
    }
    throw new IllegalArgumentException("Method call corrupted");
  }

  @Override
  @NonNull
  public ByteBuffer encodeSuccessEnvelope(@NonNull Object result) {
    final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
    stream.write(0);
    messageCodec.writeValue(stream, result);
    final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
    buffer.put(stream.buffer(), 0, stream.size());
    return buffer;
  }

  @Override
  @NonNull
  public ByteBuffer encodeErrorEnvelope(
      @NonNull String errorCode, @NonNull String errorMessage, @NonNull Object errorDetails) {
    final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
    stream.write(1);
    messageCodec.writeValue(stream, errorCode);
    messageCodec.writeValue(stream, errorMessage);
    if (errorDetails instanceof Throwable) {
      messageCodec.writeValue(stream, getStackTrace((Throwable) errorDetails));
    } else {
      messageCodec.writeValue(stream, errorDetails);
    }
    final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
    buffer.put(stream.buffer(), 0, stream.size());
    return buffer;
  }

  @Override
  @NonNull
  public ByteBuffer encodeErrorEnvelopeWithStacktrace(
      @NonNull String errorCode,
      @NonNull String errorMessage,
      @NonNull Object errorDetails,
      @NonNull String errorStacktrace) {
    final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
    stream.write(1);
    messageCodec.writeValue(stream, errorCode);
    messageCodec.writeValue(stream, errorMessage);
    if (errorDetails instanceof Throwable) {
      messageCodec.writeValue(stream, getStackTrace((Throwable) errorDetails));
    } else {
      messageCodec.writeValue(stream, errorDetails);
    }
    messageCodec.writeValue(stream, errorStacktrace);
    final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
    buffer.put(stream.buffer(), 0, stream.size());
    return buffer;
  }

  @Override
  @NonNull
  public Object decodeEnvelope(@NonNull ByteBuffer envelope) {
    envelope.order(ByteOrder.nativeOrder());
    final byte flag = envelope.get();
    switch (flag) {
      case 0:
        {
          final Object result = messageCodec.readValue(envelope);
          if (!envelope.hasRemaining()) {
            return result;
          }
        }
        // Falls through intentionally.
      case 1:
        {
          final Object code = messageCodec.readValue(envelope);
          final Object message = messageCodec.readValue(envelope);
          final Object details = messageCodec.readValue(envelope);
          if (code instanceof String
              && (message == null || message instanceof String)
              && !envelope.hasRemaining()) {
            throw new FlutterException((String) code, (String) message, details);
          }
        }
    }
    throw new IllegalArgumentException("Envelope corrupted");
  }

  @NonNull
  private static String getStackTrace(@NonNull Throwable t) {
    Writer result = new StringWriter();
    t.printStackTrace(new PrintWriter(result));
    return result.toString();
  }
}
