// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. 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:dart_style/dart_style.dart';

import 'typescript.dart';
import 'typescript_parser.dart';

final formatter = new DartFormatter();
Map<String, Interface> _interfaces = {};
Map<String, List<String>> _subtypes = {};
// TODO(dantup): Rename namespaces -> enums since they're always that now.
Map<String, Namespace> _namespaces = {};
Map<String, TypeAlias> _typeAliases = {};

/// Whether our enum class allows any value (eg. should always return true
/// from canParse() for the correct type). This is to allow us to have some
/// type safety for these values but without restricting which values are allowed.
/// This is to support things like custom error codes and also future changes
/// in the spec (it's important the server doesn't crash on deserialising
/// newer values).
bool enumClassAllowsAnyValue(String name) {
  // TODO(dantup): This should return true by default, and allow opt-out for
  // those things we know are not supported. This behaviour matches the old
  // code in order to simplify diffs while migrating.
  return name == 'ErrorCodes' || name == 'CodeActionKind' || name == 'Method';
}

String generateDartForTypes(List<AstNode> types) {
  // Keep maps of items we may need to look up quickly later.
  types
      .whereType<TypeAlias>()
      .forEach((alias) => _typeAliases[alias.name] = alias);
  types.whereType<Interface>().forEach((interface) {
    _interfaces[interface.name] = interface;
    // Keep track of our base classes so they can look up their super classes
    // later in their fromJson() to deserialise into the most specific type.
    interface.baseTypes.forEach((base) {
      final subTypes = _subtypes[base.dartType] ??= new List<String>();
      subTypes.add(interface.name);
    });
  });
  types
      .whereType<Namespace>()
      .forEach((namespace) => _namespaces[namespace.name] = namespace);
  final buffer = new IndentableStringBuffer();
  _getSorted(types).forEach((t) => _writeType(buffer, t));
  final formattedCode = _formatCode(buffer.toString());
  return formattedCode.trim() + '\n'; // Ensure a single trailing newline.
}

TypeBase resolveTypeAlias(TypeBase type, {resolveEnumClasses: false}) {
  if (type is Type && _typeAliases.containsKey(type.name)) {
    final alias = _typeAliases[type.name];
    // Only follow the type if we're not an enum, or we wanted to follow enums.
    if (!_namespaces.containsKey(alias.name) || resolveEnumClasses) {
      return alias.baseType;
    }
  }
  return type;
}

String _formatCode(String code) {
  try {
    code = formatter.format(code);
  } catch (e) {
    print('Failed to format code, returning unformatted code.');
  }
  return code;
}

/// Recursively gets all members from superclasses.
List<Field> _getAllFields(Interface interface) {
  // Handle missing interfaces (such as special cased interfaces that won't
  // be included in this model).
  if (interface == null) {
    return [];
  }
  return interface.members
      .whereType<Field>()
      .followedBy(interface.baseTypes
          // This cast is safe because base types are always real types.
          .map((type) => _getAllFields(_interfaces[(type as Type).name]))
          .expand((ts) => ts))
      .toList();
}

/// Returns a copy of the list sorted by name.
List<AstNode> _getSorted(List<AstNode> items) {
  final sortedList = items.toList();
  sortedList.sort((item1, item2) => item1.name.compareTo(item2.name));
  return sortedList;
}

bool _isSimpleType(TypeBase type) {
  const literals = ['num', 'String', 'bool'];
  return type is Type && literals.contains(type.dartType);
}

bool _isSpecType(TypeBase type) {
  return type is Type &&
      (_interfaces.containsKey(type.name) ||
          (_namespaces.containsKey(type.name)));
}

/// Maps reserved words and identifiers that cause issues in field names.
String _makeValidIdentifier(String identifier) {
  // The SymbolKind class has uses these names which cause issues for code that
  // uses them as types.
  const map = {
    'Object': 'Obj',
    'String': 'Str',
  };
  return map[identifier] ?? identifier;
}

