var $ = function (selector, context) {
  return new $.fn.init(selector, context);
};
$.fn = $.prototype;
$.fn.init = function (selector, context) {
  var nodeList = [];
  if (typeof selector == 'string') {
    nodeList = (context || document).querySelectorAll(selector);
  } else if (selector instanceof Node) {
    nodeList[0] = selector;
  } else if (selector instanceof NodeList || selector instanceof Array) {
    nodeList = selector;
  }
  this.length = nodeList.length;
  for (var i = 0; i < this.length; i += 1) {
    this[i] = nodeList[i];
  }
  return this;
};
$.fn.init.prototype = $.fn;
$.fn.each = function (cb_fun, need_ret) {
  var res = [];
  for (var i = 0; i < this.length; i++) {
    res[i] = cb_fun.call(this[i]);
  }
  if (need_ret) {
    if (res.length == 1) {
      res = res[0];
    }
    return res;
  }
  return this;
};
$.fn.eq = function () {
  var nodeList = [];
  for (var i = 0; i < arguments.length; i++) {
    nodeList[i] = this[arguments[i]];
  }
  return $s(nodeList);
};
$.fn.first = function () {
  return this.eq(0);
};
$.fn.last = function () {
  return this.eq(this.length - 1);
};
$.fn.find = function (str) {
  var nodeList = [];
  var res = this.each(function () {
    return this.querySelectorAll(str);
  }, 1);
  if (res instanceof Array) {
    for (var i = 0; i < res.length; i++) {
      for (var j = 0; j < res[i].length; j++) {
        nodeList.push(res[i][j]);
      }
    }
  } else {
    nodeList = res;
  }
  return $s(nodeList);
};
$.fn.parent = function () {
  return $s(
    this.each(function () {
      return this.parentNode;
    }, 1)
  );
};
$.fn.hide = function () {
  return this.each(function () {
    this.style.display = 'none';
  });
};
$.fn.show = function () {
  return this.each(function () {
    this.style.display = 'block';
  });
};
$.fn.text = function (str) {
  if (str != undefined) {
    return this.each(function () {
      this.innerText = str;
    });
  } else {
    return this.each(function () {
      return this.innerText;
    }, 1);
  }
};
$.fn.html = function (str) {
  if (str != undefined) {
    return this.each(function () {
      this.innerHTML = str;
    });
  } else {
    return this.each(function () {
      return this.innerHTML;
    }, 1);
  }
};
$.fn.outHtml = function (str) {
  if (str != undefined) {
    return this.each(function () {
      this.outerHTML = str;
    });
  } else {
    return this.each(function () {
      return this.outerHTML;
    }, 1);
  }
};
$.fn.val = function (str) {
  if (str != undefined) {
    return this.each(function () {
      this.value = str;
    });
  } else {
    return this.each(function () {
      return this.value;
    }, 1);
  }
};
$.fn.css = function (key, value, important) {
  if (value != undefined) {
    return this.each(function () {
      this.style.setProperty(key, value, important);
    });
  } else {
    return this.each(function () {
      return this.style.getPropertyValue(key);
    }, 1);
  }
};
$.fn.attr = function (key, value) {
  if (value != undefined) {
    return this.each(function () {
      this.setAttribute(key, value);
    });
  } else {
    return this.each(function () {
      return this.getAttribute(key);
    }, 1);
  }
};
$.fn.removeAttr = function (key) {
  return this.each(function () {
    this.removeAttribute(key);
  });
};
$.fn.remove = function () {
  return this.each(function () {
    this.remove();
  });
};
$.fn.append = function (str) {
  return this.each(function () {
    this.insertAdjacentHTML('beforeend', str);
  });
};
$.fn.prepend = function (str) {
  return this.each(function () {
    this.insertAdjacentHTML('afterbegin', str);
  });
};
$.fn.hasClass = function (str) {
  return this.each(function () {
    return this.classList.contains(str);
  }, 1);
};
$.fn.addClass = function (str) {
  return this.each(function () {
    return this.classList.add(str);
  });
};
$.fn.removeClass = function (str) {
  return this.each(function () {
    return this.classList.remove(str);
  });
};

$.fn.on = function (type, fn) {
  return this.each(function (i, v) {
    window.addEventListener
      ? this.addEventListener(type, fn)
      : this.attachEvent('on' + type, fn);
  });
};

module.exports = $;
