// 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.

// Autogenerated from Pigeon (v1.0.9), do not edit directly.
// See also: https://pub.dev/packages/pigeon

package io.flutter.plugins.webviewflutter;

import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.common.StandardMessageCodec;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** Generated class from Pigeon. */
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"})
public class GeneratedAndroidWebView {

  /** Generated class from Pigeon that represents data sent in messages. */
  public static class WebResourceRequestData {
    private String url;

    public String getUrl() {
      return url;
    }

    public void setUrl(String setterArg) {
      this.url = setterArg;
    }

    private Boolean isForMainFrame;

    public Boolean getIsForMainFrame() {
      return isForMainFrame;
    }

    public void setIsForMainFrame(Boolean setterArg) {
      this.isForMainFrame = setterArg;
    }

    private Boolean isRedirect;

    public Boolean getIsRedirect() {
      return isRedirect;
    }

    public void setIsRedirect(Boolean setterArg) {
      this.isRedirect = setterArg;
    }

    private Boolean hasGesture;

    public Boolean getHasGesture() {
      return hasGesture;
    }

    public void setHasGesture(Boolean setterArg) {
      this.hasGesture = setterArg;
    }

    private String method;

    public String getMethod() {
      return method;
    }

    public void setMethod(String setterArg) {
      this.method = setterArg;
    }

    private Map<String, String> requestHeaders;

    public Map<String, String> getRequestHeaders() {
      return requestHeaders;
    }

    public void setRequestHeaders(Map<String, String> setterArg) {
      this.requestHeaders = setterArg;
    }

    Map<String, Object> toMap() {
      Map<String, Object> toMapResult = new HashMap<>();
      toMapResult.put("url", url);
      toMapResult.put("isForMainFrame", isForMainFrame);
      toMapResult.put("isRedirect", isRedirect);
      toMapResult.put("hasGesture", hasGesture);
      toMapResult.put("method", method);
      toMapResult.put("requestHeaders", requestHeaders);
      return toMapResult;
    }

    static WebResourceRequestData fromMap(Map<String, Object> map) {
      WebResourceRequestData fromMapResult = new WebResourceRequestData();
      Object url = map.get("url");
      fromMapResult.url = (String) url;
      Object isForMainFrame = map.get("isForMainFrame");
      fromMapResult.isForMainFrame = (Boolean) isForMainFrame;
      Object isRedirect = map.get("isRedirect");
      fromMapResult.isRedirect = (Boolean) isRedirect;
      Object hasGesture = map.get("hasGesture");
      fromMapResult.hasGesture = (Boolean) hasGesture;
      Object method = map.get("method");
      fromMapResult.method = (String) method;
      Object requestHeaders = map.get("requestHeaders");
      fromMapResult.requestHeaders = (Map<String, String>) requestHeaders;
      return fromMapResult;
    }
  }

  /** Generated class from Pigeon that represents data sent in messages. */
  public static class WebResourceErrorData {
    private Long errorCode;

    public Long getErrorCode() {
      return errorCode;
    }

    public void setErrorCode(Long setterArg) {
      this.errorCode = setterArg;
    }

    private String description;

    public String getDescription() {
      return description;
    }

    public void setDescription(String setterArg) {
      this.description = setterArg;
    }

    Map<String, Object> toMap() {
      Map<String, Object> toMapResult = new HashMap<>();
      toMapResult.put("errorCode", errorCode);
      toMapResult.put("description", description);
      return toMapResult;
    }

    static WebResourceErrorData fromMap(Map<String, Object> map) {
      WebResourceErrorData fromMapResult = new WebResourceErrorData();
      Object errorCode = map.get("errorCode");
      fromMapResult.errorCode =
          (errorCode == null)
              ? null
              : ((errorCode instanceof Integer) ? (Integer) errorCode : (Long) errorCode);
      Object description = map.get("description");
      fromMapResult.description = (String) description;
      return fromMapResult;
    }
  }

