// 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 'package:args/args.dart';
import 'package:path/path.dart' as path;
import 'package:yaml_edit/yaml_edit.dart';

/// If no `copies` param is passed in, we scale the generated app up to 60k lines.
const int kTargetLineCount = 60 * 1024;

/// Make `n` copies of flutter_gallery.
void main(List<String> args) {
  // If we're run from the `tools` dir, set the cwd to the repo root.
  if (path.basename(Directory.current.path) == 'tools') {
    Directory.current = Directory.current.parent.parent;
  }

  final ArgParser argParser = ArgParser();
  argParser.addOption('out', mandatory: true);
  argParser.addOption('copies');
  argParser.addFlag('delete', negatable: false);
  argParser.addFlag('help', abbr: 'h', negatable: false);

  final ArgResults results = argParser.parse(args);

  if (results['help'] as bool) {
    print('Generate n copies of flutter_gallery.\n');
    print('usage: dart mega_gallery.dart <options>');
    print(argParser.usage);
    exit(0);
  }

  final Directory source = Directory(_normalize('dev/integration_tests/flutter_gallery'));
  final Directory outParent = Directory(_normalize(results['out'] as String));
  final Directory out = Directory(path.join(outParent.path, 'packages'));

  if (results['delete'] as bool) {
    if (outParent.existsSync()) {
      print('Deleting ${outParent.path}');
      outParent.deleteSync(recursive: true);
    }

    exit(0);
  }

  if (!results.wasParsed('out')) {
    print('The --out parameter is required.');
    print(argParser.usage);
    exit(1);
  }

  int copies;
  if (!results.wasParsed('copies')) {
    final SourceStats stats = getStatsFor(_dir(source, 'lib'));
    copies = (kTargetLineCount / stats.lines).round();
  } else {
    copies = int.parse(results['copies'] as String);
  }

  print('Making $copies copies of flutter_gallery.');
  print('');
  print('Stats:');
  print('  packages/flutter            : ${getStatsFor(Directory("packages/flutter"))}');
  print(
    '  dev/integration_tests/flutter_gallery    : ${getStatsFor(Directory("dev/integration_tests/flutter_gallery"))}',
  );

  final Directory lib = _dir(out, 'lib');
  if (lib.existsSync()) {
    lib.deleteSync(recursive: true);
  }

  // Copy everything that's not a symlink, dot directory, or build/.
  _copy(source, out);

  // Make n - 1 copies.
  for (int i = 1; i < copies; i++) {
    _copyGallery(out, i);
  }

  // Create a new entry-point.
  _createEntry(_file(out, 'lib/main.dart'), copies);

  // Update the pubspec.
  final String pubspec = _file(Directory(''), 'pubspec.yaml').readAsStringSync();

  final YamlEditor yamlEditor = YamlEditor(pubspec);
  yamlEditor.update(<String>['workspace'], <String>['packages']);
  File(path.join(outParent.path, 'pubspec.yaml')).writeAsStringSync(yamlEditor.toString());

  // Replace the (flutter_gallery specific) analysis_options.yaml file with a default one.
  _file(out, 'analysis_options.yaml').writeAsStringSync('''
analyzer:
  errors:
    # See analysis_options.yaml in the flutter root for context.
    deprecated_member_use: ignore
    deprecated_member_use_from_same_package: ignore
''');

  _file(out, '.dartignore').writeAsStringSync('');

  // Count source lines and number of files; tell how to run it.
  print('  ${path.relative(results["out"] as String)} : ${getStatsFor(out)}');
}

// TODO(devoncarew): Create an entry-point that builds a UI with all `n` copies.
void _createEntry(File mainFile, int copies) {
  final StringBuffer imports = StringBuffer();

  for (int i = 1; i < copies; i++) {
    imports.writeln('// ignore: unused_import');
    imports.writeln("import 'gallery_$i/main.dart' as main_$i;");
  }

  final String contents =
      '''
// 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 'package:flutter/widgets.dart';

import 'gallery/app.dart';
${imports.toString().trim()}

void main() {
  runApp(const GalleryApp());
}
''';

  mainFile.writeAsStringSync(contents);
}

void _copyGallery(Directory galleryDir, int index) {
  final Directory lib = _dir(galleryDir, 'lib');
  final Directory dest = _dir(lib, 'gallery_$index');
  dest.createSync();

  // Copy demo/, gallery/, and main.dart.
  _copy(_dir(lib, 'demo'), _dir(dest, 'demo'));
  _copy(_dir(lib, 'gallery'), _dir(dest, 'gallery'));
  _file(dest, 'main.dart').writeAsBytesSync(_file(lib, 'main.dart').readAsBytesSync());
}

void _copy(Directory source, Directory target) {
  if (!target.existsSync()) {
    target.createSync(recursive: true);
  }

  for (final FileSystemEntity entity in source.listSync(followLinks: false)) {
    final String name = path.basename(entity.path);

    switch (entity) {
      case Directory() when name != 'build' && !name.startsWith('.'):
        _copy(entity, Directory(path.join(target.path, name)));

      case File() when name != '.packages' && name != 'pubspec.lock':
        final File dest = File(path.join(target.path, name));
        dest.writeAsBytesSync(entity.readAsBytesSync());
    }
  }
}

Directory _dir(Directory parent, String name) => Directory(path.join(parent.path, name));
File _file(Directory parent, String name) => File(path.join(parent.path, name));
String _normalize(String filePath) => path.normalize(path.absolute(filePath));

class SourceStats {
  int files = 0;
  int lines = 0;

  @override
  String toString() => '${_comma(files).padLeft(3)} files, ${_comma(lines).padLeft(6)} lines';
}

SourceStats getStatsFor(Directory dir, [SourceStats? stats]) {
  stats ??= SourceStats();

  for (final FileSystemEntity entity in dir.listSync(followLinks: false)) {
    final String name = path.basename(entity.path);
    if (entity is File && name.endsWith('.dart')) {
      stats.files += 1;
      stats.lines += _lineCount(entity);
    } else if (entity is Directory && !name.startsWith('.')) {
      getStatsFor(entity, stats);
    }
  }

  return stats;
}

int _lineCount(File file) {
  return file.readAsLinesSync().where((String line) {
    line = line.trim();
    if (line.isEmpty || line.startsWith('//')) {
      return false;
    }
    return true;
  }).length;
}

String _comma(int count) {
  final String str = count.toString();
  if (str.length > 3) {
    return '${str.substring(0, str.length - 3)},${str.substring(str.length - 3)}';
  }
  return str;
}
