// Copyright (c) 2012, 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 csslib.src.validate;

import 'package:csslib/visitor.dart';
import 'package:source_span/source_span.dart';

/** Can be thrown on any Css runtime problem includes source location. */
class CssSelectorException extends SourceSpanException {
  CssSelectorException(String message, [SourceSpan span])
      : super(message, span);
}

List<String> classes = [];
List<String> ids = [];

class Validate {
  static int _classNameCheck(var selector, int matches) {
    if (selector.isCombinatorDescendant() ||
        (selector.isCombinatorNone() && matches == 0)) {
      if (matches < 0) {
        String tooMany = selector.simpleSelector.toString();
        throw new CssSelectorException(
            'Can not mix Id selector with class selector(s). Id '
            'selector must be singleton too many starting at $tooMany');
      }

      return matches + 1;
    } else {
      String error = selector.toString();
      throw new CssSelectorException(
          'Selectors can not have combinators (>, +, or ~) before $error');
    }
  }

  static int _elementIdCheck(var selector, int matches) {
    if (selector.isCombinatorNone() && matches == 0) {
      // Perfect just one element id returns matches of -1.
      return -1;
    } else if (selector.isCombinatorDescendant()) {
      String tooMany = selector.simpleSelector.toString();
      throw new CssSelectorException(
          'Use of Id selector must be singleton starting at $tooMany');
    } else {
      String error = selector.simpleSelector.toString();
      throw new CssSelectorException(
          'Selectors can not have combinators (>, +, or ~) before $error');
    }
  }

  // Validate the @{css expression} only .class and #elementId are valid inside
  // of @{...}.
  static template(List<Selector> selectors) {
    var errorSelector; // signal which selector didn't match.
    bool found = false; // signal if a selector is matched.
    int matches = 0; // < 0 IdSelectors, > 0 ClassSelector

    // At most one selector group (any number of simple selector sequences).
    assert(selectors.length <= 1);

    for (final sels in selectors) {
      for (final selector in sels.simpleSelectorSequences) {
        found = false;
        var simpleSelector = selector.simpleSelector;
        if (simpleSelector is ClassSelector) {
          // Any class name starting with an underscore is a private class name
          // that doesn't have to match the world of known classes.
          if (!simpleSelector.name.startsWith('_')) {
            // TODO(terry): For now iterate through all classes look for faster
            //              mechanism hash map, etc.
            for (final className in classes) {
              if (selector.simpleSelector.name == className) {
                matches = _classNameCheck(selector, matches);
                found = true; // .class found.
                break;
              }
              for (final className2 in classes) {
                print(className2);
              }
            }
          } else {
            // Don't check any class name that is prefixed with an underscore.
            // However, signal as found and bump up matches; it's a valid class
            // name.
            matches = _classNameCheck(selector, matches);
            found = true; // ._class are always okay.
          }
        } else if (simpleSelector is IdSelector) {
          // Any element id starting with an underscore is a private element id
          // that doesn't have to match the world of known elemtn ids.
          if (!simpleSelector.name.startsWith('_')) {
            for (final id in ids) {
              if (simpleSelector.name == id) {
                matches = _elementIdCheck(selector, matches);
                found = true; // #id found.
                break;
              }
            }
          } else {
            // Don't check any element ID that is prefixed with an underscore.
            // Signal as found and bump up matches; it's a valid element ID.
            matches = _elementIdCheck(selector, matches);
            found = true; // #_id are always okay
          }
        } else {
          String badSelector = simpleSelector.toString();
          throw new CssSelectorException(
              'Invalid template selector $badSelector');
        }

        if (!found) {
          String unknownName = simpleSelector.toString();
          throw new CssSelectorException('Unknown selector name $unknownName');
        }
      }
    }

    // Every selector must match.
    Selector selector = selectors[0];
    assert((matches >= 0 ? matches : -matches) ==
        selector.simpleSelectorSequences.length);
  }
}
