// Copyright 2015 The Chromium 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:async';
import 'dart:io';

import 'package:archive/archive.dart';
import 'package:path/path.dart' as path;

import 'base/globals.dart';
import 'base/os.dart';
import 'base/process.dart';
import 'build_configuration.dart';

String _getNameForHostPlatform(HostPlatform platform) {
  switch (platform) {
    case HostPlatform.linux:
      return 'linux-x64';
    case HostPlatform.mac:
      return 'darwin-x64';
  }
}

String _getNameForTargetPlatform(TargetPlatform platform) {
  switch (platform) {
    case TargetPlatform.android:
      return 'android-arm';
    case TargetPlatform.iOS:
      return 'ios-arm';
    case TargetPlatform.iOSSimulator:
      return 'ios-x64';
    case TargetPlatform.mac:
      return 'darwin-x64';
    case TargetPlatform.linux:
      return 'linux-x64';
  }
}

// Keep in sync with https://github.com/flutter/engine/blob/master/sky/tools/release_engine.py
// and https://github.com/flutter/buildbot/blob/master/travis/build.sh
String _getCloudStorageBaseUrl({String platform, String revision}) {
  return 'https://storage.googleapis.com/mojo_infra/flutter/$revision/$platform/';
}

enum ArtifactType {
  snapshot,
  shell,
  mojo,
  androidClassesJar,
  androidIcuData,
  androidKeystore,
  androidLibSkyShell,
}

class Artifact {
  const Artifact._({
    this.name,
    this.fileName,
    this.type,
    this.hostPlatform,
    this.targetPlatform
  });

  final String name;
  final String fileName;
  final ArtifactType type;
  final HostPlatform hostPlatform;
  final TargetPlatform targetPlatform;

  String get platform {
    if (targetPlatform != null)
      return _getNameForTargetPlatform(targetPlatform);
    if (hostPlatform != null)
      return _getNameForHostPlatform(hostPlatform);
    assert(false);
    return null;
  }

  // Whether the artifact needs to be marked as executable on disk.
  bool get executable {
    return type == ArtifactType.snapshot ||
      (type == ArtifactType.shell && targetPlatform == TargetPlatform.linux);
  }
}

class ArtifactStore {
  static const List<Artifact> knownArtifacts = const <Artifact>[
    const Artifact._(
      name: 'Sky Shell',
      fileName: 'SkyShell.apk',
      type: ArtifactType.shell,
      targetPlatform: TargetPlatform.android
    ),
    const Artifact._(
      name: 'Sky Shell',
      fileName: 'sky_shell',
      type: ArtifactType.shell,
      targetPlatform: TargetPlatform.linux
    ),
    const Artifact._(
      name: 'Sky Snapshot',
      fileName: 'sky_snapshot',
      type: ArtifactType.snapshot,
      hostPlatform: HostPlatform.linux
    ),
    const Artifact._(
      name: 'Sky Snapshot',
      fileName: 'sky_snapshot',
      type: ArtifactType.snapshot,
      hostPlatform: HostPlatform.mac
    ),
    const Artifact._(
      name: 'Flutter for Mojo',
      fileName: 'flutter.mojo',
      type: ArtifactType.mojo,
      targetPlatform: TargetPlatform.android
    ),
    const Artifact._(
      name: 'Flutter for Mojo',
      fileName: 'flutter.mojo',
      type: ArtifactType.mojo,
      targetPlatform: TargetPlatform.linux
    ),
    const Artifact._(
      name: 'Compiled Java code',
      fileName: 'classes.dex.jar',
      type: ArtifactType.androidClassesJar,
      targetPlatform: TargetPlatform.android
    ),
    const Artifact._(
      name: 'ICU data table',
      fileName: 'icudtl.dat',
      type: ArtifactType.androidIcuData,
      targetPlatform: TargetPlatform.android
    ),
    const Artifact._(
      name: 'Key Store',
      fileName: 'chromium-debug.keystore',
      type: ArtifactType.androidKeystore,
      targetPlatform: TargetPlatform.android
    ),
    const Artifact._(
      name: 'Compiled C++ code',
      fileName: 'libsky_shell.so',
      type: ArtifactType.androidLibSkyShell,
      targetPlatform: TargetPlatform.android
    ),
  ];

