// 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.

part of csslib.parser;

// TODO(terry): Add optimizing phase to remove duplicated selectors in the same
//              selector group (e.g., .btn, .btn { color: red; }).  Also, look
//              at simplifying selectors expressions too (much harder).
// TODO(terry): Detect invalid directive usage.  All @imports must occur before
//              all rules other than @charset directive.  Any @import directive
//              after any non @charset or @import directive are ignored. e.g.,
//                  @import "a.css";
//                  div { color: red; }
//                  @import "b.css";
//              becomes:
//                  @import "a.css";
//                  div { color: red; }
// <http://www.w3.org/TR/css3-syntax/#at-rules>

/**
 * Analysis phase will validate/fixup any new CSS feature or any SASS style
 * feature.
 */
class Analyzer {
  final List<StyleSheet> _styleSheets;
  final Messages _messages;

  Analyzer(this._styleSheets, this._messages);

  // TODO(terry): Currently each feature walks the AST each time.  Once we have
  //               our complete feature set consider benchmarking the cost and
  //               possibly combine in one walk.
  void run() {
    // Expand top-level @include.
    _styleSheets.forEach(
        (styleSheet) => TopLevelIncludes.expand(_messages, _styleSheets));

    // Expand @include in declarations.
    _styleSheets.forEach(
        (styleSheet) => DeclarationIncludes.expand(_messages, _styleSheets));

    // Remove all @mixin and @include
    _styleSheets.forEach((styleSheet) => MixinsAndIncludes.remove(styleSheet));

    // Expand any nested selectors using selector desendant combinator to
    // signal CSS inheritance notation.
    _styleSheets.forEach((styleSheet) => new ExpandNestedSelectors()
      ..visitStyleSheet(styleSheet)
      ..flatten(styleSheet));

    // Expand any @extend.
    _styleSheets.forEach((styleSheet) {
      var allExtends = new AllExtends()..visitStyleSheet(styleSheet);
      new InheritExtends(_messages, allExtends)..visitStyleSheet(styleSheet);
    });
  }
}

/**
 * Traverse all rulesets looking for nested ones.  If a ruleset is in a
 * declaration group (implies nested selector) then generate new ruleset(s) at
 * level 0 of CSS using selector inheritance syntax (flattens the nesting).
 *
 * How the AST works for a rule [RuleSet] and nested rules.  First of all a
 * CSS rule [RuleSet] consist of a selector and a declaration e.g.,
 *
 *    selector {
 *      declaration
 *    }
 *
 * AST structure of a [RuleSet] is:
 *
 *    RuleSet
 *       SelectorGroup
 *         List<Selector>
 *            List<SimpleSelectorSequence>
 *              Combinator      // +, >, ~, DESCENDENT, or NONE
 *              SimpleSelector  // class, id, element, namespace, attribute
 *        DeclarationGroup
 *          List                // Declaration or RuleSet
 *
 * For the simple rule:
 *
 *    div + span { color: red; }
 *
 * the AST [RuleSet] is:
 *
 *    RuleSet
 *       SelectorGroup
 *         List<Selector>
 *          [0]
 *            List<SimpleSelectorSequence>
 *              [0] Combinator = COMBINATOR_NONE
 *                  ElementSelector (name = div)
 *              [1] Combinator = COMBINATOR_PLUS
 *                  ElementSelector (name = span)
 *        DeclarationGroup
 *          List                // Declarations or RuleSets
 *            [0]
 *              Declaration (property = color, expression = red)
 *
 * Usually a SelectorGroup contains 1 Selector.  Consider the selectors:
 *
 *    div { color: red; }
 *    a { color: red; }
 *
 * are equivalent to
 *
 *    div, a { color : red; }
 *
 * In the above the RuleSet would have a SelectorGroup with 2 selectors e.g.,
 *
 *    RuleSet
 *       SelectorGroup
 *         List<Selector>
 *          [0]
 *            List<SimpleSelectorSequence>
 *              [0] Combinator = COMBINATOR_NONE
 *                  ElementSelector (name = div)
 *          [1]
 *            List<SimpleSelectorSequence>
 *              [0] Combinator = COMBINATOR_NONE
 *                  ElementSelector (name = a)
 *        DeclarationGroup
 *          List                // Declarations or RuleSets
 *            [0]
 *              Declaration (property = color, expression = red)
 *
 * For a nested rule e.g.,
 *
 *    div {
 *      color : blue;
 *      a { color : red; }
 *    }
 *
 * Would map to the follow CSS rules:
 *
 *    div { color: blue; }
 *    div a { color: red; }
 *
 * The AST for the former nested rule is:
 *
 *    RuleSet
 *       SelectorGroup
 *         List<Selector>
 *          [0]
 *            List<SimpleSelectorSequence>
 *              [0] Combinator = COMBINATOR_NONE
 *                  ElementSelector (name = div)
 *        DeclarationGroup
 *          List                // Declarations or RuleSets
 *            [0]
 *              Declaration (property = color, expression = blue)
 *            [1]
 *              RuleSet
 *                SelectorGroup
 *                  List<Selector>
 *                    [0]
 *                      List<SimpleSelectorSequence>
 *                        [0] Combinator = COMBINATOR_NONE
 *                            ElementSelector (name = a)
 *                DeclarationGroup
 *                  List                // Declarations or RuleSets
 *                    [0]
 *                      Declaration (property = color, expression = red)
 *
 * Nested rules is a terse mechanism to describe CSS inheritance.  The analyzer
 * will flatten and expand the nested rules to it's flatten strucure.  Using the
 * all parent [RuleSets] (selector expressions) and applying each nested
 * [RuleSet] to the list of [Selectors] in a [SelectorGroup].
 *
 * Then result is a style sheet where all nested rules have been flatten and
 * expanded.
 */
