// Copyright 2019 The Flutter team. 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:convert';
import 'dart:io';
import 'prehighlighter.dart';

const _globalPrologue =
    '''// This file is automatically generated by codeviewer_cli.
// Do not edit this file.

// Copyright 2019 The Flutter team. 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/material.dart';
import 'package:gallery/codeviewer/code_style.dart';

class CodeSegments {
''';

const _globalEpilogue = '}\n';

final Pattern beginSubsegment = RegExp(r'//\s+BEGIN');
final Pattern endSubsegment = RegExp(r'//\s+END');

enum _FileReadStatus {
  comments,
  imports,
  finished,
}

/// Returns the new status of the scanner whose previous status was
/// [oldStatus], after scanning the line [line].
_FileReadStatus _updatedStatus(_FileReadStatus oldStatus, String line) {
  _FileReadStatus lineStatus;
  if (line.trim().startsWith('//')) {
    lineStatus = _FileReadStatus.comments;
  } else if (line.trim().startsWith('import')) {
    lineStatus = _FileReadStatus.imports;
  } else {
    lineStatus = _FileReadStatus.finished;
  }

  _FileReadStatus newStatus;
  switch (oldStatus) {
    case _FileReadStatus.comments:
      newStatus =
          (line.trim().isEmpty || lineStatus == _FileReadStatus.comments)
              ? _FileReadStatus.comments
              : lineStatus;
      break;
    case _FileReadStatus.imports:
      newStatus = (line.trim().isEmpty || lineStatus == _FileReadStatus.imports)
          ? _FileReadStatus.imports
          : _FileReadStatus.finished;
      break;
    case _FileReadStatus.finished:
      newStatus = oldStatus;
      break;
  }
  return newStatus;
}

Map<String, String> _createSegments(String sourceDirectoryPath) {
  final files = Directory(sourceDirectoryPath)
      .listSync(recursive: true)
      .whereType<File>()
      .toList();

  var subsegments = <String, StringBuffer>{};
  var subsegmentPrologues = <String, String>{};

  var appearedSubsegments = <String>{};

  for (final file in files) {
    // Process file.

    final content = file.readAsStringSync();
    final lines = const LineSplitter().convert(content);

    var status = _FileReadStatus.comments;

    final prologue = StringBuffer();

    final activeSubsegments = <String>{};

    for (final line in lines) {
      // Update status.

      status = _updatedStatus(status, line);

      if (status != _FileReadStatus.finished) {
        prologue.writeln(line);
      }

      // Process run commands.

      if (line.trim().startsWith(beginSubsegment)) {
        final argumentString = line.replaceFirst(beginSubsegment, '').trim();
        var arguments = argumentString.isEmpty
            ? <String>[]
            : argumentString.split(RegExp(r'\s+'));

        for (final argument in arguments) {
          if (activeSubsegments.contains(argument)) {
            throw PreformatterException(
                'BEGIN $argument is used twice in file ${file.path}');
          } else if (appearedSubsegments.contains(argument)) {
            throw PreformatterException('BEGIN $argument is used twice');
          } else {
            activeSubsegments.add(argument);
            appearedSubsegments.add(argument);
            subsegments[argument] = StringBuffer();
            subsegmentPrologues[argument] = prologue.toString();
          }
        }
      } else if (line.trim().startsWith(endSubsegment)) {
        final argumentString = line.replaceFirst(endSubsegment, '').trim();
        final arguments = argumentString.isEmpty
            ? <String>[]
            : argumentString.split(RegExp(r'\s+'));

        if (arguments.isEmpty && activeSubsegments.length == 1) {
          arguments.add(activeSubsegments.first);
        }

        for (final argument in arguments) {
          if (activeSubsegments.contains(argument)) {
            activeSubsegments.remove(argument);
          } else {
            throw PreformatterException(
                'END $argument is used without a paired BEGIN in ${file.path}');
          }
        }
      } else {
        // Simple line.

        for (final name in activeSubsegments) {
          subsegments[name].writeln(line);
        }
      }
    }

    if (activeSubsegments.isNotEmpty) {
      throw PreformatterException('File ${file.path} has unpaired BEGIN');
    }
  }

  var segments = <String, List<TaggedString>>{};
  var segmentPrologues = <String, String>{};

  // Sometimes a code segment is made up of subsegments. They are marked by
  // names with a "#" symbol in it, such as "bottomSheetDemoModal#1" and
  // "bottomSheetDemoModal#2".
  // The following code groups the subsegments by order into segments.
  subsegments.forEach((key, value) {
    String name;
    double order;

    if (key.contains('#')) {
      var parts = key.split('#');
      name = parts[0];
      order = double.parse(parts[1]);
    } else {
      name = key;
      order = 0;
    }

    if (!segments.containsKey(name)) {
      segments[name] = [];
    }
    segments[name].add(
      TaggedString(
        text: value.toString(),
        order: order,
      ),
    );

    segmentPrologues[name] = subsegmentPrologues[key];
  });

  segments.forEach((key, value) {
    value.sort((ts1, ts2) => (ts1.order - ts2.order).sign.round());
  });

  var answer = <String, String>{};

  for (final name in segments.keys) {
    final buffer = StringBuffer();

    buffer.write(segmentPrologues[name].trim());
    buffer.write('\n\n');

    for (final ts in segments[name]) {
      buffer.write(ts.text.trim());
      buffer.write('\n\n');
    }

    answer[name] = buffer.toString();
  }

  return answer;
}

/// A string [text] together with a number [order], for sorting purposes.
/// Used to store different subsegments of a code segment.
/// The [order] of each subsegment is tagged with the code in order to be
/// sorted in the desired order.
class TaggedString {
  TaggedString({this.text, this.order});

  final String text;
  final double order;
}

void _formatSegments(Map<String, String> segments, IOSink output) {
  output.write(_globalPrologue);

  final sortedNames = segments.keys.toList()..sort();
  for (final name in sortedNames) {
    final code = segments[name];

    output.writeln('  static TextSpan $name (BuildContext context) {');
    output.writeln('    final codeStyle = CodeStyle.of(context);');
    output.writeln('    return TextSpan(children: [');

    final codeSpans = DartSyntaxPrehighlighter().format(code);

    for (final span in codeSpans) {
      output.write('    ');
      output.write(span.toString());
      output.write(',\n');
    }

    output.write('  ]); }\n');
  }

  output.write(_globalEpilogue);

  output.close();
}

/// Collect code segments, highlight, and write to file.
///
/// [writeSegments] walks through the directory specified by
/// [sourceDirectoryPath] and reads every file in it,
/// collects code segments marked by "// BEGIN <segment_name>" and "// END",
/// highlights them, and writes to the file specified by
/// [targetFilePath]. If [isDryRun] is true, the output will
/// be written to stdout.
///
/// The output file is a dart source file with a class "CodeSegments" and
/// static methods of type TextSpan(BuildContext context).
/// Each method generates a widget that displays a segment of code.
///
/// The target file is overwritten.
void writeSegments(
    {String sourceDirectoryPath, String targetFilePath, bool isDryRun}) {
  final segments = _createSegments(sourceDirectoryPath);
  final output = isDryRun ? stdout : File(targetFilePath).openWrite();
  _formatSegments(segments, output);
}

class PreformatterException implements Exception {
  PreformatterException(this.cause);
  String cause;
}
