// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.


import 'dart:async';
import 'dart:io';

import 'package:gcloud/datastore.dart' as datastore;
import 'package:gcloud/db.dart' as db;
import 'package:gcloud/http.dart' as gcloud_http;
import 'package:gcloud/service_scope.dart' as ss;
import 'package:gcloud/storage.dart' as storage;
import 'package:googleapis_auth/auth_io.dart' as auth;
import 'package:grpc/grpc.dart' as grpc;
import 'package:grpc/src/client/connection.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as p;

import 'api_impl/stderr_logging_impl.dart' as stderr_logging_impl;
import 'appengine_context.dart';
import 'client_context.dart';
import 'grpc_api_impl/datastore_impl.dart' as grpc_datastore_impl;
import 'grpc_api_impl/logging_impl.dart' as grpc_logging_impl;
import 'logging.dart' as logging;
import 'logging_impl.dart';
import 'server/context_registry.dart';
import 'server/logging_package_adaptor.dart';
import 'server/server.dart';

bool _loggingPackageEnabled = false;

/// Runs the given [callback] inside a new service scope and makes AppEngine
/// services available within that scope.
Future withAppEngineServices(Future Function() callback) =>
    _withAppEngineServicesInternal((_) => callback());

/// Runs the AppEngine http server and uses the given request [handler] to
/// handle incoming http requests.
///
/// The given request [handler] is run inside a new service scope and has all
/// AppEngine services available within that scope.
Future runAppEngine(
  void Function(HttpRequest request, ClientContext context) handler,
  void Function(Object e, StackTrace s)? onError, {
  int port = 8080,
  bool shared = false,
  void Function(InternetAddress address, int port)? onAcceptingConnections,
}) {
  return _withAppEngineServicesInternal((ContextRegistry contextRegistry) {
    final appengineServer = AppEngineHttpServer(contextRegistry,
        port: port, shared: shared)
      ..run((request, context) {
        ss.fork(() {
          logging.registerLoggingService(context.services.logging);
          handler(request, context);
          return request.response.done;
        }, onError: (error, stack) {
          final context = contextRegistry.lookup(request);
          if (context != null) {
            try {
              context.services.logging
                  .error('Uncaught error in request handler: $error\n$stack');
            } catch (e) {
              print('Error while logging uncaught error: $e.'
                  'Original error: $error\n$stack');
            }
          } else {
            print('Unable to log error, since response has already been sent'
                'Original error: $error\n$stack');
          }
          if (onError != null) {
            onError('Uncaught error in request handler zone: $error', stack);
          }

          // In many cases errors happen during request processing or response
          // preparation. In such cases we want to close the connection, since
          // user code might not be able to.
          try {
            request.response.statusCode = HttpStatus.internalServerError;
          } on StateError catch (_) {}
          request.response.close().catchError((closeError, closeErrorStack) {
            final message =
                'Forcefully closing response, due to error in request'
                ' handler zone, resulted in an error: $closeError';
            if (onError != null) {
              onError(message, closeErrorStack);
            } else {
              print('$message\n$closeErrorStack');
            }
          });
        });
      }, onAcceptingConnections: onAcceptingConnections);
    return appengineServer.done;
  });
}

Future _withAppEngineServicesInternal(
    Future Function(ContextRegistry contextRegistry) callback) {
  return ss.fork(() async {
    final ContextRegistry contextRegistry = await _initializeAppEngine();
    final bgServices = contextRegistry.newBackgroundServices();

    db.registerDbService(bgServices.db);
    datastore.registerDatastoreService(bgServices.db.datastore);
    storage.registerStorageService(bgServices.storage);
    logging.registerLoggingService(bgServices.logging);

    return callback(contextRegistry);
  });
}

/// Sets up a `package:logging` adaptor to use AppEngine logging service.
///
/// The logging messages made via `package:logging` which are made inside a
/// request handler will end up grouped together in an AppEngine logging entry.
void useLoggingPackageAdaptor() {
  if (_loggingPackageEnabled) return;
  _loggingPackageEnabled = true;
  setupAppEngineLogging();
}

