/**
* jQuery asGradient v0.3.3
* https://github.com/amazingSurge/jquery-asGradient
*
* Copyright (c) amazingSurge
* Released under the LGPL-3.0 license
*/
(function(global, factory) {
  if (typeof define === 'function' && define.amd) {
    define('AsGradient', ['exports', 'jquery', 'jquery-asColor'], factory);
  } else if (typeof exports !== 'undefined') {
    factory(exports, require('jquery'), require('jquery-asColor'));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.jQuery, global.AsColor);
    global.AsGradient = mod.exports;
  }
})(this, function(exports, _jquery, _jqueryAsColor) {
  'use strict';

  Object.defineProperty(exports, '__esModule', {
    value: true
  });

  var _jquery2 = _interopRequireDefault(_jquery);

  var _jqueryAsColor2 = _interopRequireDefault(_jqueryAsColor);

  function _interopRequireDefault(obj) {
    return obj && obj.__esModule
      ? obj
      : {
          default: obj
        };
  }

  var _typeof =
    typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol'
      ? function(obj) {
          return typeof obj;
        }
      : function(obj) {
          return obj &&
          typeof Symbol === 'function' &&
          obj.constructor === Symbol &&
          obj !== Symbol.prototype
            ? 'symbol'
            : typeof obj;
        };

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError('Cannot call a class as a function');
    }
  }

  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 DEFAULTS = {
    prefixes: ['-webkit-', '-moz-', '-ms-', '-o-'],
    forceStandard: true,
    angleUseKeyword: true,
    emptyString: '',
    degradationFormat: false,
    cleanPosition: true,
    color: {
      format: false, // rgb, rgba, hsl, hsla, hex
      hexUseName: false,
      reduceAlpha: true,
      shortenHex: true,
      zeroAlphaAsTransparent: false,
      invalidValue: {
        r: 0,
        g: 0,
        b: 0,
        a: 1
      }
    }
  };

  /* eslint no-extend-native: "off" */
  if (!String.prototype.includes) {
    String.prototype.includes = function(search, start) {
      'use strict';

      if (typeof start !== 'number') {
        start = 0;
      }

      if (start + search.length > this.length) {
        return false;
      }
      return this.indexOf(search, start) !== -1;
    };
  }

  function getPrefix() {
    var ua = window.navigator.userAgent;
    var prefix = '';
    if (/MSIE/g.test(ua)) {
      prefix = '-ms-';
    } else if (/Firefox/g.test(ua)) {
      prefix = '-moz-';
    } else if (/(WebKit)/i.test(ua)) {
      prefix = '-webkit-';
    } else if (/Opera/g.test(ua)) {
      prefix = '-o-';
    }
    return prefix;
  }

  function flip(o) {
    var flipped = {};
    for (var i in o) {
      if (o.hasOwnProperty(i)) {
        flipped[o[i]] = i;
      }
    }
    return flipped;
  }

  function reverseDirection(direction) {
    var mapping = {
      top: 'bottom',
      right: 'left',
      bottom: 'top',
      left: 'right',
      'right top': 'left bottom',
      'top right': 'bottom left',
      'bottom right': 'top left',
      'right bottom': 'left top',
      'left bottom': 'right top',
      'bottom left': 'top right',
      'top left': 'bottom right',
      'left top': 'right bottom'
    };
    return mapping.hasOwnProperty(direction) ? mapping[direction] : direction;
  }

  function isDirection(n) {
    var reg = /^(top|left|right|bottom)$/i;
    return reg.test(n);
  }

  var keywordAngleMap = {
    'to top': 0,
    'to right': 90,
    'to bottom': 180,
    'to left': 270,
    'to right top': 45,
    'to top right': 45,
    'to bottom right': 135,
    'to right bottom': 135,
    'to left bottom': 225,
    'to bottom left': 225,
    'to top left': 315,
    'to left top': 315
  };

  var angleKeywordMap = flip(keywordAngleMap);

  var RegExpStrings = (function() {
    var color = /(?:rgba|rgb|hsla|hsl)\s*\([\s\d\.,%]+\)|#[a-z0-9]{3,6}|[a-z]+/i;
    var position = /\d{1,3}%/i;
    var angle = /(?:to ){0,1}(?:(?:top|left|right|bottom)\s*){1,2}|\d+deg/i;
    var stop = new RegExp(
      '(' + color.source + ')\\s*(' + position.source + '){0,1}',
      'i'
    );
    var stops = new RegExp(stop.source, 'gi');
    var parameters = new RegExp(
      '(?:(' + angle.source + ')){0,1}\\s*,{0,1}\\s*(.*?)\\s*',
      'i'
    );
    var full = new RegExp(
      '^(-webkit-|-moz-|-ms-|-o-){0,1}(linear|radial|repeating-linear)-gradient\\s*\\(\\s*(' +
        parameters.source +
        ')\\s*\\)$',
      'i'
    );

    return {
      FULL: full,
      ANGLE: angle,
      COLOR: color,
      POSITION: position,
      STOP: stop,
      STOPS: stops,
      PARAMETERS: new RegExp('^' + parameters.source + '$', 'i')
    };
  })();

  var GradientString = {
    matchString: function matchString(string) {
      var matched = this.parseString(string);
      if (
        matched &&
        matched.value &&
        matched.value.stops &&
        matched.value.stops.length > 1
      ) {
        return true;
      }
      return false;
    },

    parseString: function parseString(string) {
      string = _jquery2.default.trim(string);
      var matched = void 0;
      if ((matched = RegExpStrings.FULL.exec(string)) !== null) {
        var value = this.parseParameters(matched[3]);

        return {
          prefix: typeof matched[1] === 'undefined' ? null : matched[1],
          type: matched[2],
          value: value
        };
      } else {
        return false;
      }
    },

    parseParameters: function parseParameters(string) {
      var matched = void 0;
      if ((matched = RegExpStrings.PARAMETERS.exec(string)) !== null) {
        var stops = this.parseStops(matched[2]);
        return {
          angle: typeof matched[1] === 'undefined' ? 0 : matched[1],
          stops: stops
        };
      } else {
        return false;
      }
    },

    parseStops: function parseStops(string) {
      var _this = this;

      var matched = void 0;
      var result = [];
      if ((matched = string.match(RegExpStrings.STOPS)) !== null) {
        _jquery2.default.each(matched, function(i, item) {
          var stop = _this.parseStop(item);
          if (stop) {
            result.push(stop);
          }
        });
        return result;
      } else {
        return false;
      }
    },

    formatStops: function formatStops(stops, cleanPosition) {
      var stop = void 0;
      var output = [];
      var positions = [];
      var colors = [];
      var position = void 0;

      for (var i = 0; i < stops.length; i++) {
        stop = stops[i];
        if (typeof stop.position === 'undefined' || stop.position === null) {
          if (i === 0) {
            position = 0;
          } else if (i === stops.length - 1) {
            position = 1;
          } else {
            position = undefined;
          }
        } else {
          position = stop.position;
        }
        positions.push(position);
        colors.push(stop.color.toString());
      }

      positions = (function(data) {
        var start = null;
        var average = void 0;
        for (var _i = 0; _i < data.length; _i++) {
          if (isNaN(data[_i])) {
            if (start === null) {
              start = _i;
              continue;
            }
          } else if (start) {
            average = (data[_i] - data[start - 1]) / (_i - start + 1);
            for (var j = start; j < _i; j++) {
              data[j] = data[start - 1] + (j - start + 1) * average;
            }
            start = null;
          }
        }

        return data;
      })(positions);

      for (var x = 0; x < stops.length; x++) {
        if (
          cleanPosition &&
          ((x === 0 && positions[x] === 0) ||
            (x === stops.length - 1 && positions[x] === 1))
        ) {
          position = '';
        } else {
          position = ' ' + this.formatPosition(positions[x]);
        }

        output.push(colors[x] + position);
      }
      return output.join(', ');
    },

    parseStop: function parseStop(string) {
      var matched = void 0;
      if ((matched = RegExpStrings.STOP.exec(string)) !== null) {
        var position = this.parsePosition(matched[2]);

        return {
          color: matched[1],
          position: position
        };
      } else {
        return false;
      }
    },

    parsePosition: function parsePosition(string) {
      if (typeof string === 'string' && string.substr(-1) === '%') {
        string = parseFloat(string.slice(0, -1) / 100);
      }

      if (typeof string !== 'undefined' && string !== null) {
        return parseFloat(string, 10);
      } else {
        return null;
      }
    },

    formatPosition: function formatPosition(value) {
      return parseInt(value * 100, 10) + '%';
    },

    parseAngle: function parseAngle(string, notStandard) {
      if (typeof string === 'string' && string.includes('deg')) {
        string = string.replace('deg', '');
      }
      if (!isNaN(string)) {
        if (notStandard) {
          string = this.fixOldAngle(string);
        }
      }
      if (typeof string === 'string') {
        var directions = string.split(' ');

        var filtered = [];
        for (var i in directions) {
          if (isDirection(directions[i])) {
            filtered.push(directions[i].toLowerCase());
          }
        }
        var keyword = filtered.join(' ');

        if (!string.includes('to ')) {
          keyword = reverseDirection(keyword);
        }
        keyword = 'to ' + keyword;
        if (keywordAngleMap.hasOwnProperty(keyword)) {
          string = keywordAngleMap[keyword];
        }
      }
      var value = parseFloat(string, 10);

      if (value > 360) {
        value %= 360;
      } else if (value < 0) {
        value %= -360;

        if (value !== 0) {
          value += 360;
        }
      }
      return value;
    },

    fixOldAngle: function fixOldAngle(value) {
      value = parseFloat(value);
      value = Math.abs(450 - value) % 360;
      value = parseFloat(value.toFixed(3));
      return value;
    },

    formatAngle: function formatAngle(value, notStandard, useKeyword) {
      value = parseInt(value, 10);
      if (useKeyword && angleKeywordMap.hasOwnProperty(value)) {
        value = angleKeywordMap[value];
        if (notStandard) {
          value = reverseDirection(value.substr(3));
        }
      } else {
        if (notStandard) {
          value = this.fixOldAngle(value);
        }
        value = value + 'deg';
      }

      return value;
    }
  };

  var ColorStop = (function() {
    function ColorStop(color, position, gradient) {
      _classCallCheck(this, ColorStop);

      this.color = (0, _jqueryAsColor2.default)(color, gradient.options.color);
      this.position = GradientString.parsePosition(position);
      this.id = ++gradient._stopIdCount;
      this.gradient = gradient;
    }

    _createClass(ColorStop, [
      {
        key: 'setPosition',
        value: function setPosition(string) {
          var position = GradientString.parsePosition(string);
          if (this.position !== position) {
            this.position = position;
            this.gradient.reorder();
          }
        }
      },
      {
        key: 'setColor',
        value: function setColor(string) {
          this.color.fromString(string);
        }
      },
      {
        key: 'remove',
        value: function remove() {
          this.gradient.removeById(this.id);
        }
      }
    ]);

    return ColorStop;
  })();

  var GradientTypes = {
    LINEAR: {
      parse: function parse(result) {
        return {
          r:
            result[1].substr(-1) === '%'
              ? parseInt(result[1].slice(0, -1) * 2.55, 10)
              : parseInt(result[1], 10),
          g:
            result[2].substr(-1) === '%'
              ? parseInt(result[2].slice(0, -1) * 2.55, 10)
              : parseInt(result[2], 10),
          b:
            result[3].substr(-1) === '%'
              ? parseInt(result[3].slice(0, -1) * 2.55, 10)
              : parseInt(result[3], 10),
          a: 1
        };
      },
      to: function to(gradient, instance, prefix) {
        if (gradient.stops.length === 0) {
          return instance.options.emptyString;
        }
        if (gradient.stops.length === 1) {
          return gradient.stops[0].color.to(instance.options.degradationFormat);
        }

        var standard = instance.options.forceStandard;
        var _prefix = instance._prefix;

        if (!_prefix) {
          standard = true;
        }
        if (
          prefix &&
          -1 !== _jquery2.default.inArray(prefix, instance.options.prefixes)
        ) {
          standard = false;
          _prefix = prefix;
        }

        var angle = GradientString.formatAngle(
          gradient.angle,
          !standard,
          instance.options.angleUseKeyword
        );
        var stops = GradientString.formatStops(
          gradient.stops,
          instance.options.cleanPosition
        );

        var output = 'linear-gradient(' + angle + ', ' + stops + ')';
        if (standard) {
          return output;
        } else {
          return _prefix + output;
        }
      }
    }
  };

  var AsGradient = (function() {
    function AsGradient(string, options) {
      _classCallCheck(this, AsGradient);

      if (
        (typeof string === 'undefined' ? 'undefined' : _typeof(string)) ===
          'object' &&
        typeof options === 'undefined'
      ) {
        options = string;
        string = undefined;
      }
      this.value = {
        angle: 0,
        stops: []
      };
      this.options = _jquery2.default.extend(true, {}, DEFAULTS, options);

      this._type = 'LINEAR';
      this._prefix = null;
      this.length = this.value.stops.length;
      this.current = 0;
      this._stopIdCount = 0;

      this.init(string);
    }

    _createClass(
      AsGradient,
      [
        {
          key: 'init',
          value: function init(string) {
            if (string) {
              this.fromString(string);
            }
          }
        },
        {
          key: 'val',
          value: function val(value) {
            if (typeof value === 'undefined') {
              return this.toString();
            } else {
              this.fromString(value);
              return this;
            }
          }
        },
        {
          key: 'angle',
          value: function angle(value) {
            if (typeof value === 'undefined') {
              return this.value.angle;
            } else {
              this.value.angle = GradientString.parseAngle(value);
              return this;
            }
          }
        },
        {
          key: 'append',
          value: function append(color, position) {
            return this.insert(color, position, this.length);
          }
        },
        {
          key: 'reorder',
          value: function reorder() {
            if (this.length < 2) {
              return;
            }

            this.value.stops = this.value.stops.sort(function(a, b) {
              return a.position - b.position;
            });
          }
        },
        {
          key: 'insert',
          value: function insert(color, position, index) {
            if (typeof index === 'undefined') {
              index = this.current;
            }

            var stop = new ColorStop(color, position, this);

            this.value.stops.splice(index, 0, stop);

            this.length = this.length + 1;
            this.current = index;
            return stop;
          }
        },
        {
          key: 'getById',
          value: function getById(id) {
            if (this.length > 0) {
              for (var i in this.value.stops) {
                if (id === this.value.stops[i].id) {
                  return this.value.stops[i];
                }
              }
            }
            return false;
          }
        },
        {
          key: 'removeById',
          value: function removeById(id) {
            var index = this.getIndexById(id);
            if (index) {
              this.remove(index);
            }
          }
        },
        {
          key: 'getIndexById',
          value: function getIndexById(id) {
            var index = 0;
            for (var i in this.value.stops) {
              if (id === this.value.stops[i].id) {
                return index;
              }
              index++;
            }
            return false;
          }
        },
        {
          key: 'getCurrent',
          value: function getCurrent() {
            return this.value.stops[this.current];
          }
        },
        {
          key: 'setCurrentById',
          value: function setCurrentById(id) {
            var index = 0;
            for (var i in this.value.stops) {
              if (this.value.stops[i].id !== id) {
                index++;
              } else {
                this.current = index;
              }
            }
          }
        },
        {
          key: 'get',
          value: function get(index) {
            if (typeof index === 'undefined') {
              index = this.current;
            }
            if (index >= 0 && index < this.length) {
              this.current = index;
              return this.value.stops[index];
            } else {
              return false;
            }
          }
        },
        {
          key: 'remove',
          value: function remove(index) {
            if (typeof index === 'undefined') {
              index = this.current;
            }
            if (index >= 0 && index < this.length) {
              this.value.stops.splice(index, 1);
              this.length = this.length - 1;
              this.current = index - 1;
            }
          }
        },
        {
          key: 'empty',
          value: function empty() {
            this.value.stops = [];
            this.length = 0;
            this.current = 0;
          }
        },
        {
          key: 'reset',
          value: function reset() {
            this.value._angle = 0;
            this.empty();
            this._prefix = null;
            this._type = 'LINEAR';
          }
        },
        {
          key: 'type',
          value: function type(_type) {
            if (
              typeof _type === 'string' &&
              (_type = _type.toUpperCase()) &&
              typeof GradientTypes[_type] !== 'undefined'
            ) {
              this._type = _type;
              return this;
            } else {
              return this._type;
            }
          }
        },
        {
          key: 'fromString',
          value: function fromString(string) {
            var _this2 = this;

            this.reset();

            var result = GradientString.parseString(string);

            if (result) {
              this._prefix = result.prefix;
              this.type(result.type);
              if (result.value) {
                this.value.angle = GradientString.parseAngle(
                  result.value.angle,
                  this._prefix !== null
                );

                _jquery2.default.each(result.value.stops, function(i, stop) {
                  _this2.append(stop.color, stop.position);
                });
              }
            }
          }
        },
        {
          key: 'toString',
          value: function toString(prefix) {
            if (prefix === true) {
              prefix = getPrefix();
            }
            return GradientTypes[this.type()].to(this.value, this, prefix);
          }
        },
        {
          key: 'matchString',
          value: function matchString(string) {
            return GradientString.matchString(string);
          }
        },
        {
          key: 'toStringWithAngle',
          value: function toStringWithAngle(angle, prefix) {
            var value = _jquery2.default.extend(true, {}, this.value);
            value.angle = GradientString.parseAngle(angle);

            if (prefix === true) {
              prefix = getPrefix();
            }

            return GradientTypes[this.type()].to(value, this, prefix);
          }
        },
        {
          key: 'getPrefixedStrings',
          value: function getPrefixedStrings() {
            var strings = [];
            for (var i in this.options.prefixes) {
              if (Object.hasOwnProperty.call(this.options.prefixes, i)) {
                strings.push(this.toString(this.options.prefixes[i]));
              }
            }
            return strings;
          }
        }
      ],
      [
        {
          key: 'setDefaults',
          value: function setDefaults(options) {
            _jquery2.default.extend(
              true,
              DEFAULTS,
              _jquery2.default.isPlainObject(options) && options
            );
          }
        }
      ]
    );

    return AsGradient;
  })();

  var info = {
    version: '0.3.3'
  };

  var OtherAsGradient = _jquery2.default.asGradient;

  var jQueryAsGradient = function jQueryAsGradient() {
    for (
      var _len = arguments.length, args = Array(_len), _key = 0;
      _key < _len;
      _key++
    ) {
      args[_key] = arguments[_key];
    }

    return new (Function.prototype.bind.apply(
      AsGradient,
      [null].concat(args)
    ))();
  };

  _jquery2.default.asGradient = jQueryAsGradient;
  _jquery2.default.asGradient.Constructor = AsGradient;

  _jquery2.default.extend(
    _jquery2.default.asGradient,
    {
      setDefaults: AsGradient.setDefaults,
      noConflict: function noConflict() {
        _jquery2.default.asGradient = OtherAsGradient;
        return jQueryAsGradient;
      }
    },
    GradientString,
    info
  );

  var main = _jquery2.default.asGradient;

  exports.default = main;
});
