var domEach = require('../utils').domEach,

_ = {
  pick: require('lodash.pick'),
};

var toString = Object.prototype.toString;

/**

* Set / Get css.
*
* @param {String|Object} prop
* @param {String} val
* @return {self}
* @api public
*/

exports.css = function(prop, val) {

if (arguments.length === 2 ||
  // When `prop` is a "plain" object
  (toString.call(prop) === '[object Object]')) {
  return domEach(this, function(idx, el) {
    setCss(el, prop, val, idx);
  });
} else {
  return getCss(this[0], prop);
}

};

/**

* Set styles of all elements.
*
* @param {String|Object} prop
* @param {String} val
* @param {Number} idx - optional index within the selection
* @return {self}
* @api private
*/

function setCss(el, prop, val, idx) {

if ('string' == typeof prop) {
  var styles = getCss(el);
  if (typeof val === 'function') {
    val = val.call(el, idx, styles[prop]);
  }

  if (val === '') {
    delete styles[prop];
  } else if (val != null) {
    styles[prop] = val;
  }

  el.attribs.style = stringify(styles);
} else if ('object' == typeof prop) {
  Object.keys(prop).forEach(function(k){
    setCss(el, k, prop[k]);
  });
}

}

/**

* Get parsed styles of the first element.
*
* @param {String} prop
* @return {Object}
* @api private
*/

function getCss(el, prop) {

var styles = parse(el.attribs.style);
if (typeof prop === 'string') {
  return styles[prop];
} else if (Array.isArray(prop)) {
  return _.pick(styles, prop);
} else {
  return styles;
}

}

/**

* Stringify `obj` to styles.
*
* @param {Object} obj
* @return {Object}
* @api private
*/

function stringify(obj) {

return Object.keys(obj || {})
  .reduce(function(str, prop){
    return str += ''
      + (str ? ' ' : '')
      + prop
      + ': '
      + obj[prop]
      + ';';
  }, '');

}

/**

* Parse `styles`.
*
* @param {String} styles
* @return {Object}
* @api private
*/

function parse(styles) {

styles = (styles || '').trim();

if (!styles) return {};

return styles
  .split(';')
  .reduce(function(obj, str){
    var n = str.indexOf(':');
    // skip if there is no :, or if it is the first/last character
    if (n < 1 || n === str.length-1) return obj;
    obj[str.slice(0,n).trim()] = str.slice(n+1).trim();
    return obj;
  }, {});

}