// Copyright (c) 2014, 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 'dart:io';
import 'dart:convert';
import 'dart:async';

import 'package:path/path.dart' as path;
import 'package:expect/expect.dart';
import 'package:source_maps/source_maps.dart';
import 'package:compiler/src/apiimpl.dart';
import 'package:compiler/src/elements/elements.dart'
    show
        AstElement,
        ClassElement,
        CompilationUnitElement,
        Element,
        FunctionElement,
        LibraryElement,
        MemberElement;
import 'package:compiler/src/io/source_file.dart' show SourceFile;
import 'package:compiler/src/io/source_information.dart'
    show computeElementNameForSourceMaps;
import 'package:kernel/ast.dart' show Location;

validateSourceMap(Uri targetUri,
    {Uri mainUri, Position mainPosition, CompilerImpl compiler}) {
  Uri mapUri = getMapUri(targetUri);
  List<String> targetLines = new File.fromUri(targetUri).readAsLinesSync();
  SingleMapping sourceMap = getSourceMap(mapUri);
  checkFileReferences(targetUri, mapUri, sourceMap);
  checkIndexReferences(targetLines, mapUri, sourceMap);
  checkRedundancy(sourceMap);
  if (compiler != null) {
    checkNames(targetUri, mapUri, sourceMap, compiler);
  }
  if (mainUri != null && mainPosition != null) {
    checkMainPosition(targetUri, targetLines, sourceMap, mainUri, mainPosition);
  }
}

checkIndexReferences(
    List<String> targetLines, Uri mapUri, SingleMapping sourceMap) {
  int urlsLength = sourceMap.urls.length;
  List<List<String>> sources = new List(urlsLength);
  print('Reading sources');
  for (int i = 0; i < urlsLength; i++) {
    sources[i] = new File.fromUri(mapUri.resolve(sourceMap.urls[i]))
        .readAsStringSync()
        .split('\n');
  }

  sourceMap.lines.forEach((TargetLineEntry line) {
    Expect.isTrue(line.line >= 0);
    Expect.isTrue(line.line < targetLines.length);
    for (TargetEntry entry in line.entries) {
      int urlIndex = entry.sourceUrlId;

      // TODO(zarah): Entry columns sometimes point one or more characters too
      // far. Incomment this check when this is fixed.
      //
      // Expect.isTrue(entry.column < target[line.line].length);
      Expect.isTrue(entry.column >= 0);
      Expect
          .isTrue(urlIndex == null || (urlIndex >= 0 && urlIndex < urlsLength));
      Expect.isTrue(entry.sourceLine == null ||
          (entry.sourceLine >= 0 &&
              entry.sourceLine < sources[urlIndex].length));
      Expect.isTrue(entry.sourceColumn == null ||
          (entry.sourceColumn >= 0 &&
              entry.sourceColumn < sources[urlIndex][entry.sourceLine].length));
      Expect.isTrue(entry.sourceNameId == null ||
          (entry.sourceNameId >= 0 &&
              entry.sourceNameId < sourceMap.names.length));
    }
  });
}

checkFileReferences(Uri targetUri, Uri mapUri, SingleMapping sourceMap) {
  Expect.equals(targetUri, mapUri.resolve(sourceMap.targetUrl));
  print('Checking sources');
  sourceMap.urls.forEach((String url) {
    Expect.isTrue(new File.fromUri(mapUri.resolve(url)).existsSync());
  });
}

checkRedundancy(SingleMapping sourceMap) {
  sourceMap.lines.forEach((TargetLineEntry line) {
    TargetEntry previous = null;
    for (TargetEntry next in line.entries) {
      if (previous != null) {
        Expect.isFalse(
            sameSourcePoint(previous, next),
            '$previous and $next are consecutive entries on line $line in the '
            'source map but point to same source locations');
      }
      previous = next;
    }
  });
}

checkNames(
    Uri targetUri, Uri mapUri, SingleMapping sourceMap, CompilerImpl compiler) {
  Map<Uri, CompilationUnitElement> compilationUnitMap = {};

  void mapCompilationUnits(LibraryElement library) {
    library.compilationUnits.forEach((CompilationUnitElement compilationUnit) {
      compilationUnitMap[compilationUnit.script.readableUri] = compilationUnit;
    });
  }

  compiler.libraryLoader.libraries.forEach((_library) {
    LibraryElement library = _library;
    mapCompilationUnits(library);
    if (library.patch != null) {
      mapCompilationUnits(library.patch);
    }
  });

  sourceMap.lines.forEach((TargetLineEntry line) {
    for (TargetEntry entry in line.entries) {
      if (entry.sourceNameId != null) {
        Uri uri = mapUri.resolve(sourceMap.urls[entry.sourceUrlId]);
        Position sourcePosition =
            new Position(entry.sourceLine, entry.sourceColumn);
        String name = sourceMap.names[entry.sourceNameId];

        CompilationUnitElement compilationUnit = compilationUnitMap[uri];
        Expect.isNotNull(
            compilationUnit, "No compilation unit found for $uri.");

        SourceFile sourceFile = compilationUnit.script.file;

        Position positionFromOffset(int offset) {
          Location location = sourceFile.getLocation(offset);
          int line = location.line - 1;
          int column = location.column - 1;
          return new Position(line, column);
        }

        Interval intervalFromElement(AstElement element) {
          if (!element.hasNode) return null;

          var begin = element.node.getBeginToken().charOffset;
          var endToken = element.node.getEndToken();
          int end = endToken.charOffset + endToken.charCount;
          return new Interval(
              positionFromOffset(begin), positionFromOffset(end));
        }

        AstElement findInnermost(AstElement element) {
          bool isInsideElement(FunctionElement closure) {
            Element enclosing = closure;
            while (enclosing != null) {
              if (enclosing == element) return true;
              enclosing = enclosing.enclosingElement;
            }
            return false;
          }

          if (element is MemberElement) {
            MemberElement member = element;
            member.nestedClosures.forEach((dynamic closure) {
              var localFunction = closure.expression;
              Interval interval = intervalFromElement(localFunction);
              if (interval != null &&
                  interval.contains(sourcePosition) &&
                  isInsideElement(localFunction)) {
                element = localFunction;
              }
            });
          }
          return element;
        }

        void match(Element _element) {
          AstElement element = _element;
          Interval interval = intervalFromElement(element);
          if (interval != null && interval.contains(sourcePosition)) {
            AstElement innerElement = findInnermost(element);
            String expectedName = computeElementNameForSourceMaps(innerElement);
            if (name != expectedName) {
              // For the code
              //    (){}();
              //    ^
              // the indicated position is within the scope of the local
              // function but it is also the position for the invocation of it.
              // Allow name to be either from the local or from its calling
              // context.
              if (innerElement.isLocal && innerElement.isFunction) {
                var enclosingElement = innerElement.enclosingElement;
                String expectedName2 =
                    computeElementNameForSourceMaps(enclosingElement);
                Expect.isTrue(
                    name == expectedName2,
                    "Unexpected name '${name}', "
                    "expected '${expectedName}' for $innerElement "
                    "or '${expectedName2}' for $enclosingElement.");
              } else {
                Expect.equals(
                    expectedName,
                    name,
                    "Unexpected name '${name}', "
                    "expected '${expectedName}' or for $innerElement.");
              }
            }
          }
        }

        compilationUnit.forEachLocalMember((Element element) {
          if (element.isClass) {
            ClassElement classElement = element;
            classElement.forEachLocalMember(match);
          } else {
            match(element);
          }
        });
      }
    }
  });
}