  static Artifact getArtifact({
    ArtifactType type,
    HostPlatform hostPlatform,
    TargetPlatform targetPlatform
  }) {
    for (Artifact artifact in ArtifactStore.knownArtifacts) {
      if (type != null &&
          type != artifact.type)
        continue;
      if (hostPlatform != null &&
          artifact.hostPlatform != null &&
          hostPlatform != artifact.hostPlatform)
        continue;
      if (targetPlatform != null &&
          artifact.targetPlatform != null &&
          targetPlatform != artifact.targetPlatform)
        continue;
      return artifact;
    }
    return null;
  }

  // These values are initialized by FlutterCommandRunner on startup.
  static String flutterRoot;
  static String packageRoot = 'packages';

  static bool get isPackageRootValid {
    return FileSystemEntity.isDirectorySync(packageRoot);
  }

  static void ensurePackageRootIsValid() {
    if (!isPackageRootValid) {
      String message = '$packageRoot is not a valid directory.';
      if (packageRoot == 'packages') {
        if (FileSystemEntity.isFileSync('pubspec.yaml'))
          message += '\nDid you run `pub get` in this directory?';
        else
          message += '\nDid you run this command from the same directory as your pubspec.yaml file?';
      }
      printError(message);
      throw new ProcessExit(2);
    }
  }

  static void validateSkyEnginePackage() {
    if (engineRevision == null) {
      printError("Cannot locate the sky_engine package; did you include 'flutter' in your pubspec.yaml file?");
      throw new ProcessExit(2);
    }
    if (engineRevision != expectedEngineRevision) {
      printError("Error: incompatible sky_engine package; please run 'pub get' to get the correct one.\n");
      throw new ProcessExit(2);
    }
  }

  static String _engineRevision;

  static String get engineRevision {
    if (_engineRevision == null) {
      File revisionFile = new File(path.join(packageRoot, 'sky_engine', 'REVISION'));
      if (revisionFile.existsSync())
        _engineRevision = revisionFile.readAsStringSync();
    }
    return _engineRevision;
  }

  static String _expectedEngineRevision;

  static String get expectedEngineRevision {
    if (_expectedEngineRevision == null) {
      // TODO(jackson): Parse the .packages file and use the path from there instead
      File revisionFile = new File(path.join(flutterRoot, 'packages', 'flutter', 'packages', 'sky_engine', 'REVISION'));
      if (revisionFile.existsSync())
        _expectedEngineRevision = revisionFile.readAsStringSync();
    }
    return _expectedEngineRevision;
  }

  static String getCloudStorageBaseUrl(String platform) {
    return _getCloudStorageBaseUrl(
      platform: platform,
      revision: engineRevision
    );
  }

  /// Download a file from the given URL and return the bytes.
  static Future<List<int>> _downloadFile(Uri url) async {
    printStatus('Downloading $url.');

    HttpClient httpClient = new HttpClient();
    HttpClientRequest request = await httpClient.getUrl(url);
    HttpClientResponse response = await request.close();
    printTrace('Received response statusCode=${response.statusCode}');
    if (response.statusCode != 200)
      throw new Exception(response.reasonPhrase);

    BytesBuilder responseBody = new BytesBuilder(copy: false);
    await for (List<int> chunk in response) {
      responseBody.add(chunk);
    }

    return responseBody.takeBytes();
  }

  /// Download a file from the given url and write it to the cache.
  /// If [unzip] is true, treat the url as a zip file, and unzip it to the
  /// directory given.
  static Future _downloadFileToCache(Uri url, FileSystemEntity cachedFile, bool unzip) async {
    if (!cachedFile.parent.existsSync())
      cachedFile.parent.createSync(recursive: true);

    List<int> fileBytes = await _downloadFile(url);
    if (unzip) {
      if (cachedFile is Directory && !cachedFile.existsSync())
        cachedFile.createSync(recursive: true);

      Archive archive = new ZipDecoder().decodeBytes(fileBytes);
      for (ArchiveFile archiveFile in archive) {
        File subFile = new File(path.join(cachedFile.path, archiveFile.name));
        subFile.writeAsBytesSync(archiveFile.content, flush: true);
      }
    } else {
      File asFile = new File(cachedFile.path);
      asFile.writeAsBytesSync(fileBytes, flush: true);
    }
  }

