text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
  
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  
  var _utils = require('../utils');
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  /**
   * Regular rules.
   *
   * @api public
   */
  
  var Rule = function () {
    function Rule(selector, style, options) {
      _classCallCheck(this, Rule);
  
      this.id = _utils.uid.get();
      this.type = 'regular';
      this.options = options;
      this.selectorText = selector || '';
      this.className = options.className || '';
      this.originalStyle = style;
      // We expect style to be plain object.
      this.style = (0, _utils.clone)(style);
      if (options.named) {
        this.name = selector;
        if (!this.className) {
          this.className = this.name ? this.name + '--' + this.id : this.id;
        }
        this.selectorText = '.' + this.className;
      }
    }
  
    /**
     * Set selector string.
     * Attenition: use this with caution. Most browser didn't implement selector
     * text setter, so this will result in rerendering of entire style sheet.
     *
     * @param {String} selector
     * @api public
     */
  
  
    _createClass(Rule, [{
      key: 'prop',
  
  
      /**
       * Get or set a style property.
       *
       * @param {String} name
       * @param {String|Number} [value]
       * @return {Rule|String|Number}
       * @api public
       */
      value: function prop(name, value) {
        var style = this.options.Renderer.style;
        // Its a setter.
  
        if (value != null) {
          this.style[name] = value;
          // Only defined if option linked is true.
          if (this.renderable) style(this.renderable, name, value);
          return this;
        }
        // Its a getter, read the value from the DOM if its not cached.
        if (this.renderable && this.style[name] == null) {
          // Cache the value after we have got it from the DOM once.
          this.style[name] = style(this.renderable, name);
        }
        return this.style[name];
      }
  
      /**
       * Apply rule to an element inline.
       *
       * @param {Element} renderable
       * @return {Rule}
       * @api public
       */
  
    }, {
      key: 'applyTo',
      value: function applyTo(renderable) {
        for (var prop in this.style) {
          var value = this.style[prop];
          var style = this.options.Renderer.style;
  
          if (Array.isArray(value)) {
            for (var index = 0; index < value.length; index++) {
              style(renderable, prop, value[index]);
            }
          } else style(renderable, prop, value);
        }
        return this;
      }
  
      /**
       * Returns JSON representation of the rule.
       * Array of values is not supported.
       *
       * @return {Object}
       * @api public
       */
  
    }, {
      key: 'toJSON',
      value: function toJSON() {
        var style = Object.create(null);
        for (var prop in this.style) {
          if (_typeof(this.style[prop]) != 'object') {
            style[prop] = this.style[prop];
          }
        }
        return style;
      }
  
      /**
       * Generates a CSS string.
       *
       * @see toCSS
       * @api public
       */
  
    }, {
      key: 'toString',
      value: function toString(options) {
        return (0, _utils.toCSS)(this.selector, this.style, options);
      }
    }, {
      key: 'selector',
      set: function set() {
        var selector = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0];
        var _options = this.options;
        var Renderer = _options.Renderer;
        var sheet = _options.sheet;
  
        // After we modify selector, ref by old selector needs to be removed.
  
        if (sheet) sheet.unregisterRule(this);
  
        this.selectorText = selector;
        this.className = (0, _utils.findClassNames)(selector);
  
        if (!this.renderable) {
          // Register the rule with new selector.
          if (sheet) sheet.registerRule(this);
          return;
        }
  
        var changed = Renderer.setSelector(this.renderable, selector);
  
        if (changed) {
          sheet.registerRule(this);
          return;
        }
  
        // If selector setter is not implemented, rerender the sheet.
        // We need to delete renderable from the rule, because when sheet.deploy()
        // calls rule.toString, it will get the old selector.
        delete this.renderable;
        sheet.registerRule(this).deploy().link();
      }
  
      /**
       * Get selector string.
       *
       * @return {String}
       * @api public
       */
      ,
      get: function get() {
        if (this.renderable) {
          return this.options.Renderer.getSelector(this.renderable);
        }
  
        return this.selectorText;
      }
    }]);
  
    return Rule;
  }();
  
  exports.default = Rule;