// Copyright (c) 2016, 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.

// @dart = 2.7

library sourcemap.output_structure;

import 'dart:math' as Math;
import 'html_parts.dart' show CodeLine, JsonStrategy;

// Constants used to identify the subsection of the JavaScript output. These
// are specifically for the unminified full_emitter output.
const String HEAD = '  var dart = [';
const String TAIL = '  }], ';
const String END = '  setupProgram(dart';

final RegExp TOP_LEVEL_VALUE = new RegExp(r'^    (".+?"):');
final RegExp TOP_LEVEL_FUNCTION =
    new RegExp(r'^    ([a-zA-Z0-9_$]+): \[?function');
final RegExp TOP_LEVEL_CLASS = new RegExp(r'^    ([a-zA-Z0-9_$]+): \[?\{');

final RegExp STATICS = new RegExp(r'^      static:');
final RegExp MEMBER_VALUE = new RegExp(r'^      (".+?"):');
final RegExp MEMBER_FUNCTION =
    new RegExp(r'^      ([a-zA-Z0-9_$]+): \[?function');
final RegExp MEMBER_OBJECT = new RegExp(r'^      ([a-zA-Z0-9_$]+): \[?\{');

final RegExp STATIC_FUNCTION =
    new RegExp(r'^        ([a-zA-Z0-9_$]+): \[?function');

/// Subrange of the JavaScript output.
abstract class OutputEntity {
  Interval get interval;
  Interval get header;
  Interval get footer;

  bool get canHaveChildren => false;

  List<OutputEntity> get children;

  CodeSource codeSource;

  Interval getChildInterval(Interval childIndex) {
    return new Interval(children[childIndex.from].interval.from,
        children[childIndex.to - 1].interval.to);
  }

  OutputEntity getChild(int index) {
    return children[index];
  }

  accept(OutputVisitor visitor, arg);

  EntityKind get kind;

  Map toJson(JsonStrategy strategy);

  OutputEntity getEntityForLine(int line);
}

enum EntityKind {
  STRUCTURE,
  LIBRARY,
  CLASS,
  TOP_LEVEL_FUNCTION,
  TOP_LEVEL_VALUE,
  MEMBER_FUNCTION,
  MEMBER_OBJECT,
  MEMBER_VALUE,
  STATICS,
  STATIC_FUNCTION,
}

abstract class OutputVisitor<R, A> {
  R visitStructure(OutputStructure entity, A arg);
  R visitLibrary(LibraryBlock entity, A arg);
  R visitClass(LibraryClass entity, A arg);
  R visitTopLevelFunction(TopLevelFunction entity, A arg);
  R visitTopLevelValue(TopLevelValue entity, A arg);
  R visitMemberObject(MemberObject entity, A arg);
  R visitMemberFunction(MemberFunction entity, A arg);
  R visitMemberValue(MemberValue entity, A arg);
  R visitStatics(Statics entity, A arg);
  R visitStaticFunction(StaticFunction entity, A arg);
}

abstract class BaseOutputVisitor<R, A> extends OutputVisitor<R, A> {
  R visitEntity(OutputEntity entity, A arg) => null;

  @override
  R visitStructure(OutputStructure entity, A arg) => visitEntity(entity, arg);
  @override
  R visitLibrary(LibraryBlock entity, A arg) => visitEntity(entity, arg);
  @override
  R visitClass(LibraryClass entity, A arg) => visitEntity(entity, arg);

  R visitMember(BasicEntity entity, A arg) => visitEntity(entity, arg);

  R visitTopLevelMember(BasicEntity entity, A arg) => visitMember(entity, arg);

  @override
  R visitTopLevelFunction(TopLevelFunction entity, A arg) {
    return visitTopLevelMember(entity, arg);
  }

  @override
  R visitTopLevelValue(TopLevelValue entity, A arg) {
    return visitTopLevelMember(entity, arg);
  }

  R visitClassMember(BasicEntity entity, A arg) => visitMember(entity, arg);