class ExpandNestedSelectors extends Visitor {
  /** Parent [RuleSet] if a nested rule otherwise [:null:]. */
  RuleSet _parentRuleSet;

  /** Top-most rule if nested rules. */
  SelectorGroup _topLevelSelectorGroup;

  /** SelectorGroup at each nesting level. */
  SelectorGroup _nestedSelectorGroup;

  /** Declaration (sans the nested selectors). */
  DeclarationGroup _flatDeclarationGroup;

  /** Each nested selector get's a flatten RuleSet. */
  List<RuleSet> _expandedRuleSets = [];

  /** Maping of a nested rule set to the fully expanded list of RuleSet(s). */
  final Map<RuleSet, List<RuleSet>> _expansions = new Map();

  void visitRuleSet(RuleSet node) {
    final oldParent = _parentRuleSet;

    var oldNestedSelectorGroups = _nestedSelectorGroup;

    if (_nestedSelectorGroup == null) {
      // Create top-level selector (may have nested rules).
      final newSelectors = node.selectorGroup.selectors.toList();
      _topLevelSelectorGroup = new SelectorGroup(newSelectors, node.span);
      _nestedSelectorGroup = _topLevelSelectorGroup;
    } else {
      // Generate new selector groups from the nested rules.
      _nestedSelectorGroup = _mergeToFlatten(node);
    }

    _parentRuleSet = node;

    super.visitRuleSet(node);

    _parentRuleSet = oldParent;

    // Remove nested rules; they're all flatten and in the _expandedRuleSets.
    node.declarationGroup.declarations
        .removeWhere((declaration) => declaration is RuleSet);

    _nestedSelectorGroup = oldNestedSelectorGroups;

    // If any expandedRuleSets and we're back at the top-level rule set then
    // there were nested rule set(s).
    if (_parentRuleSet == null) {
      if (_expandedRuleSets.isNotEmpty) {
        // Remember ruleset to replace with these flattened rulesets.
        _expansions[node] = _expandedRuleSets;
        _expandedRuleSets = [];
      }
      assert(_flatDeclarationGroup == null);
      assert(_nestedSelectorGroup == null);
    }
  }

  /**
   * Build up the list of all inherited sequences from the parent selector
   * [node] is the current nested selector and it's parent is the last entry in
   * the [_nestedSelectorGroup].
   */
  SelectorGroup _mergeToFlatten(RuleSet node) {
    // Create a new SelectorGroup for this nesting level.
    var nestedSelectors = _nestedSelectorGroup.selectors;
    var selectors = node.selectorGroup.selectors;

    // Create a merged set of previous parent selectors and current selectors.
    var newSelectors = <Selector>[];
    for (Selector selector in selectors) {
      for (Selector nestedSelector in nestedSelectors) {
        var seq = _mergeNestedSelector(nestedSelector.simpleSelectorSequences,
            selector.simpleSelectorSequences);
        newSelectors.add(new Selector(seq, node.span));
      }
    }

    return new SelectorGroup(newSelectors, node.span);
  }

