(function () {
  "use strict";

  function escapeCss(value) {
    if (window.CSS && typeof window.CSS.escape === "function") {
      return window.CSS.escape(value);
    }
    return String(value).replace(/[^a-zA-Z0-9_-]/g, "\\$&");
  }

  function queryCount(selector) {
    try {
      return document.querySelectorAll(selector).length;
    } catch (error) {
      return 0;
    }
  }

  function byId(el) {
    if (!el || !el.id) {
      return null;
    }
    var selector = "#" + escapeCss(el.id);
    return queryCount(selector) === 1 ? selector : null;
  }

  function byData(el) {
    if (!el || !el.attributes) {
      return null;
    }
    for (var i = 0; i < el.attributes.length; i++) {
      var attr = el.attributes[i];
      if (!attr || !attr.name || attr.name.indexOf("data-") !== 0 || !attr.value) {
        continue;
      }
      var selector = "[" + escapeCss(attr.name) + '="' + escapeCss(attr.value) + '"]';
      if (queryCount(selector) === 1) {
        return selector;
      }
    }
    return null;
  }

  function byUniqueClass(el) {
    if (!el || !el.classList || !el.classList.length) {
      return null;
    }

    var classes = Array.prototype.slice.call(el.classList).filter(function (className) {
      return className && className.indexOf("polanger-") !== 0 && className.indexOf("is-") !== 0 && className.indexOf("has-") !== 0;
    });

    for (var i = 0; i < classes.length; i++) {
      var selector = "." + escapeCss(classes[i]);
      if (queryCount(selector) === 1) {
        return selector;
      }
    }

    if (classes.length > 1) {
      var combo = "." + escapeCss(classes[0]) + "." + escapeCss(classes[1]);
      if (queryCount(combo) === 1) {
        return combo;
      }
    }

    return null;
  }

  function simplePart(el) {
    if (!el || !el.tagName) {
      return "";
    }

    if (el.id) {
      return "#" + escapeCss(el.id);
    }

    var tag = el.tagName.toLowerCase();
    var classList = el.classList ? Array.prototype.slice.call(el.classList) : [];
    classList = classList.filter(function (className) {
      return className && className.indexOf("polanger-") !== 0;
    }).slice(0, 2);

    if (!classList.length) {
      return tag;
    }

    return tag + classList.map(function (className) {
      return "." + escapeCss(className);
    }).join("");
  }

  function byParentPath(el) {
    var parts = [];
    var current = el;

    while (current && current !== document.body) {
      var part = simplePart(current);
      if (!part) {
        break;
      }
      parts.unshift(part);
      var selector = parts.join(" > ");
      if (queryCount(selector) === 1) {
        return selector;
      }
      current = current.parentElement;
    }

    return null;
  }

  function byNthPath(el) {
    var current = el;
    var parts = [];

    while (current && current !== document.body) {
      if (!current.tagName) {
        break;
      }

      var tag = current.tagName.toLowerCase();
      var index = 1;
      var sibling = current;
      while ((sibling = sibling.previousElementSibling)) {
        if (sibling.tagName && sibling.tagName.toLowerCase() === tag) {
          index++;
        }
      }
      parts.unshift(tag + ":nth-of-type(" + index + ")");
      current = current.parentElement;
    }

    return "body > " + parts.join(" > ");
  }

  window.PolangerShieldSelector = {
    generate: function (el) {
      var idSelector = byId(el);
      if (idSelector) {
        return { selector: idSelector, strength: 100, method: "id" };
      }

      var dataSelector = byData(el);
      if (dataSelector) {
        return { selector: dataSelector, strength: 90, method: "data" };
      }

      var classSelector = byUniqueClass(el);
      if (classSelector) {
        return { selector: classSelector, strength: 75, method: "class" };
      }

      var parentSelector = byParentPath(el);
      if (parentSelector) {
        return { selector: parentSelector, strength: 55, method: "parent_path" };
      }

      return { selector: byNthPath(el), strength: 30, method: "nth_path" };
    }
  };
})();