/// Uses various environment variables to initialize the appengine services and
/// returns a new [ContextRegistry] which is used for registering in-progress
/// http requests.
Future<ContextRegistry> _initializeAppEngine() async {
  var zoneId = await _getZoneInProduction();
  final isDevEnvironment = zoneId == null;
  zoneId ??= 'dev-machine';
  final bool isProdEnvironment = !isDevEnvironment;

  String? findEnvironmentVariable(String name,
      {bool onlyInProd = false, bool onlyInDev = false, bool needed = true}) {
    if (onlyInProd && !isProdEnvironment) return null;
    if (onlyInDev && !isDevEnvironment) return null;

    final value = Platform.environment[name];
    if (value == null && needed) {
      throw StateError('Expected environment variable $name to be set!');
    }
    return value;
  }

  final projectId = findEnvironmentVariable(
    'GOOGLE_CLOUD_PROJECT',
    needed: true,
  )!;

  // For local testing the gcloud sdk brings now a gRPC-ready datastore
  // emulator which will tell the user to use this environment variable.
  final dbEmulatorHost = findEnvironmentVariable('DATASTORE_EMULATOR_HOST',
      onlyInDev: false, needed: false);

  final serviceId =
      findEnvironmentVariable('GAE_SERVICE', onlyInProd: true, needed: true) ??
          'dummy-service';
  final versionId =
      findEnvironmentVariable('GAE_VERSION', onlyInProd: true, needed: true) ??
          'dummy-version';
  final instance = findEnvironmentVariable('GAE_INSTANCE',
          onlyInProd: true, needed: true) ??
      'dummy-instance';

  final String? pubServeUrlString = Platform.environment['DART_PUB_SERVE'];
  final Uri? pubServeUrl =
      pubServeUrlString != null ? Uri.parse(pubServeUrlString) : null;

  final instanceId = await _getInstanceid();

  final context = AppEngineContext(isDevEnvironment, projectId, versionId,
      serviceId, instance, instanceId, pubServeUrl);

  final loggerFactory = await _obtainLoggerFactory(context, zoneId);
  final storageService = await _obtainStorageService(context.applicationID);

  final dbService = await _obtainDatastoreService(
    context.applicationID,
    dbEmulatorHost,
  );

  // Setup a default authClient for package:gcloud
  gcloud_http.registerAuthClientService(
      await auth.clientViaApplicationDefaultCredentials(
    scopes: ['https://www.googleapis.com/auth/cloud-platform'],
  ));

  return ContextRegistry(loggerFactory, dbService, storageService, context);
}

/// Obtains a gRPC-based datastore implementation.
///
/// If [dbEmulatorHost] is not null it must have the form 'host:port' and
/// support http/2-based unencrypted gRPC.
///
/// Otherwise http2/-based encrypted gRPC will be used to Google's production
/// service.
///
/// The datastore emulator comes with the gcloud sdk and can be launched via:
///
///     $ gcloud beta emulators datastore start
///       ...
///       [datastore] If you are using a library that supports the
///                   DATASTORE_EMULATOR_HOST environment variable, run:
///       [datastore]
///       [datastore]   export DATASTORE_EMULATOR_HOST=localhost:8037
///       [datastore]
///       [datastore] Dev App Server is now running.
///       ...
///
/// The returned [db.DatastoreDB] will be usable within the current service
/// scope.
Future<db.DatastoreDB> _obtainDatastoreService(
  String projectId,
  String? dbEmulatorHost,
) async {
  String endpoint = 'https://datastore.googleapis.com';
  bool needAuthorization = true;
  if (dbEmulatorHost != null && dbEmulatorHost.contains(':')) {
    // The datastore emulator uses unencrypted http/2, we use therefore 'http'
    // for the uri scheme.
    endpoint = 'http://$dbEmulatorHost';
    needAuthorization = false;
  }
  final authenticator = await grpc.applicationDefaultCredentialsAuthenticator(
    grpc_datastore_impl.OAuth2Scopes,
  );
  final grpcClient = _getGrpcClientChannel(endpoint, needAuthorization);
  final rawDatastore = datastore.Datastore.withRetry(
    grpc_datastore_impl.GrpcDatastoreImpl(
      grpcClient,
      authenticator,
      projectId,
    ),
  );
  return db.DatastoreDB(rawDatastore, modelDB: db.ModelDBImpl());
}

/// Creates a storage service using the service account credentials (if given)
/// or using the metadata to obtain access credentials.
Future<storage.Storage> _obtainStorageService(String projectId) async {
  final authClient = await auth.clientViaApplicationDefaultCredentials(
    scopes: storage.Storage.SCOPES,
  );
  return storage.Storage(authClient, projectId);
}

/// Creates a closure function which can be used for
///
/// The underlying logging implementation will be usable within the current
/// service scope.
Future<LoggerFactory> _obtainLoggerFactory(
  AppEngineContext context,
  String zoneId,
) async {
  if (context.isDevelopmentEnvironment) {
    return StderrLoggerFactory();
  } else {
    final authenticator = await grpc.applicationDefaultCredentialsAuthenticator(
      grpc_logging_impl.OAuth2Scopes,
    );
    final sharedLoggingService = grpc_logging_impl.SharedLoggingService(
        _getGrpcClientChannel('https://logging.googleapis.com', true),
        authenticator,
        context.applicationID,
        context.module,
        context.version,
        zoneId,
        context.instance,
        context.instanceId);
    ss.registerScopeExitCallback(sharedLoggingService.close);
    return GrpcLoggerFactory(sharedLoggingService);
  }
}