  @override
  R visitMemberObject(MemberObject entity, A arg) {
    return visitClassMember(entity, arg);
  }

  @override
  R visitMemberFunction(MemberFunction entity, A arg) {
    return visitClassMember(entity, arg);
  }

  @override
  R visitMemberValue(MemberValue entity, A arg) {
    return visitClassMember(entity, arg);
  }

  @override
  R visitStatics(Statics entity, A arg) {
    return visitClassMember(entity, arg);
  }

  @override
  R visitStaticFunction(StaticFunction entity, A arg) {
    return visitClassMember(entity, arg);
  }
}

/// The whole JavaScript output.
class OutputStructure extends OutputEntity {
  final List<CodeLine> lines;
  final int headerEnd;
  final int footerStart;
  @override
  final List<LibraryBlock> children;

  OutputStructure(this.lines, this.headerEnd, this.footerStart, this.children);

  @override
  EntityKind get kind => EntityKind.STRUCTURE;

  @override
  Interval get interval => new Interval(0, lines.length);

  @override
  Interval get header => new Interval(0, headerEnd);

  @override
  Interval get footer => new Interval(footerStart, lines.length);

  @override
  bool get canHaveChildren => true;

  @override
  OutputEntity getEntityForLine(int line) {
    if (line < headerEnd || line >= footerStart) {
      return this;
    }
    for (LibraryBlock library in children) {
      if (library.interval.contains(line)) {
        return library.getEntityForLine(line);
      }
    }
    return null;
  }

  /// Compute the structure of the JavaScript [lines].
  static OutputStructure parse(List<CodeLine> lines) {
    int findHeaderStart(List<CodeLine> lines) {
      int index = 0;
      for (CodeLine line in lines) {
        if (line.code.startsWith(HEAD)) {
          return index;
        }
        index++;
      }
      return lines.length;
    }

    int findHeaderEnd(int start, List<CodeLine> lines) {
      int index = start;
      for (CodeLine line in lines.skip(start)) {
        if (line.code.startsWith(END)) {
          return index;
        }
        index++;
      }
      return lines.length;
    }

    String readHeader(CodeLine line) {
      String code = line.code;
      if (code.startsWith(HEAD)) {
        return code.substring(HEAD.length);
      } else if (code.startsWith(TAIL)) {
        return code.substring(TAIL.length);
      }
      return null;
    }

    List<LibraryBlock> computeHeaderMap(
        List<CodeLine> lines, int start, int end) {
      List<LibraryBlock> libraryBlocks = <LibraryBlock>[];
      LibraryBlock current;
      for (int index = start; index < end; index++) {
        String header = readHeader(lines[index]);
        if (header != null) {
          if (current != null) {
            current.to = index;
          }
          libraryBlocks.add(current = new LibraryBlock(header, index));
        }
      }
      if (current != null) {
        current.to = end;
      }
      return libraryBlocks;
    }

    int headerEnd = findHeaderStart(lines);
    int footerStart = findHeaderEnd(headerEnd, lines);
    List<LibraryBlock> libraryBlocks =
        computeHeaderMap(lines, headerEnd, footerStart);
    for (LibraryBlock block in libraryBlocks) {
      block.preprocess(lines);
    }

    return new OutputStructure(lines, headerEnd, footerStart, libraryBlocks);
  }

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitStructure(this, arg);

  @override
  Map toJson(JsonStrategy strategy) {
    return {
      'lines': lines.map((line) => line.toJson(strategy)).toList(),
      'headerEnd': headerEnd,
      'footerStart': footerStart,
      'children': children.map((child) => child.toJson(strategy)).toList(),
    };
  }

  static OutputStructure fromJson(Map json, JsonStrategy strategy) {
    List<CodeLine> lines =
        json['lines'].map((l) => CodeLine.fromJson(l, strategy)).toList();
    int headerEnd = json['headerEnd'];
    int footerStart = json['footerStart'];
    List<LibraryBlock> children = json['children']
        .map((j) => AbstractEntity.fromJson(j, strategy))
        .toList();
    return new OutputStructure(lines, headerEnd, footerStart, children);
  }
}