  public interface Result<T> {
    void success(T result);

    void error(Throwable error);
  }

  private static class WebViewHostApiCodec extends StandardMessageCodec {
    public static final WebViewHostApiCodec INSTANCE = new WebViewHostApiCodec();

    private WebViewHostApiCodec() {}
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
  public interface WebViewHostApi {
    void create(Long instanceId, Boolean useHybridComposition);

    void dispose(Long instanceId);

    void loadData(Long instanceId, String data, String mimeType, String encoding);

    void loadDataWithBaseUrl(
        Long instanceId,
        String baseUrl,
        String data,
        String mimeType,
        String encoding,
        String historyUrl);

    void loadUrl(Long instanceId, String url, Map<String, String> headers);

    String getUrl(Long instanceId);

    Boolean canGoBack(Long instanceId);

    Boolean canGoForward(Long instanceId);

    void goBack(Long instanceId);

    void goForward(Long instanceId);

    void reload(Long instanceId);

    void clearCache(Long instanceId, Boolean includeDiskFiles);

    void evaluateJavascript(Long instanceId, String javascriptString, Result<String> result);

    String getTitle(Long instanceId);

    void scrollTo(Long instanceId, Long x, Long y);

    void scrollBy(Long instanceId, Long x, Long y);

    Long getScrollX(Long instanceId);

    Long getScrollY(Long instanceId);

    void setWebContentsDebuggingEnabled(Boolean enabled);

    void setWebViewClient(Long instanceId, Long webViewClientInstanceId);

    void addJavaScriptChannel(Long instanceId, Long javaScriptChannelInstanceId);

    void removeJavaScriptChannel(Long instanceId, Long javaScriptChannelInstanceId);

    void setDownloadListener(Long instanceId, Long listenerInstanceId);

    void setWebChromeClient(Long instanceId, Long clientInstanceId);

    void setBackgroundColor(Long instanceId, Long color);

    /** The codec used by WebViewHostApi. */
    static MessageCodec<Object> getCodec() {
      return WebViewHostApiCodec.INSTANCE;
    }

