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

/// Make `n` copies of flutter_gallery.

import 'dart:io';

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

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

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');
  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 out = Directory(_normalize(results['out'] as String));

  if (results['delete'] as bool) {
    if (out.existsSync()) {
      print('Deleting ${out.path}');
      out.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.
  String pubspec = _file(out, 'pubspec.yaml').readAsStringSync();
  pubspec = pubspec.replaceAll('../../packages/flutter', '../../../packages/flutter');
  _file(out, 'pubspec.yaml').writeAsStringSync(pubspec);

  // Remove the (flutter_gallery specific) analysis_options.yaml file.
  _file(out, 'analysis_options.yaml').deleteSync();

  _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);

    if (entity is Directory) {
      if (name == 'build' || name.startsWith('.')) {
        continue;
      }
      _copy(entity, Directory(path.join(target.path, name)));
    } else if (entity is File) {
      if (name == '.packages' || name == 'pubspec.lock') {
        continue;
      }
      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;
}
