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

import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:mime/mime.dart' as mime;

import '../artifacts.dart';
import '../asset.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../compile.dart';
import '../convert.dart';
import '../devfs.dart';
import '../globals.dart';
import 'bootstrap.dart';

/// A web server which handles serving JavaScript and assets.
///
/// This is only used in development mode.
class WebAssetServer {
  @visibleForTesting
  WebAssetServer(this._httpServer, { @required void Function(dynamic, StackTrace) onError }) {
    _httpServer.listen((HttpRequest request) {
      _handleRequest(request).catchError(onError);
      // TODO(jonahwilliams): test the onError callback when https://github.com/dart-lang/sdk/issues/39094 is fixed.
    }, onError: onError);
  }

  // Fallback to "application/octet-stream" on null which
  // makes no claims as to the structure of the data.
  static const String _kDefaultMimeType = 'application/octet-stream';

  /// Start the web asset server on a [hostname] and [port].
  ///
  /// Unhandled exceptions will throw a [ToolExit] with the error and stack
  /// trace.
  static Future<WebAssetServer> start(String hostname, int port) async {
    try {
      final HttpServer httpServer = await HttpServer.bind(hostname, port);
      return WebAssetServer(httpServer, onError: (dynamic error, StackTrace stackTrace) {
        httpServer.close(force: true);
        throwToolExit('Unhandled exception in web development server:\n$error\n$stackTrace');
      });
    } on SocketException catch (err) {
      throwToolExit('Failed to bind web development server:\n$err');
    }
    assert(false);
    return null;
  }

  final HttpServer _httpServer;
  // If holding these in memory is too much overhead, this can be switched to a
  // RandomAccessFile and read on demand.
  final Map<String, Uint8List> _files = <String, Uint8List>{};
  final Map<String, Uint8List> _sourcemaps = <String, Uint8List>{};

  final RegExp _drivePath = RegExp(r'\/[A-Z]:\/');

  // handle requests for JavaScript source, dart sources maps, or asset files.
  Future<void> _handleRequest(HttpRequest request) async {
    final HttpResponse response = request.response;
    // If the response is `/`, then we are requesting the index file.
    if (request.uri.path == '/') {
      final File indexFile = fs.currentDirectory
        .childDirectory('web')
        .childFile('index.html');
      if (indexFile.existsSync()) {
        response.headers.add('Content-Type', 'text/html');
        response.headers.add('Content-Length', indexFile.lengthSync());
        await response.addStream(indexFile.openRead());
      } else {
        response.statusCode = HttpStatus.notFound;
      }
      await response.close();
      return;
    }
    // TODO(jonahwilliams): better path normalization in frontend_server to remove
    // this workaround.
    String requestPath = request.uri.path;
    if (requestPath.startsWith(_drivePath)) {
      requestPath = requestPath.substring(3);
    }

    // If this is a JavaScript file, it must be in the in-memory cache.
    // Attempt to look up the file by URI.
    if (_files.containsKey(requestPath)) {
      final List<int> bytes = _files[requestPath];
      response.headers
        ..add('Content-Length', bytes.length)
        ..add('Content-Type', 'application/javascript');
      response.add(bytes);
      await response.close();
      return;
    }
    // If this is a sourcemap file, then it might be in the in-memory cache.
    // Attempt to lookup the file by URI.
    if (_sourcemaps.containsKey(requestPath)) {
      final List<int> bytes = _sourcemaps[requestPath];
      response.headers
        ..add('Content-Length', bytes.length)
        ..add('Content-Type', 'application/json');
      response.add(bytes);
      await response.close();
      return;
    }

    // If this is a dart file, it must be on the local file system and is
    // likely coming from a source map request. Attempt to look in the
    // local filesystem for it, and return a 404 if it is not found. The tool
    // doesn't currently consider the case of Dart files as assets.
    File file = fs.file(Uri.base.resolve(request.uri.path));

    // If both of the lookups above failed, the file might have been an asset.
    // Try and resolve the path relative to the built asset directory.
    if (!file.existsSync()) {
      final String assetPath = request.uri.path.replaceFirst('/assets/', '');
      file = fs.file(fs.path.join(getAssetBuildDirectory(), fs.path.relative(assetPath)));
    }

    // If it isn't a project source or an asset, it must be a dart SDK source.
    // or a flutter web SDK source.
    if (!file.existsSync()) {
      final Directory dartSdkParent = fs.directory(artifacts.getArtifactPath(Artifact.engineDartSdkPath)).parent;
      file = fs.file(fs.path.joinAll(<String>[dartSdkParent.path, ...request.uri.pathSegments]));
    }

    if (!file.existsSync()) {
      final String flutterWebSdk = artifacts.getArtifactPath(Artifact.flutterWebSdk);
      file = fs.file(fs.path.joinAll(<String>[flutterWebSdk, ...request.uri.pathSegments]));
    }

    if (!file.existsSync()) {
      response.statusCode = HttpStatus.notFound;
      await response.close();
      return;
    }
    final int length = file.lengthSync();
    // Attempt to determine the file's mime type. if this is not provided some
    // browsers will refuse to render images/show video et cetera. If the tool
    // cannot determine a mime type, fall back to application/octet-stream.
    String mimeType;
    if (length >= 12) {
      mimeType= mime.lookupMimeType(
        file.path,
        headerBytes: await file.openRead(0, 12).first,
      );
    }
    mimeType ??= _kDefaultMimeType;
    response.headers.add('Content-Length', length);
    response.headers.add('Content-Type', mimeType);
    await response.addStream(file.openRead());
    await response.close();
  }

