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