abstract class AbstractEntity extends OutputEntity {
  final String name;
  final int from;
  int to;

  AbstractEntity(this.name, this.from);

  @override
  Interval get interval => new Interval(from, to);

  @override
  Map toJson(JsonStrategy strategy) {
    return {
      'kind': kind.index,
      'name': name,
      'from': from,
      'to': to,
      'children': children.map((child) => child.toJson(strategy)).toList(),
      'codeSource': codeSource != null ? codeSource.toJson() : null,
    };
  }

  static AbstractEntity fromJson(Map json, JsonStrategy strategy) {
    EntityKind kind = EntityKind.values[json['kind']];
    String name = json['name'];
    int from = json['from'];
    int to = json['to'];
    CodeSource codeSource = CodeSource.fromJson(json['codeSource']);

    switch (kind) {
      case EntityKind.STRUCTURE:
        throw new StateError('Unexpected entity kind $kind');
      case EntityKind.LIBRARY:
        LibraryBlock lib = new LibraryBlock(name, from)
          ..to = to
          ..codeSource = codeSource;
        json['children']
            .forEach((child) => lib.children.add(fromJson(child, strategy)));
        return lib;
      case EntityKind.CLASS:
        LibraryClass cls = new LibraryClass(name, from)
          ..to = to
          ..codeSource = codeSource;
        json['children']
            .forEach((child) => cls.children.add(fromJson(child, strategy)));
        return cls;
      case EntityKind.TOP_LEVEL_FUNCTION:
        return new TopLevelFunction(name, from)
          ..to = to
          ..codeSource = codeSource;
      case EntityKind.TOP_LEVEL_VALUE:
        return new TopLevelValue(name, from)
          ..to = to
          ..codeSource = codeSource;
      case EntityKind.MEMBER_FUNCTION:
        return new MemberFunction(name, from)
          ..to = to
          ..codeSource = codeSource;
      case EntityKind.MEMBER_OBJECT:
        return new MemberObject(name, from)
          ..to = to
          ..codeSource = codeSource;
      case EntityKind.MEMBER_VALUE:
        return new MemberValue(name, from)
          ..to = to
          ..codeSource = codeSource;
      case EntityKind.STATICS:
        Statics statics = new Statics(from)
          ..to = to
          ..codeSource = codeSource;
        json['children'].forEach(
            (child) => statics.children.add(fromJson(child, strategy)));
        return statics;
      case EntityKind.STATIC_FUNCTION:
        return new StaticFunction(name, from)
          ..to = to
          ..codeSource = codeSource;
    }
    throw "Unhandled: $kind";
  }
}

/// A block defining the content of a Dart library.
class LibraryBlock extends AbstractEntity {
  @override
  List<BasicEntity> children = <BasicEntity>[];
  int get headerEnd => from + 2;
  int get footerStart => to /* - 1*/;

  LibraryBlock(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.LIBRARY;

  @override
  Interval get header => new Interval(from, headerEnd);

  @override
  Interval get footer => new Interval(footerStart, to);

  @override
  bool get canHaveChildren => true;

  void preprocess(List<CodeLine> lines) {
    int index = headerEnd;
    BasicEntity current;
    while (index < footerStart) {
      String line = lines[index].code;
      BasicEntity next;
      Match matchFunction = TOP_LEVEL_FUNCTION.firstMatch(line);
      if (matchFunction != null) {
        next = new TopLevelFunction(matchFunction.group(1), index);
      } else {
        Match matchClass = TOP_LEVEL_CLASS.firstMatch(line);
        if (matchClass != null) {
          next = new LibraryClass(matchClass.group(1), index);
        } else {
          Match matchValue = TOP_LEVEL_VALUE.firstMatch(line);
          if (matchValue != null) {
            next = new TopLevelValue(matchValue.group(1), index);
          }
        }
      }
      if (next != null) {
        if (current != null) {
          current.to = index;
        }
        children.add(current = next);
      } else if (index == headerEnd) {
        throw 'Failed to match first library block line:\n$line';
      }

      index++;
    }
    if (current != null) {
      current.to = footerStart;
    }

    for (BasicEntity entity in children) {
      entity.preprocess(lines);
    }
  }

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitLibrary(this, arg);

  @override
  OutputEntity getEntityForLine(int line) {
    if (line < headerEnd || line >= footerStart) {
      return this;
    }
    for (BasicEntity child in children) {
      if (child.interval.contains(line)) {
        return child.getEntityForLine(line);
      }
    }
    return null;
  }
}

/// A simple member of a library or class.
abstract class BasicEntity extends AbstractEntity {
  BasicEntity(String name, int from) : super(name, from);