String _rewriteCommentReference(String comment) {
  final commentReferencePattern = new RegExp(r'\[([\w ]+)\]\(#(\w+)\)');
  return comment.replaceAllMapped(commentReferencePattern, (m) {
    final description = m.group(1);
    final reference = m.group(2);
    if (description == reference) {
      return '[$reference]';
    } else {
      return '$description ([$reference])';
    }
  });
}

Iterable<String> _wrapLines(List<String> lines, int maxLength) sync* {
  lines = lines.map((l) => l.trimRight()).toList();
  for (var line in lines) {
    while (true) {
      if (line.length <= maxLength) {
        yield line;
        break;
      } else {
        int lastSpace = line.lastIndexOf(' ', maxLength);
        // If there was no valid place to wrap, yield the whole string.
        if (lastSpace == -1) {
          yield line;
          break;
        } else {
          yield line.substring(0, lastSpace);
          line = line.substring(lastSpace + 1);
        }
      }
    }
  }
}

void _writeCanParseMethod(IndentableStringBuffer buffer, Interface interface) {
  buffer
    ..writeIndentedln('static bool canParse(Object obj) {')
    ..indent()
    ..writeIndented('return obj is Map<String, dynamic>');
  // In order to consider this valid for parsing, all fields that may not be
  // undefined must be present and also type check for the correct type.
  final requiredFields =
      _getAllFields(interface).where((f) => !f.allowsUndefined);
  for (var field in requiredFields) {
    buffer.write(" && obj.containsKey('${field.name}') && ");
    _writeTypeCheckCondition(buffer, "obj['${field.name}']", field.type);
  }
  buffer
    ..writeln(';')
    ..outdent()
    ..writeIndentedln('}');
}

void _writeConst(IndentableStringBuffer buffer, Const cons) {
  _writeDocCommentsAndAnnotations(buffer, cons);
  buffer.writeIndentedln('static const ${cons.name} = ${cons.valueAsLiteral};');
}

void _writeConstructor(IndentableStringBuffer buffer, Interface interface) {
  final allFields = _getAllFields(interface);
  if (allFields.isEmpty) {
    return;
  }
  buffer
    ..writeIndented('${interface.name}(')
    ..write(allFields.map((field) => 'this.${field.name}').join(', '))
    ..write(')');
  final fieldsWithValidation =
      allFields.where((f) => !f.allowsNull && !f.allowsUndefined).toList();
  if (fieldsWithValidation.isNotEmpty) {
    buffer
      ..writeIndentedln(' {')
      ..indent();
    for (var field in fieldsWithValidation) {
      buffer
        ..writeIndentedln('if (${field.name} == null) {')
        ..indent()
        ..writeIndentedln(
            "throw '${field.name} is required but was not provided';")
        ..outdent()
        ..writeIndentedln('}');
    }
    buffer
      ..outdent()
      ..writeIndentedln('}');
  } else {
    buffer.writeln(';');
  }
}

void _writeDocCommentsAndAnnotations(
    IndentableStringBuffer buffer, AstNode node) {
  var comment = node.commentText?.trim();
  if (comment != null && comment.isNotEmpty) {
    comment = _rewriteCommentReference(comment);
    Iterable<String> lines = comment.split('\n');
    // Wrap at 80 - 4 ('/// ') - indent characters.
    lines = _wrapLines(lines, (80 - 4 - buffer.totalIndent).clamp(0, 80));
    lines.forEach((l) => buffer.writeIndentedln('/// $l'.trim()));
  }
  if (node.isDeprecated) {
    buffer.writeIndentedln('@core.deprecated');
  }
}