  /// Tear down the http server running.
  Future<void> dispose() {
    return _httpServer.close();
  }

  /// Write a single file into the in-memory cache.
  void writeFile(String filePath, String contents) {
    _files[filePath] = Uint8List.fromList(utf8.encode(contents));
  }

  /// Update the in-memory asset server with the provided source and manifest files.
  ///
  /// Returns a list of updated modules.
  List<String> write(File codeFile, File manifestFile, File sourcemapFile) {
    final List<String> modules = <String>[];
    final Uint8List codeBytes = codeFile.readAsBytesSync();
    final Uint8List sourcemapBytes = sourcemapFile.readAsBytesSync();
    final Map<String, dynamic> manifest = castStringKeyedMap(json.decode(manifestFile.readAsStringSync()));
    for (String filePath in manifest.keys) {
      if (filePath == null) {
        printTrace('Invalid manfiest file: $filePath');
        continue;
      }
      final Map<String, dynamic> offsets = castStringKeyedMap(manifest[filePath]);
      final List<int> codeOffsets = (offsets['code'] as List<dynamic>).cast<int>();
      final List<int> sourcemapOffsets = (offsets['sourcemap'] as List<dynamic>).cast<int>();
      if (codeOffsets.length != 2 || sourcemapOffsets.length != 2) {
        printTrace('Invalid manifest byte offsets: $offsets');
        continue;
      }

      final int codeStart = codeOffsets[0];
      final int codeEnd = codeOffsets[1];
      if (codeStart < 0 || codeEnd > codeBytes.lengthInBytes) {
        printTrace('Invalid byte index: [$codeStart, $codeEnd]');
        continue;
      }
      final Uint8List byteView = Uint8List.view(
        codeBytes.buffer,
        codeStart,
        codeEnd - codeStart,
      );
      _files[_filePathToUriFragment(filePath)] = byteView;

      final int sourcemapStart = sourcemapOffsets[0];
      final int sourcemapEnd = sourcemapOffsets[1];
      if (sourcemapStart < 0 || sourcemapEnd > sourcemapBytes.lengthInBytes) {
        printTrace('Invalid byte index: [$sourcemapStart, $sourcemapEnd]');
        continue;
      }
      final Uint8List sourcemapView = Uint8List.view(
        sourcemapBytes.buffer,
        sourcemapStart,
        sourcemapEnd - sourcemapStart ,
      );
      _sourcemaps['${_filePathToUriFragment(filePath)}.map'] = sourcemapView;

      modules.add(filePath);
    }
    return modules;
  }
}

class WebDevFS implements DevFS {
  WebDevFS(this.hostname, this.port, this._packagesFilePath);

  final String hostname;
  final int port;
  final String _packagesFilePath;
  WebAssetServer _webAssetServer;

  @override
  List<Uri> sources = <Uri>[];

  @override
  DateTime lastCompiled;

  // We do not evict assets on the web.
  @override
  Set<String> get assetPathsToEvict => const <String>{};