  @override
  Interval get header => new Interval(from, to);

  @override
  Interval get footer => new Interval(to, to);

  @override
  List<OutputEntity> get children => const <OutputEntity>[];

  void preprocess(List<CodeLine> lines) {}

  @override
  OutputEntity getEntityForLine(int line) {
    if (interval.contains(line)) {
      return this;
    }
    return null;
  }
}

class TopLevelFunction extends BasicEntity {
  TopLevelFunction(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.TOP_LEVEL_FUNCTION;

  @override
  accept(OutputVisitor visitor, arg) {
    return visitor.visitTopLevelFunction(this, arg);
  }
}

class TopLevelValue extends BasicEntity {
  TopLevelValue(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.TOP_LEVEL_VALUE;

  @override
  accept(OutputVisitor visitor, arg) {
    return visitor.visitTopLevelValue(this, arg);
  }
}

/// A block defining a Dart class.
class LibraryClass extends BasicEntity {
  @override
  List<BasicEntity> children = <BasicEntity>[];
  int get headerEnd => from + 1;
  int get footerStart => to - 1;

  LibraryClass(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.CLASS;

  @override
  Interval get header => new Interval(from, headerEnd);

  @override
  Interval get footer => new Interval(footerStart, to);

  @override
  bool get canHaveChildren => true;

  @override
  void preprocess(List<CodeLine> lines) {
    int index = headerEnd;
    BasicEntity current;
    while (index < footerStart) {
      String line = lines[index].code;
      BasicEntity next;
      Match match = MEMBER_FUNCTION.firstMatch(line);
      if (match != null) {
        next = new MemberFunction(match.group(1), index);
      } else {
        match = STATICS.firstMatch(line);
        if (match != null) {
          next = new Statics(index);
        } else {
          match = MEMBER_OBJECT.firstMatch(line);
          if (match != null) {
            next = new MemberObject(match.group(1), index);
          } else {
            match = MEMBER_VALUE.firstMatch(line);
            if (match != null) {
              next = new MemberValue(match.group(1), index);
            }
          }
        }
      }
      if (next != null) {
        if (current != null) {
          current.to = index;
        }
        children.add(current = next);
      } else if (index == headerEnd) {
        throw 'Failed to match first library block line:\n$line';
      }

      index++;
    }
    if (current != null) {
      current.to = footerStart;
    }

    for (BasicEntity entity in children) {
      entity.preprocess(lines);
    }
  }

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitClass(this, arg);

  @override
  OutputEntity getEntityForLine(int line) {
    if (line < headerEnd || line >= footerStart) {
      return this;
    }
    for (BasicEntity child in children) {
      if (child.interval.contains(line)) {
        return child.getEntityForLine(line);
      }
    }
    return null;
  }
}

/// A block defining static members of a Dart class.
class Statics extends BasicEntity {
  @override
  List<BasicEntity> children = <BasicEntity>[];
  int get headerEnd => from + 1;
  int get footerStart => to - 1;

  Statics(int from) : super('statics', from);

  @override
  EntityKind get kind => EntityKind.STATICS;

  @override
  Interval get header => new Interval(from, headerEnd);

  @override
  Interval get footer => new Interval(footerStart, to);

  @override
  bool get canHaveChildren => true;