  /**
   * Merge the nested selector sequences [current] to the [parent] sequences or
   * substitue any & with the parent selector.
   */
  List<SimpleSelectorSequence> _mergeNestedSelector(
      List<SimpleSelectorSequence> parent,
      List<SimpleSelectorSequence> current) {
    // If any & operator then the parent selector will be substituted otherwise
    // the parent selector is pre-pended to the current selector.
    var hasThis = current.any((s) => s.simpleSelector.isThis);

    var newSequence = <SimpleSelectorSequence>[];

    if (!hasThis) {
      // If no & in the sector group then prefix with the parent selector.
      newSequence.addAll(parent);
      newSequence.addAll(_convertToDescendentSequence(current));
    } else {
      for (var sequence in current) {
        if (sequence.simpleSelector.isThis) {
          // Substitue the & with the parent selector and only use a combinator
          // descendant if & is prefix by a sequence with an empty name e.g.,
          // "... + &", "&", "... ~ &", etc.
          var hasPrefix = newSequence.isNotEmpty &&
              newSequence.last.simpleSelector.name.isNotEmpty;
          newSequence.addAll(
              hasPrefix ? _convertToDescendentSequence(parent) : parent);
        } else {
          newSequence.add(sequence);
        }
      }
    }

    return newSequence;
  }

  /**
   * Return selector sequences with first sequence combinator being a
   * descendant.  Used for nested selectors when the parent selector needs to
   * be prefixed to a nested selector or to substitute the this (&) with the
   * parent selector.
   */
  List<SimpleSelectorSequence> _convertToDescendentSequence(
      List<SimpleSelectorSequence> sequences) {
    if (sequences.isEmpty) return sequences;

    var newSequences = <SimpleSelectorSequence>[];
    var first = sequences.first;
    newSequences.add(new SimpleSelectorSequence(
        first.simpleSelector, first.span, TokenKind.COMBINATOR_DESCENDANT));
    newSequences.addAll(sequences.skip(1));

    return newSequences;
  }

  void visitDeclarationGroup(DeclarationGroup node) {
    var span = node.span;

    var currentGroup = new DeclarationGroup([], span);

    var oldGroup = _flatDeclarationGroup;
    _flatDeclarationGroup = currentGroup;

    var expandedLength = _expandedRuleSets.length;

    super.visitDeclarationGroup(node);

    // We're done with the group.
    _flatDeclarationGroup = oldGroup;

    // No nested rule to process it's a top-level rule.
    if (_nestedSelectorGroup == _topLevelSelectorGroup) return;

    // If flatten selector's declaration is empty skip this selector, no need
    // to emit an empty nested selector.
    if (currentGroup.declarations.isEmpty) return;

    var selectorGroup = _nestedSelectorGroup;

    // Build new rule set from the nested selectors and declarations.
    var newRuleSet = new RuleSet(selectorGroup, currentGroup, span);

    // Place in order so outer-most rule is first.
    if (expandedLength == _expandedRuleSets.length) {
      _expandedRuleSets.add(newRuleSet);
    } else {
      _expandedRuleSets.insert(expandedLength, newRuleSet);
    }
  }

  // Record all declarations in a nested selector (Declaration, VarDefinition
  // and MarginGroup) but not the nested rule in the Declaration.

  void visitDeclaration(Declaration node) {
    if (_parentRuleSet != null) {
      _flatDeclarationGroup.declarations.add(node);
    }
    super.visitDeclaration(node);
  }

  void visitVarDefinition(VarDefinition node) {
    if (_parentRuleSet != null) {
      _flatDeclarationGroup.declarations.add(node);
    }
    super.visitVarDefinition(node);
  }

  void visitExtendDeclaration(ExtendDeclaration node) {
    if (_parentRuleSet != null) {
      _flatDeclarationGroup.declarations.add(node);
    }
    super.visitExtendDeclaration(node);
  }

  void visitMarginGroup(MarginGroup node) {
    if (_parentRuleSet != null) {
      _flatDeclarationGroup.declarations.add(node);
    }
    super.visitMarginGroup(node);
  }

