// Copyright (c) 2013, 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;

/// CSS polyfill emits CSS to be understood by older parsers that which do not
/// understand (var, calc, etc.).
class PolyFill {
  final Messages _messages;
  Map<String, VarDefinition> _allVarDefinitions =
      new Map<String, VarDefinition>();

  Set<StyleSheet> allStyleSheets = new Set<StyleSheet>();

  /// [_pseudoElements] list of known pseudo attributes found in HTML, any
  /// CSS pseudo-elements 'name::custom-element' is mapped to the manged name
  /// associated with the pseudo-element key.
  PolyFill(this._messages);

  /// Run the analyzer on every file that is a style sheet or any component that
  /// has a style tag.
  void process(StyleSheet styleSheet, {List<StyleSheet> includes: null}) {
    if (includes != null) {
      processVarDefinitions(includes);
    }
    processVars(styleSheet);

    // Remove all var definitions for this style sheet.
    new _RemoveVarDefinitions().visitTree(styleSheet);
  }

  /// Process all includes looking for var definitions.
  void processVarDefinitions(List<StyleSheet> includes) {
    for (var include in includes) {
      _allVarDefinitions = (new _VarDefinitionsIncludes(_allVarDefinitions)
            ..visitTree(include))
          .varDefs;
    }
  }

  void processVars(StyleSheet styleSheet) {
    // Build list of all var definitions.
    var mainStyleSheetVarDefs =
        (new _VarDefAndUsage(this._messages, _allVarDefinitions)
              ..visitTree(styleSheet))
            .varDefs;

    // Resolve all definitions to a non-VarUsage (terminal expression).
    mainStyleSheetVarDefs.forEach((key, value) {
      for (var _ in (value.expression as Expressions).expressions) {
        mainStyleSheetVarDefs[key] =
            _findTerminalVarDefinition(_allVarDefinitions, value);
      }
    });
  }
}

/// Build list of all var definitions in all includes.
class _VarDefinitionsIncludes extends Visitor {
  final Map<String, VarDefinition> varDefs;

  _VarDefinitionsIncludes(this.varDefs);

  void visitTree(StyleSheet tree) {
    visitStyleSheet(tree);
  }

  visitVarDefinition(VarDefinition node) {
    // Replace with latest variable definition.
    varDefs[node.definedName] = node;
    super.visitVarDefinition(node);
  }

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

/// Find var- definitions in a style sheet.
/// [found] list of known definitions.
class _VarDefAndUsage extends Visitor {
  final Messages _messages;
  final Map<String, VarDefinition> _knownVarDefs;
  final Map<String, VarDefinition> varDefs = new Map<String, VarDefinition>();

  VarDefinition currVarDefinition;
  List<Expression> currentExpressions;

  _VarDefAndUsage(this._messages, this._knownVarDefs);

  void visitTree(StyleSheet tree) {
    visitStyleSheet(tree);
  }

  visitVarDefinition(VarDefinition node) {
    // Replace with latest variable definition.
    currVarDefinition = node;

    _knownVarDefs[node.definedName] = node;
    varDefs[node.definedName] = node;

    super.visitVarDefinition(node);

    currVarDefinition = null;
  }

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

  void visitExpressions(Expressions node) {
    currentExpressions = node.expressions;
    super.visitExpressions(node);
    currentExpressions = null;
  }

