// 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:io';
import 'dart:math';

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

const String kDocRoot = 'dev/docs/doc';

/// This script downloads an archive of Javadoc and objc doc for the engine from
/// the artifact store and extracts them to the location used for Dartdoc.
Future<void> main(List<String> args) async {
  final String engineVersion = File('bin/internal/engine.version').readAsStringSync().trim();
  String engineRealm = File('bin/internal/engine.realm').readAsStringSync().trim();
  if (engineRealm.isNotEmpty) {
    engineRealm = '$engineRealm/';
  }

  final String javadocUrl = 'https://storage.googleapis.com/${engineRealm}flutter_infra_release/flutter/$engineVersion/android-javadoc.zip';
  generateDocs(javadocUrl, 'javadoc', 'io/flutter/view/FlutterView.html');

  final String objcdocUrl = 'https://storage.googleapis.com/${engineRealm}flutter_infra_release/flutter/$engineVersion/ios-objcdoc.zip';
  generateDocs(objcdocUrl, 'objcdoc', 'Classes/FlutterViewController.html');
}

/// Fetches the zip archive at the specified url.
///
/// Returns null if the archive fails to download after [maxTries] attempts.
Future<Archive?> fetchArchive(String url, int maxTries) async {
  List<int>? responseBytes;
  for (int i = 0; i < maxTries; i++) {
    final http.Response response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      responseBytes = response.bodyBytes;
      break;
    }
    stderr.writeln('Failed attempt ${i+1} to fetch $url.');

    // On failure print a short snipped from the body in case it's helpful.
    final int bodyLength = min(1024, response.body.length);
    stderr.writeln('Response status code ${response.statusCode}. Body: ${response.body.substring(0, bodyLength)}');
    sleep(const Duration(seconds: 1));
  }
  return responseBytes == null ? null : ZipDecoder().decodeBytes(responseBytes);
}

Future<void> generateDocs(String url, String docName, String checkFile) async {
  const int maxTries = 5;
  final Archive? archive = await fetchArchive(url, maxTries);
  if (archive == null) {
    stderr.writeln('Failed to fetch zip archive from: $url after $maxTries attempts. Giving up.');
    exit(1);
  }

  final Directory output = Directory('$kDocRoot/$docName');
  print('Extracting $docName to ${output.path}');
  output.createSync(recursive: true);

  for (final ArchiveFile af in archive) {
    if (!af.name.endsWith('/')) {
      final File file = File('${output.path}/${af.name}');
      file.createSync(recursive: true);
      file.writeAsBytesSync(af.content as List<int>);
    }
  }

  /// If object then copy files to old location if the archive is using the new location.
  final bool exists = Directory('$kDocRoot/$docName/objectc_docs').existsSync();
  if (exists) {
    copyFolder(Directory('$kDocRoot/$docName/objectc_docs'), Directory('$kDocRoot/$docName/'));
  }

  final File testFile = File('${output.path}/$checkFile');
  if (!testFile.existsSync()) {
    print('Expected file ${testFile.path} not found');
    exit(1);
  }
  print('$docName ready to go!');
}

/// Copies the files in a directory recursively to a new location.
void copyFolder(Directory source, Directory destination) {
  source.listSync()
  .forEach((FileSystemEntity entity) {
    if (entity is Directory) {
      final Directory newDirectory = Directory(path.join(destination.absolute.path, path.basename(entity.path)));
      newDirectory.createSync();
      copyFolder(entity.absolute, newDirectory);
    } else if (entity is File) {
      entity.copySync(path.join(destination.path, path.basename(entity.path)));
    }
  });
}