  /// Download the artifacts.zip archive for the given platform from GCS
  /// and extract it to the local cache.
  static Future _doDownloadArtifactsFromZip(String platform) async {
    String url = getCloudStorageBaseUrl(platform) + 'artifacts.zip';
    Directory cacheDir = _getCacheDirForPlatform(platform);
    await _downloadFileToCache(Uri.parse(url), cacheDir, true);

    for (Artifact artifact in knownArtifacts) {
      if (artifact.platform == platform && artifact.executable) {
        ProcessResult result = os.makeExecutable(
            new File(path.join(cacheDir.path, artifact.fileName)));
        if (result.exitCode != 0)
          throw new Exception(result.stderr);
      }
    }
  }

  /// A wrapper ensuring that a platform's ZIP is not downloaded multiple times
  /// concurrently.
  static Future _downloadArtifactsFromZip(String platform) {
    if (_pendingZipDownloads.containsKey(platform)) {
      return _pendingZipDownloads[platform];
    }
    printStatus('Downloading $platform artifacts from the cloud, one moment please...');
    Future future = _doDownloadArtifactsFromZip(platform);
    _pendingZipDownloads[platform] = future;
    return future.then((_) => _pendingZipDownloads.remove(platform));
  }

  static final Map<String, Future> _pendingZipDownloads = new Map<String, Future>();

  static Directory getBaseCacheDir() {
    if (flutterRoot == null) {
      printError('FLUTTER_ROOT not specified. Cannot find artifact cache.');
      throw new ProcessExit(2);
    }
    Directory cacheDir = new Directory(path.join(flutterRoot, 'bin', 'cache', 'artifacts'));
    if (!cacheDir.existsSync())
      cacheDir.createSync(recursive: true);
    return cacheDir;
  }

  static Directory _getCacheDirForPlatform(String platform) {
    validateSkyEnginePackage();
    Directory baseDir = getBaseCacheDir();
    // TODO(jamesr): Add support for more configurations.
    String config = 'Release';
    Directory artifactSpecificDir = new Directory(path.join(
        baseDir.path, 'sky_engine', engineRevision, config, platform));
    if (!artifactSpecificDir.existsSync())
      artifactSpecificDir.createSync(recursive: true);
    return artifactSpecificDir;
  }

  static Future<String> getPath(Artifact artifact) async {
    Directory cacheDir = _getCacheDirForPlatform(artifact.platform);
    File cachedFile = new File(path.join(cacheDir.path, artifact.fileName));
    if (!cachedFile.existsSync()) {
      await _downloadArtifactsFromZip(artifact.platform);
      if (!cachedFile.existsSync()) {
        printError('File not found in the platform artifacts: ${cachedFile.path}');
        throw new ProcessExit(2);
      }
    }
    return cachedFile.path;
  }

  static Future<String> getThirdPartyFile(String urlStr, String cacheSubdir, bool unzip) async {
    Uri url = Uri.parse(urlStr);
    Directory baseDir = getBaseCacheDir();
    Directory cacheDir = new Directory(path.join(
        baseDir.path, 'third_party', cacheSubdir));
    File cachedFile = new File(
        path.join(cacheDir.path, url.pathSegments[url.pathSegments.length-1]));
    if (!cachedFile.existsSync()) {
      try {
        await _downloadFileToCache(url, cachedFile, unzip);
      } catch (e) {
        printError('Failed to fetch third-party artifact: $url: $e');
        throw new ProcessExit(2);
      }
    }
    return cachedFile.path;
  }

  static void clear() {
    Directory cacheDir = getBaseCacheDir();
    printTrace('Clearing cache directory ${cacheDir.path}');
    cacheDir.deleteSync(recursive: true);
  }

  static Future populate() {
    return Future.wait(knownArtifacts.map((artifact) => getPath(artifact)));
  }
}