  void visitVarUsage(VarUsage node) {
    if (currVarDefinition != null && currVarDefinition.badUsage) return;

    // Don't process other var() inside of a varUsage.  That implies that the
    // default is a var() too.  Also, don't process any var() inside of a
    // varDefinition (they're just place holders until we've resolved all real
    // usages.
    var expressions = currentExpressions;
    var index = expressions.indexOf(node);
    assert(index >= 0);
    var def = _knownVarDefs[node.name];
    if (def != null) {
      if (def.badUsage) {
        // Remove any expressions pointing to a bad var definition.
        expressions.removeAt(index);
        return;
      }
      _resolveVarUsage(currentExpressions, index,
          _findTerminalVarDefinition(_knownVarDefs, def));
    } else if (node.defaultValues.any((e) => e is VarUsage)) {
      // Don't have a VarDefinition need to use default values resolve all
      // default values.
      var terminalDefaults = <Expression>[];
      for (var defaultValue in node.defaultValues) {
        terminalDefaults.addAll(resolveUsageTerminal(defaultValue));
      }
      expressions.replaceRange(index, index + 1, terminalDefaults);
    } else if (node.defaultValues.isNotEmpty) {
      // No VarDefinition but default value is a terminal expression; use it.
      expressions.replaceRange(index, index + 1, node.defaultValues);
    } else {
      if (currVarDefinition != null) {
        currVarDefinition.badUsage = true;
        var mainStyleSheetDef = varDefs[node.name];
        if (mainStyleSheetDef != null) {
          varDefs.remove(currVarDefinition.property);
        }
      }
      // Remove var usage that points at an undefined definition.
      expressions.removeAt(index);
      _messages.warning("Variable is not defined.", node.span);
    }

    var oldExpressions = currentExpressions;
    currentExpressions = node.defaultValues;
    super.visitVarUsage(node);
    currentExpressions = oldExpressions;
  }

  List<Expression> resolveUsageTerminal(VarUsage usage) {
    var result = <Expression>[];

    var varDef = _knownVarDefs[usage.name];
    var expressions;
    if (varDef == null) {
      // VarDefinition not found try the defaultValues.
      expressions = usage.defaultValues;
    } else {
      // Use the VarDefinition found.
      expressions = (varDef.expression as Expressions).expressions;
    }

    for (var expr in expressions) {
      if (expr is VarUsage) {
        // Get terminal value.
        result.addAll(resolveUsageTerminal(expr));
      }
    }

    // We're at a terminal just return the VarDefinition expression.
    if (result.isEmpty && varDef != null) {
      result = (varDef.expression as Expressions).expressions;
    }

    return result;
  }

  _resolveVarUsage(List<Expression> expressions, int index, VarDefinition def) {
    var defExpressions = (def.expression as Expressions).expressions;
    expressions.replaceRange(index, index + 1, defExpressions);
  }
}

/// Remove all var definitions.
class _RemoveVarDefinitions extends Visitor {
  void visitTree(StyleSheet tree) {
    visitStyleSheet(tree);
  }

  void visitStyleSheet(StyleSheet ss) {
    ss.topLevels.removeWhere((e) => e is VarDefinitionDirective);
    super.visitStyleSheet(ss);
  }

  void visitDeclarationGroup(DeclarationGroup node) {
    node.declarations.removeWhere((e) => e is VarDefinition);
    super.visitDeclarationGroup(node);
  }
}

/// Find terminal definition (non VarUsage implies real CSS value).
VarDefinition _findTerminalVarDefinition(
    Map<String, VarDefinition> varDefs, VarDefinition varDef) {
  var expressions = varDef.expression as Expressions;
  for (var expr in expressions.expressions) {
    if (expr is VarUsage) {
      var usageName = expr.name;
      var foundDef = varDefs[usageName];

      // If foundDef is unknown check if defaultValues; if it exist then resolve
      // to terminal value.
      if (foundDef == null) {
        // We're either a VarUsage or terminal definition if in varDefs;
        // either way replace VarUsage with it's default value because the
        // VarDefinition isn't found.
        var defaultValues = expr.defaultValues;
        var replaceExprs = expressions.expressions;
        assert(replaceExprs.length == 1);
        replaceExprs.replaceRange(0, 1, defaultValues);
        return varDef;
      }
      if (foundDef is VarDefinition) {
        return _findTerminalVarDefinition(varDefs, foundDef);
      }
    } else {
      // Return real CSS property.
      return varDef;
    }
  }

  // Didn't point to a var definition that existed.
  return varDef;
}
