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

library sourcemap.output_structure;

import 'dart:math' as Math;
import 'html_parts.dart' show
    Annotation,
    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;

  R visitStructure(OutputStructure entity, A arg) => visitEntity(entity, arg);
  R visitLibrary(LibraryBlock entity, A arg) => visitEntity(entity, arg);
  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);

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

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

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

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

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

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

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

  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;
  final List<LibraryBlock> children;

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

  @override
  EntityKind get kind => EntityKind.STRUCTURE;

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

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

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

  bool get canHaveChildren => true;

  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;
      String ssaLineHeader;
      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);
  }

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

  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;
    }
  }
}

/// A block defining the content of a Dart library.
class LibraryBlock extends AbstractEntity {
  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;

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

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

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

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

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

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

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

  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;

  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;

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

/// A block defining a Dart class.
class LibraryClass extends BasicEntity {
  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;

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

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

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

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

  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 {
  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;

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

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

  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 = 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;
    }
  }

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

  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;

  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;

  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;

  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;

  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;
  }

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

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

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

  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;

  }

  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;
  }
}