/// Creates a grpc client to the specified host using service account
/// credentials for authorization.
///
/// The returned [grpc.Client] will be usable within the current service scope.
grpc.ClientChannel _getGrpcClientChannel(String url, bool needAuthorization) {
  final clientChannel = _ClientChannelWithClientId(grpc.ClientChannel(
    Uri.parse(url).host,
    options: needAuthorization
        ? grpc.ChannelOptions()
        : grpc.ChannelOptions(
            credentials: grpc.ChannelCredentials.insecure(),
          ),
  ));
  ss.registerScopeExitCallback(clientChannel.shutdown);
  return clientChannel;
}

/// Major.minor.patch version of the current Dart SDK.
final _dartVersion = Platform.version.split(RegExp('[^0-9]')).take(3).join('.');

/// Wraps [grpc.ClientChannel] attaching a client id header to each request.
class _ClientChannelWithClientId implements grpc.ClientChannel {
  final grpc.ClientChannel _clientChannel;
  _ClientChannelWithClientId(this._clientChannel);

  @override
  grpc.ClientCall<Q, R> createCall<Q, R>(
    grpc.ClientMethod<Q, R> method,
    Stream<Q> requests,
    grpc.CallOptions options,
  ) =>
      _clientChannel.createCall<Q, R>(
        method,
        requests,
        grpc.CallOptions(metadata: {
          'x-goog-api-client': 'gl-dart/$_dartVersion',
        }).mergedWith(options),
      );

  @override
  ClientConnection createConnection() => _clientChannel.createConnection();

  @override
  Future<ClientConnection> getConnection() => _clientChannel.getConnection();

  @override
  String get host => _clientChannel.host as String;

  @override
  grpc.ChannelOptions get options => _clientChannel.options;

  @override
  int get port => _clientChannel.port;

  @override
  Future<void> shutdown() => _clientChannel.shutdown();

  @override
  Future<void> terminate() => _clientChannel.terminate();

  @override
  Stream<ConnectionState> get onConnectionStateChanged =>
      _clientChannel.onConnectionStateChanged;
}

Future<String?> _getZoneInProduction() => _getMetadataValue('zone');

Future<String?> _getInstanceid() => _getMetadataValue('id');

Future<String?> _getMetadataValue(String path) async {
  final client = http.Client();
  try {
    final response = await client.get(
        Uri.parse(
            'http://metadata.google.internal/computeMetadata/v1/instance/$path'),
        headers: {
          'Metadata-Flavor': 'Google',
        });
    if (response.statusCode == HttpStatus.ok) {
      if (response.headers[HttpHeaders.contentTypeHeader]!.contains('html') ||
          response.body.contains('<html>')) {
        // The response is not expected to be HTML. This likely means we're not
        // running on cloud, and the request was intercepted by an HTTP proxy.
        return null;
      }
      return p.split(response.body).last;
    }

    throw Exception([
      'Reqeust for metadata returned something unexpected',
      response.statusCode,
      response.body
    ].join('\n'));
  } on SocketException {
    // likely not on cloud
    return null;
  } catch (e) {
    stderr.writeln('Unexpected error when trying to access metadata');
    rethrow;
  } finally {
    client.close();
  }
}

/// Factory used for creating request-specific and background loggers.
///
/// The implementation sends log messages to the Stackdriver logging service via
/// gRPC.
class GrpcLoggerFactory implements LoggerFactory {
  final grpc_logging_impl.SharedLoggingService _shared;

  GrpcLoggerFactory(this._shared);

  @override
  LoggingImpl newRequestSpecificLogger(
      String method,
      String resource,
      String userAgent,
      String host,
      String ip,
      String? traceId,
      String referrer) {
    return grpc_logging_impl.GrpcRequestLoggingImpl(
        _shared, method, resource, userAgent, host, ip, traceId, referrer);
  }

  @override
  logging.Logging newBackgroundLogger() {
    return grpc_logging_impl.GrpcBackgroundLoggingImpl(_shared);
  }
}

/// Factory used for creating request-specific and background loggers.
///
/// The implementation writes log messages to stderr.
class StderrLoggerFactory implements LoggerFactory {
  @override
  LoggingImpl newRequestSpecificLogger(
      String method,
      String resource,
      String userAgent,
      String host,
      String ip,
      String? traceId,
      String referrer) {
    return stderr_logging_impl.StderrRequestLoggingImpl(method, resource);
  }

  @override
  logging.Logging newBackgroundLogger() {
    return stderr_logging_impl.StderrBackgroundLoggingImpl();
  }
}
