// 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();

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

  final String objcdocUrl = 'https://storage.googleapis.com/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)));
    }
  });
}
