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

part of dart2js.mirrors;

class Dart2JsLibraryMirror extends Dart2JsElementMirror
    with ObjectMirrorMixin, ContainerMixin
    implements LibrarySourceMirror {
  List<LibraryDependencySourceMirror> _libraryDependencies;

  Dart2JsLibraryMirror(Dart2JsMirrorSystem system, LibraryElement library)
      : super(system, library);

  Function operator [](Symbol name) {
    throw new UnsupportedError('LibraryMirror.operator [] unsupported.');
  }

  // TODO(johnniwinther): Avoid the need for [LibraryElementX].
  LibraryElementX get _element => super._element;

  Uri get uri => _element.canonicalUri;

  DeclarationMirror get owner => null;

  bool get isPrivate => false;

  LibraryMirror library() => this;

  /**
   * Returns the library name (for libraries with a library tag) or the script
   * file name (for scripts without a library tag). The latter case is used to
   * provide a 'library name' for scripts, to use for instance in dartdoc.
   */
  String get _simpleNameString => _element.libraryOrScriptName;

  Symbol get qualifiedName => simpleName;

  void _forEachElement(f(Element element)) => _element.forEachLocalMember(f);

  Iterable<Dart2JsDeclarationMirror> _getDeclarationMirrors(Element element) {
    if (element.isClass || element.isTypedef) {
      return [mirrorSystem._getTypeDeclarationMirror(element)];
    } else {
      return super._getDeclarationMirrors(element);
    }
  }

  Map<Symbol, MethodMirror> get topLevelMembers => null;

  /**
   * Computes the first token of this library using the first library tag as
   * indicator.
   */
  Token getBeginToken() {
    if (_element.libraryTag != null) {
      return _element.libraryTag.getBeginToken();
    } else if (!_element.tags.isEmpty) {
      return _element.tags.first.getBeginToken();
    }
    return null;
  }

  /**
   * Computes the first token of this library using the last library tag as
   * indicator.
   */
  Token getEndToken() {
    if (!_element.tags.isEmpty) {
      return _element.tags.last.getEndToken();
    }
    return null;
  }

  void _ensureLibraryDependenciesAnalyzed() {
    if (_libraryDependencies == null) {
      // TODO(johnniwinther): Support order of declarations on [LibraryElement].
      Map<LibraryDependency, Dart2JsLibraryDependencyMirror> mirrorMap =
          <LibraryDependency, Dart2JsLibraryDependencyMirror>{};

      void addLibraryDependency(LibraryDependency libraryDependency,
          LibraryElement targetLibraryElement) {
        assert(targetLibraryElement != null);
        LibraryMirror targetLibrary =
            mirrorSystem._getLibrary(targetLibraryElement);
        mirrorMap[libraryDependency] = new Dart2JsLibraryDependencyMirror(
            libraryDependency, this, targetLibrary);
      }
      for (ImportElement import in _element.imports) {
        addLibraryDependency(import.node, import.importedLibrary);
      }
      for (ExportElement export in _element.exports) {
        addLibraryDependency(export.node, export.exportedLibrary);
      }

      _libraryDependencies = <LibraryDependencySourceMirror>[];

      for (LibraryTag node in _element.tags) {
        LibraryDependency libraryDependency = node.asLibraryDependency();
        if (libraryDependency != null) {
          Dart2JsLibraryDependencyMirror mirror = mirrorMap[libraryDependency];
          assert(mirror != null);
          _libraryDependencies.add(mirror);
        }
      }
    }
  }

  List<LibraryDependencyMirror> get libraryDependencies {
    _ensureLibraryDependenciesAnalyzed();
    return _libraryDependencies;
  }
}

class Dart2JsLibraryDependencyMirror implements LibraryDependencySourceMirror {
  final LibraryDependency _node;
  final Dart2JsLibraryMirror _sourceLibrary;
  final Dart2JsLibraryMirror _targetLibrary;
  List<CombinatorMirror> _combinators;

  Dart2JsLibraryDependencyMirror(
      this._node, this._sourceLibrary, this._targetLibrary);

  SourceLocation get location {
    return new Dart2JsSourceLocation(
        _sourceLibrary._element.entryCompilationUnit.script,
        _sourceLibrary.mirrorSystem.compiler.reporter.spanFromSpannable(_node));
  }

  List<CombinatorMirror> get combinators {
    if (_combinators == null) {
      _combinators = <CombinatorMirror>[];
      if (_node.combinators != null) {
        for (Combinator combinator in _node.combinators.nodes) {
          List<String> identifiers = <String>[];
          for (Identifier identifier in combinator.identifiers.nodes) {
            identifiers.add(identifier.source);
          }
          _combinators.add(new Dart2JsCombinatorMirror(identifiers,
              isShow: combinator.isShow));
        }
      }
    }
    return _combinators;
  }

  LibraryMirror get sourceLibrary => _sourceLibrary;

  LibraryMirror get targetLibrary => _targetLibrary;

  /*String*/ get prefix {
    Import import = _node.asImport();
    if (import != null && import.prefix != null) {
      return import.prefix.source;
    }
    return null;
  }

  bool get isImport => _node.asImport() != null;

  bool get isExport => _node.asExport() != null;

  bool get isDeferred {
    if (_node is Import) {
      Import import = _node;
      return import.isDeferred;
    }
    return false;
  }

  List<InstanceMirror> get metadata => const <InstanceMirror>[];

  /*Future<LibraryMirror>*/ loadLibrary() {
    throw new UnsupportedError(
        'LibraryDependencyMirror.loadLibrary unsupported.');
  }
}

class Dart2JsCombinatorMirror implements CombinatorSourceMirror {
  final List/*<String>*/ identifiers;
  final bool isShow;

  Dart2JsCombinatorMirror(this.identifiers, {bool isShow: true})
      : this.isShow = isShow;

  bool get isHide => !isShow;
}

class Dart2JsSourceLocation implements SourceLocation {
  final Script _script;
  final SourceSpan _span;
  int _line;
  int _column;

  Dart2JsSourceLocation(this._script, this._span);

  int _computeLine() {
    var sourceFile = _script.file;
    if (sourceFile != null) {
      return sourceFile.getLine(offset) + 1;
    }
    var index = 0;
    var lineNumber = 0;
    while (index <= offset && index < sourceText.length) {
      index = sourceText.indexOf('\n', index) + 1;
      if (index <= 0) break;
      lineNumber++;
    }
    return lineNumber;
  }

  int get line {
    if (_line == null) {
      _line = _computeLine();
    }
    return _line;
  }

  int _computeColumn() {
    if (length == 0) return 0;

    var sourceFile = _script.file;
    if (sourceFile != null) {
      return sourceFile.getColumn(sourceFile.getLine(offset), offset) + 1;
    }
    int index = offset - 1;
    var columnNumber = 0;
    while (0 <= index && index < sourceText.length) {
      columnNumber++;
      var codeUnit = sourceText.codeUnitAt(index);
      if (codeUnit == $CR || codeUnit == $LF) {
        break;
      }
      index--;
    }
    return columnNumber;
  }

  int get column {
    if (_column == null) {
      _column = _computeColumn();
    }
    return _column;
  }

  int get offset => _span.begin;

  int get length => _span.end - _span.begin;

  String get text => _script.text.substring(_span.begin, _span.end);

  Uri get sourceUri => _script.resourceUri;

  String get sourceText => _script.text;
}