    /** Sets up an instance of `WebViewHostApi` to handle messages through the `binaryMessenger`. */
    static void setup(BinaryMessenger binaryMessenger, WebViewHostApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.create", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean useHybridCompositionArg = (Boolean) args.get(1);
                  if (useHybridCompositionArg == null) {
                    throw new NullPointerException("useHybridCompositionArg unexpectedly null.");
                  }
                  api.create(instanceIdArg.longValue(), useHybridCompositionArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.dispose", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  api.dispose(instanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.loadData", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String dataArg = (String) args.get(1);
                  if (dataArg == null) {
                    throw new NullPointerException("dataArg unexpectedly null.");
                  }
                  String mimeTypeArg = (String) args.get(2);
                  if (mimeTypeArg == null) {
                    throw new NullPointerException("mimeTypeArg unexpectedly null.");
                  }
                  String encodingArg = (String) args.get(3);
                  if (encodingArg == null) {
                    throw new NullPointerException("encodingArg unexpectedly null.");
                  }
                  api.loadData(instanceIdArg.longValue(), dataArg, mimeTypeArg, encodingArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.loadDataWithBaseUrl",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String baseUrlArg = (String) args.get(1);
                  if (baseUrlArg == null) {
                    throw new NullPointerException("baseUrlArg unexpectedly null.");
                  }
                  String dataArg = (String) args.get(2);
                  if (dataArg == null) {
                    throw new NullPointerException("dataArg unexpectedly null.");
                  }
                  String mimeTypeArg = (String) args.get(3);
                  if (mimeTypeArg == null) {
                    throw new NullPointerException("mimeTypeArg unexpectedly null.");
                  }
                  String encodingArg = (String) args.get(4);
                  if (encodingArg == null) {
                    throw new NullPointerException("encodingArg unexpectedly null.");
                  }
                  String historyUrlArg = (String) args.get(5);
                  if (historyUrlArg == null) {
                    throw new NullPointerException("historyUrlArg unexpectedly null.");
                  }
                  api.loadDataWithBaseUrl(
                      instanceIdArg.longValue(),
                      baseUrlArg,
                      dataArg,
                      mimeTypeArg,
                      encodingArg,
                      historyUrlArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.loadUrl", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String urlArg = (String) args.get(1);
                  if (urlArg == null) {
                    throw new NullPointerException("urlArg unexpectedly null.");
                  }
                  Map<String, String> headersArg = (Map<String, String>) args.get(2);
                  if (headersArg == null) {
                    throw new NullPointerException("headersArg unexpectedly null.");
                  }
                  api.loadUrl(instanceIdArg.longValue(), urlArg, headersArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getUrl", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String output = api.getUrl(instanceIdArg.longValue());
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.canGoBack", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean output = api.canGoBack(instanceIdArg.longValue());
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.canGoForward", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean output = api.canGoForward(instanceIdArg.longValue());
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.goBack", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  api.goBack(instanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.goForward", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  api.goForward(instanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.reload", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  api.reload(instanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.clearCache", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean includeDiskFilesArg = (Boolean) args.get(1);
                  if (includeDiskFilesArg == null) {
                    throw new NullPointerException("includeDiskFilesArg unexpectedly null.");
                  }
                  api.clearCache(instanceIdArg.longValue(), includeDiskFilesArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.evaluateJavascript",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String javascriptStringArg = (String) args.get(1);
                  if (javascriptStringArg == null) {
                    throw new NullPointerException("javascriptStringArg unexpectedly null.");
                  }
                  Result<String> resultCallback =
                      new Result<String>() {
                        public void success(String result) {
                          wrapped.put("result", result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          wrapped.put("error", wrapError(error));
                          reply.reply(wrapped);
                        }
                      };

                  api.evaluateJavascript(
                      instanceIdArg.longValue(), javascriptStringArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                  reply.reply(wrapped);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getTitle", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String output = api.getTitle(instanceIdArg.longValue());
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.scrollTo", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number xArg = (Number) args.get(1);
                  if (xArg == null) {
                    throw new NullPointerException("xArg unexpectedly null.");
                  }
                  Number yArg = (Number) args.get(2);
                  if (yArg == null) {
                    throw new NullPointerException("yArg unexpectedly null.");
                  }
                  api.scrollTo(instanceIdArg.longValue(), xArg.longValue(), yArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.scrollBy", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number xArg = (Number) args.get(1);
                  if (xArg == null) {
                    throw new NullPointerException("xArg unexpectedly null.");
                  }
                  Number yArg = (Number) args.get(2);
                  if (yArg == null) {
                    throw new NullPointerException("yArg unexpectedly null.");
                  }
                  api.scrollBy(instanceIdArg.longValue(), xArg.longValue(), yArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getScrollX", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Long output = api.getScrollX(instanceIdArg.longValue());
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.getScrollY", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Long output = api.getScrollY(instanceIdArg.longValue());
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.setWebContentsDebuggingEnabled",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Boolean enabledArg = (Boolean) args.get(0);
                  if (enabledArg == null) {
                    throw new NullPointerException("enabledArg unexpectedly null.");
                  }
                  api.setWebContentsDebuggingEnabled(enabledArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewHostApi.setWebViewClient", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number webViewClientInstanceIdArg = (Number) args.get(1);
                  if (webViewClientInstanceIdArg == null) {
                    throw new NullPointerException("webViewClientInstanceIdArg unexpectedly null.");
                  }
                  api.setWebViewClient(
                      instanceIdArg.longValue(), webViewClientInstanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.addJavaScriptChannel",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number javaScriptChannelInstanceIdArg = (Number) args.get(1);
                  if (javaScriptChannelInstanceIdArg == null) {
                    throw new NullPointerException(
                        "javaScriptChannelInstanceIdArg unexpectedly null.");
                  }
                  api.addJavaScriptChannel(
                      instanceIdArg.longValue(), javaScriptChannelInstanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.removeJavaScriptChannel",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number javaScriptChannelInstanceIdArg = (Number) args.get(1);
                  if (javaScriptChannelInstanceIdArg == null) {
                    throw new NullPointerException(
                        "javaScriptChannelInstanceIdArg unexpectedly null.");
                  }
                  api.removeJavaScriptChannel(
                      instanceIdArg.longValue(), javaScriptChannelInstanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.setDownloadListener",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number listenerInstanceIdArg = (Number) args.get(1);
                  if (listenerInstanceIdArg == null) {
                    throw new NullPointerException("listenerInstanceIdArg unexpectedly null.");
                  }
                  api.setDownloadListener(
                      instanceIdArg.longValue(), listenerInstanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.setWebChromeClient",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number clientInstanceIdArg = (Number) args.get(1);
                  if (clientInstanceIdArg == null) {
                    throw new NullPointerException("clientInstanceIdArg unexpectedly null.");
                  }
                  api.setWebChromeClient(
                      instanceIdArg.longValue(), clientInstanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebViewHostApi.setBackgroundColor",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number colorArg = (Number) args.get(1);
                  if (colorArg == null) {
                    throw new NullPointerException("colorArg unexpectedly null.");
                  }
                  api.setBackgroundColor(instanceIdArg.longValue(), colorArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class WebSettingsHostApiCodec extends StandardMessageCodec {
    public static final WebSettingsHostApiCodec INSTANCE = new WebSettingsHostApiCodec();

    private WebSettingsHostApiCodec() {}
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
  public interface WebSettingsHostApi {
    void create(Long instanceId, Long webViewInstanceId);

    void dispose(Long instanceId);

    void setDomStorageEnabled(Long instanceId, Boolean flag);

    void setJavaScriptCanOpenWindowsAutomatically(Long instanceId, Boolean flag);

    void setSupportMultipleWindows(Long instanceId, Boolean support);

    void setJavaScriptEnabled(Long instanceId, Boolean flag);

    void setUserAgentString(Long instanceId, String userAgentString);

    void setMediaPlaybackRequiresUserGesture(Long instanceId, Boolean require);

    void setSupportZoom(Long instanceId, Boolean support);

    void setLoadWithOverviewMode(Long instanceId, Boolean overview);

    void setUseWideViewPort(Long instanceId, Boolean use);

    void setDisplayZoomControls(Long instanceId, Boolean enabled);

    void setBuiltInZoomControls(Long instanceId, Boolean enabled);

    /** The codec used by WebSettingsHostApi. */
    static MessageCodec<Object> getCodec() {
      return WebSettingsHostApiCodec.INSTANCE;
    }

    /**
     * Sets up an instance of `WebSettingsHostApi` to handle messages through the `binaryMessenger`.
     */
    static void setup(BinaryMessenger binaryMessenger, WebSettingsHostApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebSettingsHostApi.create", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number webViewInstanceIdArg = (Number) args.get(1);
                  if (webViewInstanceIdArg == null) {
                    throw new NullPointerException("webViewInstanceIdArg unexpectedly null.");
                  }
                  api.create(instanceIdArg.longValue(), webViewInstanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebSettingsHostApi.dispose", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  api.dispose(instanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setDomStorageEnabled",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean flagArg = (Boolean) args.get(1);
                  if (flagArg == null) {
                    throw new NullPointerException("flagArg unexpectedly null.");
                  }
                  api.setDomStorageEnabled(instanceIdArg.longValue(), flagArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptCanOpenWindowsAutomatically",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean flagArg = (Boolean) args.get(1);
                  if (flagArg == null) {
                    throw new NullPointerException("flagArg unexpectedly null.");
                  }
                  api.setJavaScriptCanOpenWindowsAutomatically(instanceIdArg.longValue(), flagArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setSupportMultipleWindows",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean supportArg = (Boolean) args.get(1);
                  if (supportArg == null) {
                    throw new NullPointerException("supportArg unexpectedly null.");
                  }
                  api.setSupportMultipleWindows(instanceIdArg.longValue(), supportArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setJavaScriptEnabled",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean flagArg = (Boolean) args.get(1);
                  if (flagArg == null) {
                    throw new NullPointerException("flagArg unexpectedly null.");
                  }
                  api.setJavaScriptEnabled(instanceIdArg.longValue(), flagArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setUserAgentString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String userAgentStringArg = (String) args.get(1);
                  if (userAgentStringArg == null) {
                    throw new NullPointerException("userAgentStringArg unexpectedly null.");
                  }
                  api.setUserAgentString(instanceIdArg.longValue(), userAgentStringArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setMediaPlaybackRequiresUserGesture",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean requireArg = (Boolean) args.get(1);
                  if (requireArg == null) {
                    throw new NullPointerException("requireArg unexpectedly null.");
                  }
                  api.setMediaPlaybackRequiresUserGesture(instanceIdArg.longValue(), requireArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setSupportZoom",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean supportArg = (Boolean) args.get(1);
                  if (supportArg == null) {
                    throw new NullPointerException("supportArg unexpectedly null.");
                  }
                  api.setSupportZoom(instanceIdArg.longValue(), supportArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setLoadWithOverviewMode",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean overviewArg = (Boolean) args.get(1);
                  if (overviewArg == null) {
                    throw new NullPointerException("overviewArg unexpectedly null.");
                  }
                  api.setLoadWithOverviewMode(instanceIdArg.longValue(), overviewArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setUseWideViewPort",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean useArg = (Boolean) args.get(1);
                  if (useArg == null) {
                    throw new NullPointerException("useArg unexpectedly null.");
                  }
                  api.setUseWideViewPort(instanceIdArg.longValue(), useArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setDisplayZoomControls",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean enabledArg = (Boolean) args.get(1);
                  if (enabledArg == null) {
                    throw new NullPointerException("enabledArg unexpectedly null.");
                  }
                  api.setDisplayZoomControls(instanceIdArg.longValue(), enabledArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.WebSettingsHostApi.setBuiltInZoomControls",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean enabledArg = (Boolean) args.get(1);
                  if (enabledArg == null) {
                    throw new NullPointerException("enabledArg unexpectedly null.");
                  }
                  api.setBuiltInZoomControls(instanceIdArg.longValue(), enabledArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class JavaScriptChannelHostApiCodec extends StandardMessageCodec {
    public static final JavaScriptChannelHostApiCodec INSTANCE =
        new JavaScriptChannelHostApiCodec();

    private JavaScriptChannelHostApiCodec() {}
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
  public interface JavaScriptChannelHostApi {
    void create(Long instanceId, String channelName);

    /** The codec used by JavaScriptChannelHostApi. */
    static MessageCodec<Object> getCodec() {
      return JavaScriptChannelHostApiCodec.INSTANCE;
    }

    /**
     * Sets up an instance of `JavaScriptChannelHostApi` to handle messages through the
     * `binaryMessenger`.
     */
    static void setup(BinaryMessenger binaryMessenger, JavaScriptChannelHostApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.JavaScriptChannelHostApi.create", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  String channelNameArg = (String) args.get(1);
                  if (channelNameArg == null) {
                    throw new NullPointerException("channelNameArg unexpectedly null.");
                  }
                  api.create(instanceIdArg.longValue(), channelNameArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class JavaScriptChannelFlutterApiCodec extends StandardMessageCodec {
    public static final JavaScriptChannelFlutterApiCodec INSTANCE =
        new JavaScriptChannelFlutterApiCodec();

    private JavaScriptChannelFlutterApiCodec() {}
  }

  /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
  public static class JavaScriptChannelFlutterApi {
    private final BinaryMessenger binaryMessenger;

    public JavaScriptChannelFlutterApi(BinaryMessenger argBinaryMessenger) {
      this.binaryMessenger = argBinaryMessenger;
    }

    public interface Reply<T> {
      void reply(T reply);
    }

    static MessageCodec<Object> getCodec() {
      return JavaScriptChannelFlutterApiCodec.INSTANCE;
    }

    public void dispose(Long instanceIdArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.JavaScriptChannelFlutterApi.dispose",
              getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void postMessage(Long instanceIdArg, String messageArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.JavaScriptChannelFlutterApi.postMessage",
              getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg, messageArg)),
          channelReply -> {
            callback.reply(null);
          });
    }
  }

  private static class WebViewClientHostApiCodec extends StandardMessageCodec {
    public static final WebViewClientHostApiCodec INSTANCE = new WebViewClientHostApiCodec();

    private WebViewClientHostApiCodec() {}
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
  public interface WebViewClientHostApi {
    void create(Long instanceId, Boolean shouldOverrideUrlLoading);

    /** The codec used by WebViewClientHostApi. */
    static MessageCodec<Object> getCodec() {
      return WebViewClientHostApiCodec.INSTANCE;
    }

    /**
     * Sets up an instance of `WebViewClientHostApi` to handle messages through the
     * `binaryMessenger`.
     */
    static void setup(BinaryMessenger binaryMessenger, WebViewClientHostApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebViewClientHostApi.create", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Boolean shouldOverrideUrlLoadingArg = (Boolean) args.get(1);
                  if (shouldOverrideUrlLoadingArg == null) {
                    throw new NullPointerException(
                        "shouldOverrideUrlLoadingArg unexpectedly null.");
                  }
                  api.create(instanceIdArg.longValue(), shouldOverrideUrlLoadingArg);
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class WebViewClientFlutterApiCodec extends StandardMessageCodec {
    public static final WebViewClientFlutterApiCodec INSTANCE = new WebViewClientFlutterApiCodec();

    private WebViewClientFlutterApiCodec() {}

    @Override
    protected Object readValueOfType(byte type, ByteBuffer buffer) {
      switch (type) {
        case (byte) 128:
          return WebResourceErrorData.fromMap((Map<String, Object>) readValue(buffer));

        case (byte) 129:
          return WebResourceRequestData.fromMap((Map<String, Object>) readValue(buffer));

        default:
          return super.readValueOfType(type, buffer);
      }
    }

    @Override
    protected void writeValue(ByteArrayOutputStream stream, Object value) {
      if (value instanceof WebResourceErrorData) {
        stream.write(128);
        writeValue(stream, ((WebResourceErrorData) value).toMap());
      } else if (value instanceof WebResourceRequestData) {
        stream.write(129);
        writeValue(stream, ((WebResourceRequestData) value).toMap());
      } else {
        super.writeValue(stream, value);
      }
    }
  }

  /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
  public static class WebViewClientFlutterApi {
    private final BinaryMessenger binaryMessenger;

    public WebViewClientFlutterApi(BinaryMessenger argBinaryMessenger) {
      this.binaryMessenger = argBinaryMessenger;
    }

    public interface Reply<T> {
      void reply(T reply);
    }

    static MessageCodec<Object> getCodec() {
      return WebViewClientFlutterApiCodec.INSTANCE;
    }

    public void dispose(Long instanceIdArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.WebViewClientFlutterApi.dispose", getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void onPageStarted(
        Long instanceIdArg, Long webViewInstanceIdArg, String urlArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.WebViewClientFlutterApi.onPageStarted",
              getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void onPageFinished(
        Long instanceIdArg, Long webViewInstanceIdArg, String urlArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.WebViewClientFlutterApi.onPageFinished",
              getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void onReceivedRequestError(
        Long instanceIdArg,
        Long webViewInstanceIdArg,
        WebResourceRequestData requestArg,
        WebResourceErrorData errorArg,
        Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedRequestError",
              getCodec());
      channel.send(
          new ArrayList<Object>(
              Arrays.asList(instanceIdArg, webViewInstanceIdArg, requestArg, errorArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void onReceivedError(
        Long instanceIdArg,
        Long webViewInstanceIdArg,
        Long errorCodeArg,
        String descriptionArg,
        String failingUrlArg,
        Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.WebViewClientFlutterApi.onReceivedError",
              getCodec());
      channel.send(
          new ArrayList<Object>(
              Arrays.asList(
                  instanceIdArg,
                  webViewInstanceIdArg,
                  errorCodeArg,
                  descriptionArg,
                  failingUrlArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void requestLoading(
        Long instanceIdArg,
        Long webViewInstanceIdArg,
        WebResourceRequestData requestArg,
        Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.WebViewClientFlutterApi.requestLoading",
              getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg, webViewInstanceIdArg, requestArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void urlLoading(
        Long instanceIdArg, Long webViewInstanceIdArg, String urlArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.WebViewClientFlutterApi.urlLoading", getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg, webViewInstanceIdArg, urlArg)),
          channelReply -> {
            callback.reply(null);
          });
    }
  }

  private static class DownloadListenerHostApiCodec extends StandardMessageCodec {
    public static final DownloadListenerHostApiCodec INSTANCE = new DownloadListenerHostApiCodec();

    private DownloadListenerHostApiCodec() {}
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
  public interface DownloadListenerHostApi {
    void create(Long instanceId);

    /** The codec used by DownloadListenerHostApi. */
    static MessageCodec<Object> getCodec() {
      return DownloadListenerHostApiCodec.INSTANCE;
    }

    /**
     * Sets up an instance of `DownloadListenerHostApi` to handle messages through the
     * `binaryMessenger`.
     */
    static void setup(BinaryMessenger binaryMessenger, DownloadListenerHostApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.DownloadListenerHostApi.create", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  api.create(instanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class DownloadListenerFlutterApiCodec extends StandardMessageCodec {
    public static final DownloadListenerFlutterApiCodec INSTANCE =
        new DownloadListenerFlutterApiCodec();

    private DownloadListenerFlutterApiCodec() {}
  }

  /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
  public static class DownloadListenerFlutterApi {
    private final BinaryMessenger binaryMessenger;

    public DownloadListenerFlutterApi(BinaryMessenger argBinaryMessenger) {
      this.binaryMessenger = argBinaryMessenger;
    }

    public interface Reply<T> {
      void reply(T reply);
    }

    static MessageCodec<Object> getCodec() {
      return DownloadListenerFlutterApiCodec.INSTANCE;
    }

    public void dispose(Long instanceIdArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.DownloadListenerFlutterApi.dispose", getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void onDownloadStart(
        Long instanceIdArg,
        String urlArg,
        String userAgentArg,
        String contentDispositionArg,
        String mimetypeArg,
        Long contentLengthArg,
        Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.DownloadListenerFlutterApi.onDownloadStart",
              getCodec());
      channel.send(
          new ArrayList<Object>(
              Arrays.asList(
                  instanceIdArg,
                  urlArg,
                  userAgentArg,
                  contentDispositionArg,
                  mimetypeArg,
                  contentLengthArg)),
          channelReply -> {
            callback.reply(null);
          });
    }
  }

  private static class WebChromeClientHostApiCodec extends StandardMessageCodec {
    public static final WebChromeClientHostApiCodec INSTANCE = new WebChromeClientHostApiCodec();

    private WebChromeClientHostApiCodec() {}
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
  public interface WebChromeClientHostApi {
    void create(Long instanceId, Long webViewClientInstanceId);

    /** The codec used by WebChromeClientHostApi. */
    static MessageCodec<Object> getCodec() {
      return WebChromeClientHostApiCodec.INSTANCE;
    }

    /**
     * Sets up an instance of `WebChromeClientHostApi` to handle messages through the
     * `binaryMessenger`.
     */
    static void setup(BinaryMessenger binaryMessenger, WebChromeClientHostApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.WebChromeClientHostApi.create", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  Number instanceIdArg = (Number) args.get(0);
                  if (instanceIdArg == null) {
                    throw new NullPointerException("instanceIdArg unexpectedly null.");
                  }
                  Number webViewClientInstanceIdArg = (Number) args.get(1);
                  if (webViewClientInstanceIdArg == null) {
                    throw new NullPointerException("webViewClientInstanceIdArg unexpectedly null.");
                  }
                  api.create(instanceIdArg.longValue(), webViewClientInstanceIdArg.longValue());
                  wrapped.put("result", null);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class FlutterAssetManagerHostApiCodec extends StandardMessageCodec {
    public static final FlutterAssetManagerHostApiCodec INSTANCE =
        new FlutterAssetManagerHostApiCodec();

    private FlutterAssetManagerHostApiCodec() {}
  }

  /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
  public interface FlutterAssetManagerHostApi {
    List<String> list(String path);

    String getAssetFilePathByName(String name);

    /** The codec used by FlutterAssetManagerHostApi. */
    static MessageCodec<Object> getCodec() {
      return FlutterAssetManagerHostApiCodec.INSTANCE;
    }

    /**
     * Sets up an instance of `FlutterAssetManagerHostApi` to handle messages through the
     * `binaryMessenger`.
     */
    static void setup(BinaryMessenger binaryMessenger, FlutterAssetManagerHostApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.FlutterAssetManagerHostApi.list", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  String pathArg = (String) args.get(0);
                  if (pathArg == null) {
                    throw new NullPointerException("pathArg unexpectedly null.");
                  }
                  List<String> output = api.list(pathArg);
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.FlutterAssetManagerHostApi.getAssetFilePathByName",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                Map<String, Object> wrapped = new HashMap<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  String nameArg = (String) args.get(0);
                  if (nameArg == null) {
                    throw new NullPointerException("nameArg unexpectedly null.");
                  }
                  String output = api.getAssetFilePathByName(nameArg);
                  wrapped.put("result", output);
                } catch (Error | RuntimeException exception) {
                  wrapped.put("error", wrapError(exception));
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class WebChromeClientFlutterApiCodec extends StandardMessageCodec {
    public static final WebChromeClientFlutterApiCodec INSTANCE =
        new WebChromeClientFlutterApiCodec();

    private WebChromeClientFlutterApiCodec() {}
  }

  /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
  public static class WebChromeClientFlutterApi {
    private final BinaryMessenger binaryMessenger;

    public WebChromeClientFlutterApi(BinaryMessenger argBinaryMessenger) {
      this.binaryMessenger = argBinaryMessenger;
    }

    public interface Reply<T> {
      void reply(T reply);
    }

    static MessageCodec<Object> getCodec() {
      return WebChromeClientFlutterApiCodec.INSTANCE;
    }

    public void dispose(Long instanceIdArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.WebChromeClientFlutterApi.dispose", getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg)),
          channelReply -> {
            callback.reply(null);
          });
    }

    public void onProgressChanged(
        Long instanceIdArg, Long webViewInstanceIdArg, Long progressArg, Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.WebChromeClientFlutterApi.onProgressChanged",
              getCodec());
      channel.send(
          new ArrayList<Object>(Arrays.asList(instanceIdArg, webViewInstanceIdArg, progressArg)),
          channelReply -> {
            callback.reply(null);
          });
    }
  }

  private static Map<String, Object> wrapError(Throwable exception) {
    Map<String, Object> errorMap = new HashMap<>();
    errorMap.put("message", exception.toString());
    errorMap.put("code", exception.getClass().getSimpleName());
    errorMap.put("details", null);
    return errorMap;
  }
}