  /**
   * Replace the rule set that contains nested rules with the flatten rule sets.
   */
  void flatten(StyleSheet styleSheet) {
    // TODO(terry): Iterate over topLevels instead of _expansions it's already
    //              a map (this maybe quadratic).
    _expansions.forEach((RuleSet ruleSet, List<RuleSet> newRules) {
      var index = styleSheet.topLevels.indexOf(ruleSet);
      if (index == -1) {
        // Check any @media directives for nested rules and replace them.
        var found = _MediaRulesReplacer.replace(styleSheet, ruleSet, newRules);
        assert(found);
      } else {
        styleSheet.topLevels.insertAll(index + 1, newRules);
      }
    });
    _expansions.clear();
  }
}

class _MediaRulesReplacer extends Visitor {
  RuleSet _ruleSet;
  List<RuleSet> _newRules;
  bool _foundAndReplaced = false;

  /**
   * Look for the [ruleSet] inside of an @media directive; if found then replace
   * with the [newRules].  If [ruleSet] is found and replaced return true.
   */
  static bool replace(
      StyleSheet styleSheet, RuleSet ruleSet, List<RuleSet> newRules) {
    var visitor = new _MediaRulesReplacer(ruleSet, newRules);
    visitor.visitStyleSheet(styleSheet);
    return visitor._foundAndReplaced;
  }

  _MediaRulesReplacer(this._ruleSet, this._newRules);

  visitMediaDirective(MediaDirective node) {
    var index = node.rules.indexOf(_ruleSet);
    if (index != -1) {
      node.rules.insertAll(index + 1, _newRules);
      _foundAndReplaced = true;
    }
  }
}

/**
 * Expand all @include at the top-level the ruleset(s) associated with the
 * mixin.
 */
class TopLevelIncludes extends Visitor {
  StyleSheet _styleSheet;
  final Messages _messages;
  /** Map of variable name key to it's definition. */
  final Map<String, MixinDefinition> map = new Map<String, MixinDefinition>();
  MixinDefinition currDef;

  static void expand(Messages messages, List<StyleSheet> styleSheets) {
    new TopLevelIncludes(messages, styleSheets);
  }

  bool _anyRulesets(MixinRulesetDirective def) =>
      def.rulesets.any((rule) => rule is RuleSet);

  TopLevelIncludes(this._messages, List<StyleSheet> styleSheets) {
    for (var styleSheet in styleSheets) {
      visitTree(styleSheet);
    }
  }

  void visitStyleSheet(StyleSheet ss) {
    _styleSheet = ss;
    super.visitStyleSheet(ss);
    _styleSheet = null;
  }

  void visitIncludeDirective(IncludeDirective node) {
    if (map.containsKey(node.name)) {
      var mixinDef = map[node.name];
      if (mixinDef is MixinRulesetDirective) {
        _TopLevelIncludeReplacer.replace(
            _messages, _styleSheet, node, mixinDef.rulesets);
      } else if (currDef is MixinRulesetDirective && _anyRulesets(currDef)) {
        // currDef is MixinRulesetDirective
        MixinRulesetDirective mixinRuleset = currDef;
        int index = mixinRuleset.rulesets.indexOf(node);
        mixinRuleset.rulesets.removeAt(index);
        _messages.warning(
            'Using declaration mixin ${node.name} as top-level mixin',
            node.span);
      }
    } else {
      if (currDef is MixinRulesetDirective) {
        MixinRulesetDirective rulesetDirect = currDef as MixinRulesetDirective;
        rulesetDirect.rulesets.removeWhere((entry) {
          if (entry == node) {
            _messages.warning('Undefined mixin ${node.name}', node.span);
            return true;
          }
          return false;
        });
      }
    }
    super.visitIncludeDirective(node);
  }

  void visitMixinRulesetDirective(MixinRulesetDirective node) {
    currDef = node;

    super.visitMixinRulesetDirective(node);

    // Replace with latest top-level mixin definition.
    map[node.name] = node;
    currDef = null;
  }

  void visitMixinDeclarationDirective(MixinDeclarationDirective node) {
    currDef = node;

    super.visitMixinDeclarationDirective(node);

    // Replace with latest mixin definition.
    map[node.name] = node;
    currDef = null;
  }
}