void _writeEnumClass(IndentableStringBuffer buffer, Namespace namespace) {
  _writeDocCommentsAndAnnotations(buffer, namespace);
  final consts = namespace.members.cast<Const>().toList();
  final allowsAnyValue = enumClassAllowsAnyValue(namespace.name);
  final constructorName = allowsAnyValue ? '' : '._';
  final typeOfValues =
      resolveTypeAlias(consts.first.type, resolveEnumClasses: true);

  buffer
    ..writeln('class ${namespace.name} {')
    ..indent()
    ..writeIndentedln('const ${namespace.name}$constructorName(this._value);')
    ..writeIndentedln('const ${namespace.name}.fromJson(this._value);')
    ..writeln()
    ..writeIndentedln('final ${typeOfValues.dartTypeWithTypeArgs} _value;')
    ..writeln()
    ..writeIndentedln('static bool canParse(Object obj) {')
    ..indent();
  if (allowsAnyValue) {
    buffer.writeIndentedln('return ');
    _writeTypeCheckCondition(buffer, 'obj', consts.first.type);
    buffer.writeln(';');
  } else {
    buffer
      ..writeIndentedln('switch (obj) {')
      ..indent();
    consts.forEach((cons) {
      buffer..writeIndentedln('case ${cons.valueAsLiteral}:');
    });
    buffer
      ..indent()
      ..writeIndentedln('return true;')
      ..outdent()
      ..outdent()
      ..writeIndentedln('}')
      ..writeIndentedln('return false;');
  }
  buffer
    ..outdent()
    ..writeIndentedln('}');
  namespace.members.whereType<Const>().forEach((cons) {
    _writeDocCommentsAndAnnotations(buffer, cons);
    buffer
      ..writeIndentedln(
          'static const ${_makeValidIdentifier(cons.name)} = const ${namespace.name}$constructorName(${cons.valueAsLiteral});');
  });
  buffer
    ..writeln()
    ..writeIndentedln('Object toJson() => _value;')
    ..writeln()
    ..writeIndentedln('@override String toString() => _value.toString();')
    ..writeln()
    ..writeIndentedln('@override get hashCode => _value.hashCode;')
    ..writeln()
    ..writeIndentedln(
        'bool operator ==(o) => o is ${namespace.name} && o._value == _value;')
    ..outdent()
    ..writeln('}')
    ..writeln();
}

void _writeEquals(IndentableStringBuffer buffer, Interface interface) {
  buffer
    ..writeIndentedln('@override')
    ..writeIndentedln('bool operator ==(other) {')
    ..indent()
    ..writeIndentedln('if (other is ${interface.name}) {')
    ..indent()
    ..writeIndented('return ');
  for (var field in _getAllFields(interface)) {
    final type = field.type;
    if (type is ArrayType) {
      final elementType = type.elementType;
      final elementDartType = elementType.dartTypeWithTypeArgs;
      buffer.write(
          'listEqual(${field.name}, other.${field.name}, ($elementDartType a, $elementDartType b) => a == b) && ');
    } else if (type is MapType) {
      final valueType = type.valueType;
      final valueDartType = valueType.dartTypeWithTypeArgs;
      buffer.write(
          'mapEqual(${field.name}, other.${field.name}, ($valueDartType a, $valueDartType b) => a == b) && ');
    } else {
      buffer.write('${field.name} == other.${field.name} && ');
    }
  }
  buffer
    ..writeln('true;')
    ..outdent()
    ..writeIndentedln('}')
    ..writeIndentedln('return false;')
    ..outdent()
    ..writeIndentedln('}');
}

void _writeField(IndentableStringBuffer buffer, Field field) {
  _writeDocCommentsAndAnnotations(buffer, field);
  buffer
    ..writeIndented('final ')
    ..write(field.type.dartTypeWithTypeArgs)
    ..writeln(' ${field.name};');
}