RegExp mainSignaturePrefix = new RegExp(r'main: \[?function\(');

// Check that the line pointing to by [mainPosition] in [mainUri] contains
// the main function signature.
checkMainPosition(Uri targetUri, List<String> targetLines,
    SingleMapping sourceMap, Uri mainUri, Position mainPosition) {
  bool mainPositionFound = false;
  sourceMap.lines.forEach((TargetLineEntry lineEntry) {
    lineEntry.entries.forEach((TargetEntry entry) {
      if (entry.sourceLine == null || entry.sourceUrlId == null) return;
      Uri sourceUri = targetUri.resolve(sourceMap.urls[entry.sourceUrlId]);
      if (sourceUri != mainUri) return;
      if (entry.sourceLine + 1 == mainPosition.line &&
          entry.sourceColumn + 1 == mainPosition.column) {
        Expect.isNotNull(entry.sourceNameId, "Main position has no name.");
        String name = sourceMap.names[entry.sourceNameId];
        Expect.equals(
            'main', name, "Main position name is not '$name', not 'main'.");
        String line = targetLines[lineEntry.line];
        Expect.isTrue(
            line.contains(mainSignaturePrefix),
            "Line mapped to main position "
            "([${lineEntry.line + 1},${entry.column + 1}]) "
            "expected to contain '${mainSignaturePrefix.pattern}':\n$line\n");
        mainPositionFound = true;
      }
    });
  });
  Expect.isTrue(
      mainPositionFound, 'No main position $mainPosition found in $mainUri');
}

sameSourcePoint(TargetEntry entry, TargetEntry otherEntry) {
  return (entry.sourceUrlId == otherEntry.sourceUrlId) &&
      (entry.sourceLine == otherEntry.sourceLine) &&
      (entry.sourceColumn == otherEntry.sourceColumn) &&
      (entry.sourceNameId == otherEntry.sourceNameId);
}

Uri getMapUri(Uri targetUri) {
  print('Accessing $targetUri');
  File targetFile = new File.fromUri(targetUri);
  Expect.isTrue(targetFile.existsSync(), "File '$targetUri' doesn't exist.");
  List<String> target = targetFile.readAsStringSync().split('\n');
  String mapReference = target[target.length - 2]; // #sourceMappingURL=<url>
  Expect.isTrue(mapReference.startsWith('//# sourceMappingURL='));
  String mapName = mapReference.substring(mapReference.indexOf('=') + 1);
  return targetUri.resolve(mapName);
}

SingleMapping getSourceMap(Uri mapUri) {
  print('Accessing $mapUri');
  File mapFile = new File.fromUri(mapUri);
  Expect.isTrue(mapFile.existsSync());
  return new SingleMapping.fromJson(JSON.decode(mapFile.readAsStringSync()));
}

copyDirectory(Directory sourceDir, Directory destinationDir) {
  sourceDir.listSync().forEach((FileSystemEntity element) {
    String newPath =
        path.join(destinationDir.path, path.basename(element.path));
    if (element is File) {
      element.copySync(newPath);
    } else if (element is Directory) {
      Directory newDestinationDir = new Directory(newPath);
      newDestinationDir.createSync();
      copyDirectory(element, newDestinationDir);
    }
  });
}

Future<Directory> createTempDir() {
  return Directory.systemTemp
      .createTemp('sourceMap_test-')
      .then((Directory dir) {
    return dir;
  });
}

class Position {
  final int line;
  final int column;

  const Position(this.line, this.column);

  bool operator <=(Position other) {
    return line < other.line || line == other.line && column <= other.column;
  }

  String toString() => '[${line + 1},${column + 1}]';
}

class Interval {
  final Position begin;
  final Position end;

  Interval(this.begin, this.end);

  bool contains(Position other) {
    return begin <= other && other <= end;
  }

  String toString() => '$begin-$end';
}