/** @include as a top-level with ruleset(s). */
class _TopLevelIncludeReplacer extends Visitor {
  final Messages _messages;
  final IncludeDirective _include;
  final List<TreeNode> _newRules;
  bool _foundAndReplaced = false;

  /**
   * Look for the [ruleSet] inside of an @media directive; if found then replace
   * with the [newRules].  If [ruleSet] is found and replaced return true.
   */
  static bool replace(Messages messages, StyleSheet styleSheet,
      IncludeDirective include, List<TreeNode> newRules) {
    var visitor = new _TopLevelIncludeReplacer(messages, include, newRules);
    visitor.visitStyleSheet(styleSheet);
    return visitor._foundAndReplaced;
  }

  _TopLevelIncludeReplacer(this._messages, this._include, this._newRules);

  visitStyleSheet(StyleSheet node) {
    var index = node.topLevels.indexOf(_include);
    if (index != -1) {
      node.topLevels.insertAll(index + 1, _newRules);
      node.topLevels.replaceRange(index, index + 1, [new NoOp()]);
      _foundAndReplaced = true;
    }
    super.visitStyleSheet(node);
  }

  void visitMixinRulesetDirective(MixinRulesetDirective node) {
    var index = node.rulesets.indexOf(_include as dynamic);
    if (index != -1) {
      node.rulesets.insertAll(index + 1, _newRules);
      // Only the resolve the @include once.
      node.rulesets.replaceRange(index, index + 1, [new NoOp()]);
      _foundAndReplaced = true;
    }
    super.visitMixinRulesetDirective(node);
  }
}

/**
 * Utility function to match an include to a list of either Declarations or
 * RuleSets, depending on type of mixin (ruleset or declaration).  The include
 * can be an include in a declaration or an include directive (top-level).
 */
int _findInclude(List list, var node) {
  IncludeDirective matchNode =
      (node is IncludeMixinAtDeclaration) ? node.include : node;

  var index = 0;
  for (var item in list) {
    var includeNode = (item is IncludeMixinAtDeclaration) ? item.include : item;
    if (includeNode == matchNode) return index;
    index++;
  }
  return -1;
}

/**
 * Stamp out a mixin with the defined args substituted with the user's
 * parameters.
 */
class CallMixin extends Visitor {
  final MixinDefinition mixinDef;
  List _definedArgs;
  Expressions _currExpressions;
  int _currIndex = -1;

  final varUsages = new Map<String, Map<Expressions, Set<int>>>();

  /** Only var defs with more than one expression (comma separated). */
  final Map<String, VarDefinition> varDefs;

  CallMixin(this.mixinDef, [this.varDefs]) {
    if (mixinDef is MixinRulesetDirective) {
      visitMixinRulesetDirective(mixinDef);
    } else {
      visitMixinDeclarationDirective(mixinDef);
    }
  }

  /**
   * Given a mixin's defined arguments return a cloned mixin defintion that has
   * replaced all defined arguments with user's supplied VarUsages.
   */
  MixinDefinition transform(List<List<Expression>> callArgs) {
    // TODO(terry): Handle default arguments and varArgs.
    // Transform mixin with callArgs.
    for (var index = 0; index < _definedArgs.length; index++) {
      var definedArg = _definedArgs[index];
      VarDefinition varDef;
      if (definedArg is VarDefinition) {
        varDef = definedArg;
      } else if (definedArg is VarDefinitionDirective) {
        VarDefinitionDirective varDirective = definedArg;
        varDef = varDirective.def;
      }
      var callArg = callArgs[index];

      // Is callArg a var definition with multi-args (expressions > 1).
      var defArgs = _varDefsAsCallArgs(callArg);
      if (defArgs.isNotEmpty) {
        // Replace call args with the var def parameters.
        callArgs.insertAll(index, defArgs);
        callArgs.removeAt(index + defArgs.length);
        callArg = callArgs[index];
      }

      var expressions = varUsages[varDef.definedName];
      expressions.forEach((k, v) {
        for (var usagesIndex in v) {
          k.expressions.replaceRange(usagesIndex, usagesIndex + 1, callArg);
        }
      });
    }

    // Clone the mixin
    return mixinDef.clone();
  }