void _writeFromJsonCode(
    IndentableStringBuffer buffer, TypeBase type, String valueCode,
    {bool allowsNull}) {
  type = resolveTypeAlias(type);

  if (_isSimpleType(type)) {
    buffer.write("$valueCode");
  } else if (_isSpecType(type)) {
    // Our own types have fromJson() constructors we can call.
    buffer.write(
        "$valueCode != null ? ${type.dartType}.fromJson${type.typeArgsString}($valueCode) : null");
  } else if (type is ArrayType) {
    // Lists need to be map()'d so we can recursively call writeFromJsonCode
    // as they may need fromJson on each element.
    buffer.write("$valueCode?.map((item) => ");
    _writeFromJsonCode(buffer, type.elementType, 'item',
        allowsNull: allowsNull);
    buffer
        .write(')?.cast<${type.elementType.dartTypeWithTypeArgs}>()?.toList()');
  } else if (type is MapType) {
    // Maps need to be map()'d so we can recursively call writeFromJsonCode as
    // they may need fromJson on each key or value.
    buffer.write('$valueCode?.map((key, value) => new MapEntry(');
    _writeFromJsonCode(buffer, type.indexType, 'key', allowsNull: allowsNull);
    buffer.write(', ');
    _writeFromJsonCode(buffer, type.valueType, 'value', allowsNull: allowsNull);
    buffer.write(
        '))?.cast<${type.indexType.dartTypeWithTypeArgs}, ${type.valueType.dartTypeWithTypeArgs}>()');
  } else if (type is UnionType) {
    _writeFromJsonCodeForUnion(buffer, type, valueCode, allowsNull: allowsNull);
  } else {
    buffer.write("$valueCode");
  }
}

void _writeFromJsonCodeForUnion(
    IndentableStringBuffer buffer, UnionType union, String valueCode,
    {bool allowsNull}) {
  // Write a check against each type, eg.:
  // x is y ? new Either.tx(x) : (...)
  var hasIncompleteCondition = false;
  var unclosedParens = 0;
  for (var i = 0; i < union.types.length; i++) {
    final type = union.types[i];
    final isDynamic = type.dartType == 'dynamic';

    // Dynamic matches all type checks, so only emit it if required.
    if (!isDynamic) {
      _writeTypeCheckCondition(buffer, valueCode, type);
      buffer.write(' ? ');
    }

    // The code to construct a value with this "side" of the union.
    buffer.write('new ${union.dartTypeWithTypeArgs}.t${i + 1}(');
    _writeFromJsonCode(buffer, type, valueCode,
        allowsNull: allowsNull); // Call recursively!
    buffer.write(')');

    // If we output the type condition at the top, prepare for the next condition.
    if (!isDynamic) {
      buffer.write(' : (');
      hasIncompleteCondition = true;
      unclosedParens++;
    } else {
      hasIncompleteCondition = false;
    }
  }
  // Fill the final parens with a throw because if we fell through all of the
  // cases then the value we had didn't match any of the types in the union.
  if (hasIncompleteCondition) {
    if (allowsNull) {
      buffer.write('$valueCode == null ? null : (');
      unclosedParens++;
    }
    buffer.write(
        "throw '''\${$valueCode} was not one of (${union.types.map((t) => t.dartTypeWithTypeArgs).join(', ')})'''");
  }
  buffer.write(')' * unclosedParens);
}

void _writeFromJsonConstructor(
    IndentableStringBuffer buffer, Interface interface) {
  final allFields = _getAllFields(interface);
  buffer
    ..writeIndentedln('static ${interface.nameWithTypeArgs} '
        'fromJson${interface.typeArgsString}(Map<String, dynamic> json) {')
    ..indent();
  // First check whether any of our subclasses can deserialise this.
  for (final subclassName in _subtypes[interface.name] ?? const <String>[]) {
    final subclass = _interfaces[subclassName];
    buffer
      ..writeIndentedln('if (${subclass.nameWithTypeArgs}.canParse(json)) {')
      ..indent()
      ..writeln('return ${subclass.nameWithTypeArgs}.fromJson(json);')
      ..outdent()
      ..writeIndentedln('}');
  }
  for (final field in allFields) {
    buffer.writeIndented('final ${field.name} = ');
    _writeFromJsonCode(buffer, field.type, "json['${field.name}']",
        allowsNull: field.allowsNull || field.allowsUndefined);
    buffer.writeln(';');
  }
  buffer
    ..writeIndented('return new ${interface.nameWithTypeArgs}(')
    ..write(allFields.map((field) => '${field.name}').join(', '))
    ..writeln(');')
    ..outdent()
    ..writeIndented('}');
}

