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

library services_gae;

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

import 'package:appengine/appengine.dart' as ae;
import 'package:logging/logging.dart';
import 'package:rpc/rpc.dart' as rpc;
import 'package:shelf/shelf_io.dart' as shelf_io;

import 'src/common.dart';
import 'src/common_server.dart';
import 'src/common_server_impl.dart';
import 'src/common_server_proto.dart';
import 'src/flutter_web.dart';
import 'src/sdk_manager.dart';
import 'src/server_cache.dart';

const String _API = '/api';
const String _API_V1_PREFIX = '/api/dartservices/v1';
const String _healthCheck = '/_ah/health';
const String _readynessCheck = '/_ah/ready';

final Logger _logger = Logger('gae_server');

void main(List<String> args) {
  var gaePort = 8080;
  if (args.isNotEmpty) gaePort = int.parse(args[0]);

  final sdk = sdkPath;

  if (sdk == null) {
    throw 'No Dart SDK is available; set the DART_SDK env var.';
  }

  // Log to stdout/stderr.  AppEngine's logging package is disabled in 0.6.0
  // and AppEngine copies stdout/stderr to the dashboards.
  _logger.onRecord.listen((LogRecord rec) {
    final out = ('${rec.level.name}: ${rec.time}: ${rec.message}\n');
    if (rec.level > Level.INFO) {
      io.stderr.write(out);
    } else {
      io.stdout.write(out);
    }
  });
  log.info('''Initializing dart-services:
    port: $gaePort
    sdkPath: $sdkPath
    REDIS_SERVER_URI: ${io.Platform.environment['REDIS_SERVER_URI']}
    GAE_VERSION: ${io.Platform.environment['GAE_VERSION']}
  ''');

  final server = GaeServer(sdk, io.Platform.environment['REDIS_SERVER_URI']);
  server.start(gaePort);
}

class GaeServer {
  final String sdkPath;
  final String redisServerUri;

  bool discoveryEnabled;
  rpc.ApiServer apiServer;
  CommonServer commonServer;
  CommonServerImpl commonServerImpl;
  CommonServerProto commonServerProto;

  GaeServer(this.sdkPath, this.redisServerUri) {
    hierarchicalLoggingEnabled = true;
    recordStackTraceAtLevel = Level.SEVERE;

    _logger.level = Level.ALL;

    discoveryEnabled = false;
    final flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
    commonServerImpl = CommonServerImpl(
      sdkPath,
      flutterWebManager,
      GaeServerContainer(),
      redisServerUri == null
          ? InMemoryCache()
          : RedisCache(
              redisServerUri,
              io.Platform.environment['GAE_VERSION'],
            ),
    );
    commonServer = CommonServer(commonServerImpl);
    commonServerProto = CommonServerProto(commonServerImpl);
    // Enabled pretty printing of returned json for debuggability.
    apiServer = rpc.ApiServer(apiPrefix: _API, prettyPrint: true)
      ..addApi(commonServer);
  }

  Future<dynamic> start([int gaePort = 8080]) async {
    await commonServerImpl.init();
    return ae.runAppEngine(requestHandler, port: gaePort);
  }

  Future<void> requestHandler(io.HttpRequest request) async {
    request.response.headers
        .add('Access-Control-Allow-Methods', 'POST, OPTIONS');
    request.response.headers.add('Access-Control-Allow-Headers',
        'Origin, X-Requested-With, Content-Type, Accept');

    if (request.method == 'OPTIONS') {
      await _processOptionsRequest(request);
    } else if (request.uri.path == _readynessCheck) {
      await _processReadynessRequest(request);
    } else if (request.uri.path == _healthCheck) {
      await _processHealthRequest(request);
    } else if (request.uri.path.startsWith(_API_V1_PREFIX)) {
      await _processApiRequest(request);
    } else if (request.uri.path.startsWith(PROTO_API_URL_PREFIX)) {
      await shelf_io.handleRequest(request, commonServerProto.router.handler);
    } else {
      await _processDefaultRequest(request);
    }
  }

  Future<void> _processOptionsRequest(io.HttpRequest request) async {
    final requestedMethod =
        request.headers.value('access-control-request-method');
    int statusCode;
    if (requestedMethod != null && requestedMethod.toUpperCase() == 'POST') {
      statusCode = io.HttpStatus.ok;
    } else {
      statusCode = io.HttpStatus.badRequest;
    }
    request.response.statusCode = statusCode;
    await request.response.close();
  }

  Future _processReadynessRequest(io.HttpRequest request) async {
    if (commonServerImpl.running) {
      request.response.statusCode = io.HttpStatus.ok;
    } else {
      request.response.statusCode = io.HttpStatus.internalServerError;
      _logger.info('CommonServer not running - failing readiness check.');
    }

    await request.response.close();
  }

  Future _processHealthRequest(io.HttpRequest request) async {
    if (commonServerImpl.running && !commonServerImpl.analysisServersRunning) {
      _logger.severe('CommonServer running without analysis servers. '
          'Intentionally failing healthcheck.');
      request.response.statusCode = io.HttpStatus.internalServerError;
    } else {
      try {
        final tempDir = await io.Directory.systemTemp.createTemp('healthz');
        try {
          final file = await io.File('${tempDir.path}/livecheck.txt');
          await file.writeAsString('testing123\n' * 1000, flush: true);
          final stat = await file.stat();
          if (stat.size > 10000) {
            request.response.statusCode = io.HttpStatus.ok;
          } else {
            request.response.statusCode = io.HttpStatus.internalServerError;
          }
        } finally {
          await tempDir.delete(recursive: true);
        }
      } catch (e) {
        _logger.severe('Failed to create temporary file: $e');
        request.response.statusCode = io.HttpStatus.internalServerError;
      }
    }

    await request.response.close();
  }

  Future _processApiRequest(io.HttpRequest request) async {
    if (!discoveryEnabled) {
      apiServer.enableDiscoveryApi();
      discoveryEnabled = true;
    }
    // NOTE: We could read in the request body here and parse it similar to
    // the _parseRequest method to determine content-type and dispatch to e.g.
    // a plain text handler if we want to support that.
    final apiRequest = rpc.HttpApiRequest.fromHttpRequest(request);

    // Dartpad sends data as plain text, we need to promote this to
    // application/json to ensure that the rpc library processes it correctly
    try {
      apiRequest.headers['content-type'] = 'application/json; charset=utf-8';
      final apiResponse = await apiServer.handleHttpApiRequest(apiRequest);
      await rpc.sendApiResponse(apiResponse, request.response);
    } catch (e) {
      // This should only happen in the case where there is a bug in the rpc
      // package. Otherwise it always returns an HttpApiResponse.
      _logger.warning('Failed with error: $e when trying to call '
          'method at \'${request.uri.path}\'.');
      request.response.statusCode = io.HttpStatus.internalServerError;
      await request.response.close();
    }
  }

  Future _processDefaultRequest(io.HttpRequest request) async {
    request.response.statusCode = io.HttpStatus.notFound;
    await request.response.close();
  }
}

class GaeServerContainer implements ServerContainer {
  @override
  String get version => io.Platform.version;
}