  /** Rip apart var def with multiple parameters. */
  List<List<Expression>> _varDefsAsCallArgs(var callArg) {
    var defArgs = <List<Expression>>[];
    if (callArg is List && callArg[0] is VarUsage) {
      var varDef = varDefs[callArg[0].name];
      var expressions = (varDef.expression as Expressions).expressions;
      assert(expressions.length > 1);
      for (var expr in expressions) {
        if (expr is! OperatorComma) {
          defArgs.add([expr]);
        }
      }
    }
    return defArgs;
  }

  void visitExpressions(Expressions node) {
    var oldExpressions = _currExpressions;
    var oldIndex = _currIndex;

    _currExpressions = node;
    for (_currIndex = 0; _currIndex < node.expressions.length; _currIndex++) {
      node.expressions[_currIndex].visit(this);
    }

    _currIndex = oldIndex;
    _currExpressions = oldExpressions;
  }

  void _addExpression(Map<Expressions, Set<int>> expressions) {
    var indexSet = new Set<int>();
    indexSet.add(_currIndex);
    expressions[_currExpressions] = indexSet;
  }

  void visitVarUsage(VarUsage node) {
    assert(_currIndex != -1);
    assert(_currExpressions != null);
    if (varUsages.containsKey(node.name)) {
      Map<Expressions, Set<int>> expressions = varUsages[node.name];
      Set<int> allIndexes = expressions[_currExpressions];
      if (allIndexes == null) {
        _addExpression(expressions);
      } else {
        allIndexes.add(_currIndex);
      }
    } else {
      var newExpressions = new Map<Expressions, Set<int>>();
      _addExpression(newExpressions);
      varUsages[node.name] = newExpressions;
    }
    super.visitVarUsage(node);
  }

  void visitMixinDeclarationDirective(MixinDeclarationDirective node) {
    _definedArgs = node.definedArgs;
    super.visitMixinDeclarationDirective(node);
  }

  void visitMixinRulesetDirective(MixinRulesetDirective node) {
    _definedArgs = node.definedArgs;
    super.visitMixinRulesetDirective(node);
  }
}

/** Expand all @include inside of a declaration associated with a mixin. */
class DeclarationIncludes extends Visitor {
  StyleSheet _styleSheet;
  final Messages _messages;
  /** Map of variable name key to it's definition. */
  final Map<String, MixinDefinition> map = new Map<String, MixinDefinition>();
  /** Cache of mixin called with parameters. */
  final Map<String, CallMixin> callMap = new Map<String, CallMixin>();
  MixinDefinition currDef;
  DeclarationGroup currDeclGroup;

  /** Var definitions with more than 1 expression. */
  final Map<String, VarDefinition> varDefs = new Map<String, VarDefinition>();

  static void expand(Messages messages, List<StyleSheet> styleSheets) {
    new DeclarationIncludes(messages, styleSheets);
  }

  DeclarationIncludes(this._messages, List<StyleSheet> styleSheets) {
    for (var styleSheet in styleSheets) {
      visitTree(styleSheet);
    }
  }

  bool _allIncludes(rulesets) =>
      rulesets.every((rule) => rule is IncludeDirective || rule is NoOp);

  CallMixin _createCallDeclMixin(MixinDefinition mixinDef) {
    callMap.putIfAbsent(mixinDef.name,
        () => callMap[mixinDef.name] = new CallMixin(mixinDef, varDefs));
    return callMap[mixinDef.name];
  }

  void visitStyleSheet(StyleSheet ss) {
    _styleSheet = ss;
    super.visitStyleSheet(ss);
    _styleSheet = null;
  }

  void visitDeclarationGroup(DeclarationGroup node) {
    currDeclGroup = node;
    super.visitDeclarationGroup(node);
    currDeclGroup = null;
  }