void _writeHashCode(IndentableStringBuffer buffer, Interface interface) {
  buffer
    ..writeIndentedln('@override')
    ..writeIndentedln('int get hashCode {')
    ..indent()
    ..writeIndented('int hash = 0;');
  for (var field in _getAllFields(interface)) {
    buffer
        .write('hash = JenkinsSmiHash.combine(hash, ${field.name}.hashCode);');
  }
  buffer
    ..writeln('return JenkinsSmiHash.finish(hash);')
    ..outdent()
    ..writeIndentedln('}');
}

void _writeInterface(IndentableStringBuffer buffer, Interface interface) {
  _writeDocCommentsAndAnnotations(buffer, interface);

  buffer.writeIndented('class ${interface.nameWithTypeArgs} ');
  final allBaseTypes =
      interface.baseTypes.map((t) => t.dartTypeWithTypeArgs).toList();
  allBaseTypes.addAll(getSpecialBaseTypes(interface));
  allBaseTypes.add('ToJsonable');
  if (allBaseTypes.isNotEmpty) {
    buffer.writeIndented('implements ${allBaseTypes.join(', ')} ');
  }
  buffer
    ..writeln('{')
    ..indent();
  _writeConstructor(buffer, interface);
  _writeFromJsonConstructor(buffer, interface);
  // Handle Consts and Fields separately, since we need to include superclass
  // Fields.
  final consts = interface.members.whereType<Const>().toList();
  final fields = _getAllFields(interface);
  buffer.writeln();
  _writeMembers(buffer, consts);
  buffer.writeln();
  _writeMembers(buffer, fields);
  buffer.writeln();
  _writeToJsonMethod(buffer, interface);
  _writeCanParseMethod(buffer, interface);
  _writeEquals(buffer, interface);
  _writeHashCode(buffer, interface);
  _writeToString(buffer, interface);
  buffer
    ..outdent()
    ..writeIndentedln('}')
    ..writeln();
}

void _writeJsonMapAssignment(
    IndentableStringBuffer buffer, Field field, String mapName) {
  // If we are allowed to be undefined, we'll only add the value if set.
  final shouldBeOmittedIfNoValue = field.allowsUndefined;
  if (shouldBeOmittedIfNoValue) {
    buffer
      ..writeIndentedln('if (${field.name} != null) {')
      ..indent();
  }
  buffer..writeIndented('''$mapName['${field.name}'] = ${field.name}''');
  if (!field.allowsUndefined && !field.allowsNull) {
    buffer.write(''' ?? (throw '${field.name} is required but was not set')''');
  }
  buffer.writeln(';');
  if (shouldBeOmittedIfNoValue) {
    buffer
      ..outdent()
      ..writeIndentedln('}');
  }
}

void _writeMember(IndentableStringBuffer buffer, Member member) {
  if (member is Field) {
    _writeField(buffer, member);
  } else if (member is Const) {
    _writeConst(buffer, member);
  } else {
    throw 'Unknown type';
  }
}

void _writeMembers(IndentableStringBuffer buffer, List<Member> members) {
  _getSorted(members).forEach((m) => _writeMember(buffer, m));
}

void _writeToJsonMethod(IndentableStringBuffer buffer, Interface interface) {
  // It's important the name we use for the map here isn't in use in the object
  // already. 'result' was, so we prefix it with some underscores.
  buffer
    ..writeIndentedln('Map<String, dynamic> toJson() {')
    ..indent()
    ..writeIndentedln('Map<String, dynamic> __result = {};');
  // ResponseMessage must confirm to JSON-RPC which says only one of
  // result/error can be included. Since this isn't encoded in the types we
  // need to special-case it's toJson generation.
  if (interface.name == "ResponseMessage") {
    _writeToJsonFieldsForResponseMessage(buffer, interface);
  } else {
    for (var field in _getAllFields(interface)) {
      _writeJsonMapAssignment(buffer, field, '__result');
    }
  }
  buffer
    ..writeIndentedln('return __result;')
    ..outdent()
    ..writeIndentedln('}');
}

