// Copyright (c) 2015, the Fletch 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.md file.

/// Tools for loading and parsing platform-configuration files.
library plaform_configuration;

import "dart:async";

import "package:charcode/ascii.dart";

import "../compiler_new.dart" as api;

/// Parses an Ini-like format.
///
/// Sections are initialized with a name enclosed in brackets.
/// Each section contain zero or more properties of the form "name:value".
/// Empty lines are ignored.
/// Lines starting with # are ignored.
/// Duplicate names are not allowed.
/// All keys and values will be passed through [String.trim].
///
/// If an error is found, a [FormatException] is thrown, using [sourceUri] in
/// the error message.
///
/// Example
/// ```
/// [a]
/// b:c
///
/// [d]
/// e:file:///tmp/bla
/// ```
/// Will parse to {"a": {"b":"c"}, "d": {"e": "file:///tmp/bla"}}.

Map<String, Map<String, String>> parseIni(List<int> source,
    {Set<String> allowedSections, Uri sourceUri}) {
  int startOfLine = 0;
  int currentLine = 0;

  error(String message, int index) {
    int column = index - startOfLine + 1;
    throw new FormatException(
        "$sourceUri:$currentLine:$column: $message", sourceUri, index);
  }

  Map<String, Map<String, String>> result =
      new Map<String, Map<String, String>>();
  Map<String, String> currentSection = null;

  if (source.length == 0) return result;
  bool endOfFile = false;

  // Iterate once per $lf in file.
  while (!endOfFile) {
    currentLine += 1;
    int endOfLine = source.indexOf($lf, startOfLine);
    if (endOfLine == -1) {
      // The dart2js provider adds a final 0 to the file.
      endOfLine = source.last == 0 ? source.length - 1 : source.length;
      endOfFile = true;
    }
    if (startOfLine != endOfLine) {
      int firstChar = source[startOfLine];
      if (firstChar == $hash) {
        // Comment, do nothing.
      } else if (firstChar == $open_bracket) {
        // Section header
        int endOfHeader = source.indexOf($close_bracket, startOfLine);
        if (endOfHeader == -1) {
          error("'[' must be matched by ']' on the same line.", startOfLine);
        }
        if (endOfHeader == startOfLine + 1) {
          error("Empty header name", startOfLine + 1);
        }
        if (endOfHeader != endOfLine - 1) {
          error("Section heading lines must end with ']'", endOfHeader + 1);
        }
        int startOfSectionName = startOfLine + 1;
        String sectionName =
            new String.fromCharCodes(source, startOfSectionName, endOfHeader)
                .trim();
        currentSection = new Map<String, String>();
        if (result.containsKey(sectionName)) {
          error("Duplicate section name '$sectionName'", startOfSectionName);
        }
        if (allowedSections != null && !allowedSections.contains(sectionName)) {
          error("Unrecognized section name '$sectionName'", startOfSectionName);
        }
        result[sectionName] = currentSection;
      } else {
        // Property line
        if (currentSection == null) {
          error("Property outside section", startOfLine);
        }
        int separator = source.indexOf($colon, startOfLine);
        if (separator == startOfLine) {
          error("Empty property name", startOfLine);
        }
        if (separator == -1 || separator > endOfLine) {
          error("Property line without ':'", startOfLine);
        }
        String propertyName =
            new String.fromCharCodes(source, startOfLine, separator).trim();
        if (currentSection.containsKey(propertyName)) {
          error("Duplicate property name '$propertyName'", startOfLine);
        }
        String propertyValue =
            new String.fromCharCodes(source, separator + 1, endOfLine).trim();
        currentSection[propertyName] = propertyValue;
      }
    }
    startOfLine = endOfLine + 1;
  }
  return result;
}

const String librariesSection = "libraries";
const String dartSpecSection = "dart-spec";
const String featuresSection = "features";

Map<String, Uri> libraryMappings(
    Map<String, Map<String, String>> sections, Uri baseLocation) {
  assert(sections.containsKey(librariesSection));
  Map<String, Uri> result = new Map<String, Uri>();
  sections[librariesSection].forEach((String name, String value) {
    result[name] = baseLocation.resolve(value);
  });
  return result;
}

final Set<String> allowedSections =
    new Set.from([librariesSection, dartSpecSection, featuresSection]);

Future<Map<String, Uri>> load(Uri location, api.CompilerInput provider) {
  return provider.readFromUri(location).then((contents) {
    if (contents is String) {
      contents = contents.codeUnits;
    }
    return libraryMappings(
        parseIni(contents,
            allowedSections: allowedSections, sourceUri: location),
        location);
  });
}