  void visitIncludeMixinAtDeclaration(IncludeMixinAtDeclaration node) {
    if (map.containsKey(node.include.name)) {
      var mixinDef = map[node.include.name];

      // Fix up any mixin that is really a Declaration but has includes.
      if (mixinDef is MixinRulesetDirective) {
        if (!_allIncludes(mixinDef.rulesets) && currDeclGroup != null) {
          var index = _findInclude(currDeclGroup.declarations, node);
          if (index != -1) {
            currDeclGroup.declarations
                .replaceRange(index, index + 1, [new NoOp()]);
          }
          _messages.warning(
              "Using top-level mixin ${node.include.name} as a declaration",
              node.span);
        } else {
          // We're a list of @include(s) inside of a mixin ruleset - convert
          // to a list of IncludeMixinAtDeclaration(s).
          var origRulesets = mixinDef.rulesets;
          var rulesets = <Declaration>[];
          if (origRulesets.every((ruleset) => ruleset is IncludeDirective)) {
            origRulesets.forEach((ruleset) {
              rulesets.add(new IncludeMixinAtDeclaration(
                  ruleset as IncludeDirective, ruleset.span));
            });
            _IncludeReplacer.replace(_styleSheet, node, rulesets);
          }
        }
      }

      if (mixinDef.definedArgs.length > 0 && node.include.args.length > 0) {
        var callMixin = _createCallDeclMixin(mixinDef);
        mixinDef = callMixin.transform(node.include.args);
      }

      if (mixinDef is MixinDeclarationDirective) {
        _IncludeReplacer.replace(
            _styleSheet, node, mixinDef.declarations.declarations);
      }
    } else {
      _messages.warning("Undefined mixin ${node.include.name}", node.span);
    }

    super.visitIncludeMixinAtDeclaration(node);
  }

  void visitIncludeDirective(IncludeDirective node) {
    if (map.containsKey(node.name)) {
      var mixinDef = map[node.name];
      if (currDef is MixinDeclarationDirective &&
          mixinDef is MixinDeclarationDirective) {
        _IncludeReplacer.replace(
            _styleSheet, node, mixinDef.declarations.declarations);
      } else if (currDef is MixinDeclarationDirective) {
        var decls =
            (currDef as MixinDeclarationDirective).declarations.declarations;
        var index = _findInclude(decls, node);
        if (index != -1) {
          decls.replaceRange(index, index + 1, [new NoOp()]);
        }
      }
    }

    super.visitIncludeDirective(node);
  }

  void visitMixinRulesetDirective(MixinRulesetDirective node) {
    currDef = node;

    super.visitMixinRulesetDirective(node);

    // Replace with latest top-level mixin definition.
    map[node.name] = node;
    currDef = null;
  }

  void visitMixinDeclarationDirective(MixinDeclarationDirective node) {
    currDef = node;

    super.visitMixinDeclarationDirective(node);

    // Replace with latest mixin definition.
    map[node.name] = node;
    currDef = null;
  }

  void visitVarDefinition(VarDefinition node) {
    // Only record var definitions that have multiple expressions (comma
    // separated for mixin parameter substitution.
    var exprs = (node.expression as Expressions).expressions;
    if (exprs.length > 1) {
      varDefs[node.definedName] = node;
    }
    super.visitVarDefinition(node);
  }

  void visitVarDefinitionDirective(VarDefinitionDirective node) {
    visitVarDefinition(node.def);
  }
}

/** @include as a top-level with ruleset(s). */
class _IncludeReplacer extends Visitor {
  final _include;
  final List<TreeNode> _newDeclarations;
  bool _foundAndReplaced = false;

  /**
   * Look for the [ruleSet] inside of a @media directive; if found then replace
   * with the [newRules].
   */
  static void replace(
      StyleSheet ss, var include, List<TreeNode> newDeclarations) {
    var visitor = new _IncludeReplacer(include, newDeclarations);
    visitor.visitStyleSheet(ss);
  }

  _IncludeReplacer(this._include, this._newDeclarations);

  void visitDeclarationGroup(DeclarationGroup node) {
    var index = _findInclude(node.declarations, _include);
    if (index != -1) {
      node.declarations.insertAll(index + 1, _newDeclarations);
      // Change @include to NoOp so it's processed only once.
      node.declarations.replaceRange(index, index + 1, [new NoOp()]);
      _foundAndReplaced = true;
    }
    super.visitDeclarationGroup(node);
  }
}

/**
 * Remove all @mixin and @include and any NoOp used as placeholder for @include.
 */
class MixinsAndIncludes extends Visitor {
  static void remove(StyleSheet styleSheet) {
    new MixinsAndIncludes()..visitStyleSheet(styleSheet);
  }

  bool _nodesToRemove(node) =>
      node is IncludeDirective || node is MixinDefinition || node is NoOp;