void _writeToJsonFieldsForResponseMessage(
    IndentableStringBuffer buffer, Interface interface) {
  const mapName = '__result';

  final allFields = _getAllFields(interface);
  final standardFields =
      allFields.where((f) => f.name != 'error' && f.name != 'result');

  for (var field in standardFields) {
    _writeJsonMapAssignment(buffer, field, mapName);
  }

  // Write special code for result/error so that only one is populated.
  buffer
    ..writeIndentedln('if (error != null && result != null) {')
    ..indent()
    ..writeIndentedln('''throw 'result and error cannot both be set';''')
    ..outdent()
    ..writeIndentedln('} else if (error != null) {')
    ..indent()
    ..writeIndentedln('''$mapName['error'] = error;''')
    ..outdent()
    ..writeIndentedln('} else {')
    ..indent()
    ..writeIndentedln('''$mapName['result'] = result;''')
    ..outdent()
    ..writeIndentedln('}');
}

void _writeToString(IndentableStringBuffer buffer, Interface interface) {
  buffer
    ..writeIndentedln('@override')
    ..writeIndentedln('String toString() => jsonEncoder.convert(toJson());');
}

void _writeType(IndentableStringBuffer buffer, AstNode type) {
  if (type is Interface) {
    _writeInterface(buffer, type);
  } else if (type is Namespace) {
    _writeEnumClass(buffer, type);
  } else if (type is TypeAlias) {
    // For now type aliases are not supported, so are collected at the start
    // of the process in a map, and just replaced with the aliased type during
    // generation.
    // _writeTypeAlias(buffer, type);
  } else {
    throw 'Unknown type';
  }
}

void _writeTypeCheckCondition(
    IndentableStringBuffer buffer, String valueCode, TypeBase type) {
  type = resolveTypeAlias(type, resolveEnumClasses: true);

  final resolvedDartType = type.dartTypeWithTypeArgs;
  if (resolvedDartType == 'dynamic') {
    buffer.write('true');
  } else if (_isSimpleType(type)) {
    buffer.write('$valueCode is $resolvedDartType');
  } else if (_isSpecType(type)) {
    buffer.write('$resolvedDartType.canParse($valueCode)');
  } else if (type is ArrayType) {
    buffer.write('($valueCode is List');
    if (resolvedDartType != 'dynamic') {
      // TODO(dantup): If we're happy to assume we never have two lists in a union
      // we could skip this bit.
      buffer.write(' && ($valueCode.every((item) => ');
      _writeTypeCheckCondition(buffer, 'item', type.elementType);
      buffer.write('))');
    }
    buffer.write(')');
  } else if (type is MapType) {
    buffer.write('($valueCode is Map');
    if (resolvedDartType != 'dynamic') {
      buffer..write(' && ((')..write('$valueCode.keys.every((item) => ');
      _writeTypeCheckCondition(buffer, 'item', type.indexType);
      buffer..write('&& $valueCode.values.every((item) => ');
      _writeTypeCheckCondition(buffer, 'item', type.valueType);
      buffer.write(')))');
    }
    buffer.write(')');
  } else if (type is UnionType) {
    // To type check a union, we just recursively check against each of its types.
    buffer.write('(');
    for (var i = 0; i < type.types.length; i++) {
      if (i != 0) {
        buffer.write(' || ');
      }
      _writeTypeCheckCondition(buffer, valueCode, type.types[i]);
    }
    buffer.write(')');
  } else {
    throw 'Unable to type check $valueCode against $resolvedDartType';
  }
}

class IndentableStringBuffer extends StringBuffer {
  int _indentLevel = 0;
  int _indentSpaces = 2;

  int get totalIndent => _indentLevel * _indentSpaces;
  String get _indentString => ' ' * totalIndent;

  void indent() => _indentLevel++;
  void outdent() => _indentLevel--;

  void writeIndented(Object obj) {
    write(_indentString);
    write(obj);
  }

  void writeIndentedln(Object obj) {
    write(_indentString);
    writeln(obj);
  }
}