  @override
  void preprocess(List<CodeLine> lines) {
    int index = headerEnd;
    BasicEntity current;
    while (index < footerStart) {
      String line = lines[index].code;
      BasicEntity next;
      Match matchFunction = STATIC_FUNCTION.firstMatch(line);
      if (matchFunction != null) {
        next = new MemberFunction(matchFunction.group(1), index);
      }
      if (next != null) {
        if (current != null) {
          current.to = index;
        }
        children.add(current = next);
      } else if (index == headerEnd) {
        throw 'Failed to match first statics line:\n$line';
      }

      index++;
    }
    if (current != null) {
      current.to = footerStart;
    }
  }

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitStatics(this, arg);

  @override
  OutputEntity getEntityForLine(int line) {
    if (line < headerEnd || line >= footerStart) {
      return this;
    }
    for (BasicEntity child in children) {
      if (child.interval.contains(line)) {
        return child.getEntityForLine(line);
      }
    }
    return null;
  }
}

class MemberFunction extends BasicEntity {
  MemberFunction(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.MEMBER_FUNCTION;

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitMemberFunction(this, arg);
}

class MemberObject extends BasicEntity {
  MemberObject(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.MEMBER_OBJECT;

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitMemberObject(this, arg);
}

class MemberValue extends BasicEntity {
  MemberValue(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.MEMBER_VALUE;

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitMemberValue(this, arg);
}

class StaticFunction extends BasicEntity {
  StaticFunction(String name, int from) : super(name, from);

  @override
  EntityKind get kind => EntityKind.STATIC_FUNCTION;

  @override
  accept(OutputVisitor visitor, arg) => visitor.visitStaticFunction(this, arg);
}

class Interval {
  final int from;
  final int to;

  const Interval(this.from, this.to);

  int get length => to - from;

  bool get isEmpty => from == to;

  bool contains(int value) {
    return from <= value && value < to;
  }

  Interval include(int index) {
    return new Interval(Math.min(from, index), Math.max(to, index + 1));
  }

  bool inWindow(int index, {int windowSize: 0}) {
    return from - windowSize <= index && index < to + windowSize;
  }

  @override
  String toString() => '[$from,$to[';
}

enum CodeKind {
  LIBRARY,
  CLASS,
  MEMBER,
}

class CodeLocation {
  final Uri uri;
  final String name;
  final int offset;

  CodeLocation(this.uri, this.name, this.offset) {
    assert(uri != null);
  }

  @override
  String toString() => '$uri:$name:$offset';

  Map toJson(JsonStrategy strategy) {
    return {
      'uri': uri.toString(),
      'name': name,
      'offset': offset,
    };
  }

  static CodeLocation fromJson(Map json, JsonStrategy strategy) {
    if (json == null) return null;
    return new CodeLocation(
        Uri.parse(json['uri']), json['name'], json['offset']);
  }
}

/// A named entity in source code. This is used to serialize [Element]
/// references without serializing the [Element] itself.
class CodeSource {
  final CodeKind kind;
  final Uri uri;
  final String name;
  final int begin;
  final int end;
  final List<CodeSource> members = <CodeSource>[];

  CodeSource(this.kind, this.uri, this.name, this.begin, this.end);

  @override
  int get hashCode {
    return kind.hashCode * 13 +
        uri.hashCode * 17 +
        name.hashCode * 19 +
        begin.hashCode * 23;
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! CodeSource) return false;
    return kind == other.kind &&
        uri == other.uri &&
        name == other.name &&
        begin == other.begin;
  }

  @override
  String toString() => '${toJson()}';

  Map toJson() {
    return {
      'kind': kind.index,
      'uri': uri.toString(),
      'name': name,
      'begin': begin,
      'end': end,
      'members': members.map((c) => c.toJson()).toList(),
    };
  }

  static CodeSource fromJson(Map json) {
    if (json == null) return null;
    CodeSource codeSource = new CodeSource(CodeKind.values[json['kind']],
        Uri.parse(json['uri']), json['name'], json['begin'], json['end']);
    json['members'].forEach((m) => codeSource.members.add(fromJson(m)));
    return codeSource;
  }
}