  void visitStyleSheet(StyleSheet ss) {
    var index = ss.topLevels.length;
    while (--index >= 0) {
      if (_nodesToRemove(ss.topLevels[index])) {
        ss.topLevels.removeAt(index);
      }
    }
    super.visitStyleSheet(ss);
  }

  void visitDeclarationGroup(DeclarationGroup node) {
    var index = node.declarations.length;
    while (--index >= 0) {
      if (_nodesToRemove(node.declarations[index])) {
        node.declarations.removeAt(index);
      }
    }
    super.visitDeclarationGroup(node);
  }
}

/** Find all @extend to create inheritance. */
class AllExtends extends Visitor {
  final Map<String, List<SelectorGroup>> inherits =
      new Map<String, List<SelectorGroup>>();

  SelectorGroup _currSelectorGroup;
  int _currDeclIndex;
  final List<int> _extendsToRemove = [];

  void visitRuleSet(RuleSet node) {
    var oldSelectorGroup = _currSelectorGroup;
    _currSelectorGroup = node.selectorGroup;

    super.visitRuleSet(node);

    _currSelectorGroup = oldSelectorGroup;
  }

  void visitExtendDeclaration(ExtendDeclaration node) {
    var inheritName = "";
    for (var selector in node.selectors) {
      inheritName += selector.toString();
    }
    if (inherits.containsKey(inheritName)) {
      inherits[inheritName].add(_currSelectorGroup);
    } else {
      inherits[inheritName] = [_currSelectorGroup];
    }

    // Remove this @extend
    _extendsToRemove.add(_currDeclIndex);

    super.visitExtendDeclaration(node);
  }

  void visitDeclarationGroup(DeclarationGroup node) {
    var oldDeclIndex = _currDeclIndex;

    var decls = node.declarations;
    for (_currDeclIndex = 0; _currDeclIndex < decls.length; _currDeclIndex++) {
      decls[_currDeclIndex].visit(this);
    }

    if (_extendsToRemove.isNotEmpty) {
      var removeTotal = _extendsToRemove.length - 1;
      for (var index = removeTotal; index >= 0; index--) {
        decls.removeAt(_extendsToRemove[index]);
      }
      _extendsToRemove.clear();
    }

    _currDeclIndex = oldDeclIndex;
  }
}

// TODO(terry): Need to handle merging selector sequences
// TODO(terry): Need to handle @extend-Only selectors.
// TODO(terry): Need to handle !optional glag.
/**
 * Changes any selector that matches @extend.
 */
class InheritExtends extends Visitor {
  final Messages _messages;
  final AllExtends _allExtends;

  InheritExtends(this._messages, this._allExtends);

  void visitSelectorGroup(SelectorGroup node) {
    for (var selectorsIndex = 0;
        selectorsIndex < node.selectors.length;
        selectorsIndex++) {
      var selectors = node.selectors[selectorsIndex];
      var isLastNone = false;
      var selectorName = "";
      for (var index = 0;
          index < selectors.simpleSelectorSequences.length;
          index++) {
        var simpleSeq = selectors.simpleSelectorSequences[index];
        var namePart = simpleSeq.simpleSelector.toString();
        selectorName = (isLastNone) ? (selectorName + namePart) : namePart;
        List<SelectorGroup> matches = _allExtends.inherits[selectorName];
        if (matches != null) {
          for (var match in matches) {
            // Create a new group.
            var newSelectors = selectors.clone();
            var newSeq = match.selectors[0].clone();
            if (isLastNone) {
              // Add the inherited selector.
              node.selectors.add(newSeq);
            } else {
              // Replace the selector sequence to the left of the pseudo class
              // or pseudo element.

              // Make new selector seq combinator the same as the original.
              var orgCombinator =
                  newSelectors.simpleSelectorSequences[index].combinator;
              newSeq.simpleSelectorSequences[0].combinator = orgCombinator;

              newSelectors.simpleSelectorSequences.replaceRange(
                  index, index + 1, newSeq.simpleSelectorSequences);
              node.selectors.add(newSelectors);
            }
            isLastNone = false;
          }
        } else {
          isLastNone = simpleSeq.isCombinatorNone;
        }
      }
    }
    super.visitSelectorGroup(node);
  }
}
