'use strict';

var helpers = require('../helpers');
var properties = require('known-css-properties').all;
var PROP_DIVIDER = '-';
/**
 * Combine the valid property array and the array of extras into a new array
 *
 * @param {Array} props - The list of default valid properties
 * @param {Array} extras - The user specified list of valid properties
 * @returns {Array} Combined list
 */
var getCombinedList = function (props, extras) {
  return props.concat(extras);
};

var buildPartialProperty = function (valBlock, currentProperty, propsCounted) {
  var propList = [];
  var propsEncountered = propsCounted;
  if (valBlock.contains('declaration')) {
    valBlock.forEach('declaration', function (node) {
      var prop = node.first('property');
      var value = node.first('value');
      propsEncountered++;

      if (prop.first().is('ident')) {
        if (value.contains('block')) {
          propList = propList.concat(
            buildPartialProperty(value.first('block'),
              {
                name: currentProperty.name + PROP_DIVIDER + prop.first('ident').content
              },
              propsEncountered
            )
          );
        }
        else {
          propList.push({
            name: currentProperty.name + PROP_DIVIDER + prop.first('ident').content,
            line: prop.first().start.line,
            col: prop.first().start.column,
            propsEncountered: propsEncountered
          });
        }
      }
    });
  }
  return propList;
};

module.exports = {
  'name': 'no-misspelled-properties',
  'defaults': {
    'extra-properties': []
  },
  'detect': function (ast, parser) {
    var result = [];
    var toSkip = 0;
    var propertyList = getCombinedList(properties, parser.options['extra-properties']);

    ast.traverseByType('declaration', function (node) {
      var prop = node.first('property');
      var containsInterp = prop.contains('interpolation');
      if (toSkip) {
        toSkip--;
        if (toSkip) {
          return false;
        }
      }
      if (!prop.first() || !prop.first().is('ident')) {
        return false;
      }
      var curProperty = prop.first() && prop.first().is('ident') && prop.first('ident').content;
      var value = node.first('value');
      var fullProperties = [];

      if (value.contains('block')) {
        fullProperties = buildPartialProperty(
          value.first('block'),
          {
            name: curProperty,
            line: prop.first('ident').start.line,
            col: prop.first('ident').start.column
          },
          0
        );
      }

      if (fullProperties.length) {
        fullProperties.forEach(function (constrProp) {
          toSkip += constrProp.propsEncountered;
          if (propertyList.indexOf(constrProp.name) === -1) {
            result = helpers.addUnique(result, {
              'ruleId': parser.rule.name,
              'line': constrProp.line,
              'column': constrProp.col,
              'message': 'Property `' + constrProp.name + '` appears to be spelled incorrectly',
              'severity': parser.severity
            });
          }
        });
      }
      else {
        if (curProperty.length > 0) {
          if (containsInterp) {
            if (!helpers.isPartialStringMatch(curProperty, propertyList)) {
              result = helpers.addUnique(result, {
                'ruleId': parser.rule.name,
                'line': node.start.line,
                'column': node.start.column,
                'message': 'Property `' + curProperty + '` appears to be spelled incorrectly',
                'severity': parser.severity
              });
            }
          }
          else if (propertyList.indexOf(curProperty) === -1) {
            result = helpers.addUnique(result, {
              'ruleId': parser.rule.name,
              'line': node.start.line,
              'column': node.start.column,
              'message': 'Property `' + curProperty + '` appears to be spelled incorrectly',
              'severity': parser.severity
            });
          }
        }
      }
      return false;
    });
    return result;
  }
};

@@ -123,16 +123,17 @@
  = '-';%0A
+%0A
 /**%0A * C
@@ -464,16 +464,461 @@
 s);%0A%7D;%0A%0A
+/**%0A * Recursive function to build up an array of property names when encountering multiline properties%0A *%0A * @param %7BObject%7D valBlock - The current block node from within our value%0A * @param %7BObject%7D currentProperty - The current base property name i.e. border-%0A * @param %7BNumber%7D propsCounted - The number of properties encountered in our multiline so far%0A * @returns %7BArray%7D Array of objects containing our property and line/col info etc%0A */%0A
 var buil
@@ -2376,103 +2376,227 @@
     
-if (toSkip) %7B%0A        toSkip--;%0A        if (toSkip) %7B%0A          ret
+// If we've already checked declarations in a multiline we can skip those decs here%0A      if (toSkip) %7B%0A        toSkip--;%0A        return !toSkip;%0A      %7D%0A      // make sure o
 ur
-n
  f
-alse;%0A        %7D%0A      %7D
+irst node within our property is an ident
 %0A   
@@ -2674,24 +2674,25 @@
 se;%0A      %7D%0A
+%0A
       var cu
@@ -2876,32 +2876,116 @@
 ins('block')) %7B%0A
+        // encountered a multiline property, we should build the property list here%0A
         fullProp
@@ -3230,24 +3230,64 @@
  );%0A      %7D%0A
+      // If we have multiline properties
 %0A      if (f
@@ -3379,46 +3379,201 @@
     
-toSkip += constrProp.propsEncountered;
+// Add the number of propertiy declarations we've already checked here so we can skip them%0A          toSkip += constrProp.propsEncountered;%0A          // Check if the property exists in our list
 %0A   
@@ -4035,24 +4035,217 @@
 ngth %3E 0) %7B%0A
+          /*%0A           * If our property name contains interpolation we need to make a best guess by using a%0A           * partial string match as we can't be 100%25 on the context%0A           */%0A
           if
@@ -4696,32 +4696,115 @@
   %7D%0A          %7D%0A
+          // Otherwise it's just a normal string property name, lets check it here%0A
           else i
@@ -5228,24 +5228,25 @@
 se;%0A    %7D);%0A
+%0A
     return r

update comments