  @override
  Uri get baseUri => null;

  @override
  Future<Uri> create() async {
    _webAssetServer = await WebAssetServer.start(hostname, port);
   return Uri.base;
  }

  @override
  Future<void> destroy() async {
    await _webAssetServer.dispose();
  }

  @override
  Uri deviceUriToHostUri(Uri deviceUri) {
    return deviceUri;
  }

  @override
  String get fsName => 'web_asset';

  @override
  Directory get rootDirectory => null;

  @override
  Future<UpdateFSReport> update({
    String mainPath,
    String target,
    AssetBundle bundle,
    DateTime firstBuildTime,
    bool bundleFirstUpload = false,
    @required ResidentCompiler generator,
    String dillOutputPath,
    @required bool trackWidgetCreation,
    bool fullRestart = false,
    String projectRootPath,
    String pathToReload,
    List<Uri> invalidatedFiles,
    bool skipAssets = false,
  }) async {
    assert(trackWidgetCreation != null);
    assert(generator != null);
    if (bundleFirstUpload) {
      final File requireJS = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.engineDartSdkPath),
        'lib',
        'dev_compiler',
        'kernel',
        'amd',
        'require.js',
      ));
      final File dartSdk = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.flutterWebSdk),
        'kernel',
        'amd',
        'dart_sdk.js',
      ));
      final File dartSdkSourcemap = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.flutterWebSdk),
        'kernel',
        'amd',
        'dart_sdk.js.map',
      ));
      final File stackTraceMapper = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.engineDartSdkPath),
        'lib',
        'dev_compiler',
        'web',
        'dart_stack_trace_mapper.js',
      ));
      _webAssetServer.writeFile('/main.dart.js', generateBootstrapScript(
        requireUrl: _filePathToUriFragment(requireJS.path),
        mapperUrl: _filePathToUriFragment(stackTraceMapper.path),
        entrypoint: '${_filePathToUriFragment(mainPath)}.js',
      ));
      _webAssetServer.writeFile('/main_module.js', generateMainModule(
        entrypoint: '${_filePathToUriFragment(mainPath)}.js',
      ));
      _webAssetServer.writeFile('/dart_sdk.js', dartSdk.readAsStringSync());
      _webAssetServer.writeFile('/dart_sdk.js.map', dartSdkSourcemap.readAsStringSync());
      // TODO(jonahwilliams): refactor the asset code in this and the regular devfs to
      // be shared.
      await writeBundle(fs.directory(getAssetBuildDirectory()), bundle.entries);
    }
    final DateTime candidateCompileTime = DateTime.now();
    if (fullRestart) {
      generator.reset();
    }
     final CompilerOutput compilerOutput = await generator.recompile(
      mainPath,
      invalidatedFiles,
      outputPath:  dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
      packagesFilePath : _packagesFilePath,
    );
    if (compilerOutput == null || compilerOutput.errorCount > 0) {
      return UpdateFSReport(success: false);
    }
    // Only update the last compiled time if we successfully compiled.
    lastCompiled = candidateCompileTime;
    // list of sources that needs to be monitored are in [compilerOutput.sources]
    sources = compilerOutput.sources;
    File codeFile;
    File manifestFile;
    File sourcemapFile;
    List<String> modules;
    try {
      codeFile = fs.file('${compilerOutput.outputFilename}.sources');
      manifestFile = fs.file('${compilerOutput.outputFilename}.json');
      sourcemapFile = fs.file('${compilerOutput.outputFilename}.map');
      modules = _webAssetServer.write(codeFile, manifestFile, sourcemapFile);
    } on FileSystemException catch (err) {
      throwToolExit('Failed to load recompiled sources:\n$err');
    }
    return UpdateFSReport(success: true, syncedBytes: codeFile.lengthSync(),
      invalidatedSourcesCount: invalidatedFiles.length)
        ..invalidatedModules = modules.map(_filePathToUriFragment).toList();
  }
}

String _filePathToUriFragment(String path) {
  if (platform.isWindows) {
    final bool startWithSlash = path.startsWith('/');
    final String partial = fs.path
      .split(path)
      .skip(startWithSlash ? 2 : 1).join('/');
    if (partial.startsWith('/')) {
      return partial;
    }
    return '/$partial';
  }
  return path;
}
