'use strict';

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

var cookie = require('cookie');

/*
 * Copyright (c) 2021.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */
exports.Driver = void 0;

(function (Driver) {
  Driver["LOCAL_STORAGE"] = "localStorage";
  Driver["SESSION_STORAGE"] = "sessionStorage";
  Driver["COOKIE"] = "cookie";
})(exports.Driver || (exports.Driver = {}));

function ownKeys(object, enumerableOnly) {
  var keys = Object.keys(object);

  if (Object.getOwnPropertySymbols) {
    var symbols = Object.getOwnPropertySymbols(object);
    enumerableOnly && (symbols = symbols.filter(function (sym) {
      return Object.getOwnPropertyDescriptor(object, sym).enumerable;
    })), keys.push.apply(keys, symbols);
  }

  return keys;
}

function _objectSpread2(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = null != arguments[i] ? arguments[i] : {};
    i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
      _defineProperty(target, key, source[key]);
    }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
      Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
    });
  }

  return target;
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a 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);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, "prototype", {
    writable: false
  });
  return Constructor;
}

function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }

  return obj;
}

/*
 * Copyright (c) 2021-2021.
 * Author Peter Placzek (tada5hi)
 * For the full copyright and license information,
 * view the LICENSE file that was distributed with this source code.
 */
var isUnset = function isUnset(o) {
  return typeof o === 'undefined' || o === null;
};
var isSet = function isSet(o) {
  return !isUnset(o);
};
function encodeValue(val) {
  if (typeof val === 'string') {
    return val;
  }

  return JSON.stringify(val);
}
function decodeValue(val) {
  // Try to parse as json
  if (typeof val === 'string') {
    try {
      return JSON.parse(val);
    } catch (_) {// ...
    }
  } // Return as is


  return val;
}

var Adapter = /*#__PURE__*/function () {
  function Adapter(options) {
    _classCallCheck(this, Adapter);

    _defineProperty(this, "options", void 0);

    _defineProperty(this, "state", {});

    options.driver = options.driver || {};

    if (typeof options.isServer === 'undefined') {
      options.isServer = function () {
        return false;
      };
    }

    this.options = options;
    this.initState();
  } // ------------------------------------


  _createClass(Adapter, [{
    key: "getKeyWithNamespace",
    value: function getKeyWithNamespace(key) {
      var keyWithNamespace = '';

      if (typeof this.options.namespace !== 'undefined') {
        keyWithNamespace += "".concat(this.options.namespace, "_");
      }

      return keyWithNamespace + key;
    } // ------------------------------------
    // ------------------------------------
    // Universal
    // ------------------------------------

  }, {
    key: "set",
    value: function set(key, value) {
      // Unset null, undefined
      if (isUnset(value)) {
        return this.remove(key);
      }

      this.setState(key, value);
      this.setCookie(key, value);
      this.setLocalStorageItem(key, value);
      this.setSessionStorageItem(key, value);
      return value;
    }
  }, {
    key: "get",
    value: function get(key) {
      var value = this.getState(key); // Cookies

      if (isUnset(value)) {
        value = this.getCookie(key);
      } // Local Storage


      if (isUnset(value)) {
        value = this.getLocalStorageItem(key);
      } // Session Storage


      if (isUnset(value)) {
        value = this.getSessionStorageItem(key);
      }

      if (isUnset(value)) {
        value = this.getState(key);
      }

      return value;
    }
  }, {
    key: "getAll",
    value: function getAll() {
      var value = {};
      var storageValue;
      storageValue = this.getCookies();

      if (storageValue) {
        value = _objectSpread2(_objectSpread2({}, value), storageValue);
      }

      storageValue = this.getLocalStorageItems();

      if (storageValue) {
        value = _objectSpread2(_objectSpread2({}, value), storageValue);
      }

      storageValue = this.getSessionStorageItems();

      if (storageValue) {
        value = _objectSpread2(_objectSpread2({}, value), storageValue);
      }

      return value;
    }
  }, {
    key: "sync",
    value: function sync(key, defaultValue) {
      var value = this.get(key);

      if (isUnset(value) && isSet(defaultValue)) {
        value = defaultValue;
      }

      if (isSet(value)) {
        this.set(key, value);
      }

      return value;
    }
  }, {
    key: "remove",
    value: function remove(key) {
      this.removeState(key);
      this.removeSessionStorageItem(key);
      this.removeLocalStorageItem(key);
      this.removeCookie(key);
    } // ------------------------------------
    // State
    // ------------------------------------

  }, {
    key: "initState",
    value: function initState() {
      if (this.options.isServer()) {
        return;
      }

      this.state = {};
    }
  }, {
    key: "setState",
    value: function setState(key, value) {
      if (this.options.isServer()) {
        return;
      }

      this.state[key] = value;
    }
  }, {
    key: "getState",
    value: function getState(key) {
      if (this.options.isServer()) {
        return undefined;
      }

      return this.state[key];
    }
  }, {
    key: "removeState",
    value: function removeState(key) {
      this.setState(key, undefined);
    } // ------------------------------------
    // Browser Storage
    // ------------------------------------

  }, {
    key: "getBrowserStorageItems",
    value: function getBrowserStorageItems(type) {
      var storage;

      switch (type) {
        case exports.Driver.SESSION_STORAGE:
          storage = sessionStorage;
          break;

        case exports.Driver.LOCAL_STORAGE:
          storage = localStorage;
          break;
      }

      if (typeof storage === 'undefined' || !this.options.driver[type]) {
        return {};
      }

      var items = {};
      var keys = Object.keys(storage);
      var i = keys.length;

      while (i--) {
        var _key = keys[i];

        if (typeof this.options.namespace !== 'undefined') {
          if (_key.slice(0, this.options.namespace.length) !== this.options.namespace) {
            continue;
          }

          _key = _key.replace("".concat(this.options.namespace, "_"), '');
        }

        items[_key] = decodeValue(storage.getItem(keys[i]));
      }

      return items;
    } // ------------------------------------
    // Local storage
    // ------------------------------------

  }, {
    key: "setLocalStorageItem",
    value: function setLocalStorageItem(key, value) {
      // Unset null, undefined
      if (isUnset(value)) {
        this.removeLocalStorageItem(key);
        return;
      }

      if (typeof localStorage === 'undefined' || !this.options.driver.localStorage) {
        return;
      }

      var keyFull = this.getKeyWithNamespace(key);
      localStorage.setItem(keyFull, encodeValue(value));
    }
  }, {
    key: "getLocalStorageItem",
    value: function getLocalStorageItem(key) {
      if (typeof localStorage === 'undefined' || !this.options.driver.localStorage) {
        return undefined;
      }

      var keyFull = this.getKeyWithNamespace(key);
      var value = localStorage.getItem(keyFull);
      return decodeValue(value);
    }
  }, {
    key: "getLocalStorageItems",
    value: function getLocalStorageItems() {
      return this.getBrowserStorageItems(exports.Driver.LOCAL_STORAGE);
    }
  }, {
    key: "removeLocalStorageItem",
    value: function removeLocalStorageItem(key) {
      if (typeof localStorage === 'undefined' || !this.options.driver.localStorage) {
        return;
      }

      var keyWithNamespace = this.getKeyWithNamespace(key);
      localStorage.removeItem(keyWithNamespace);
    } // ------------------------------------
    // Session storage
    // ------------------------------------

  }, {
    key: "setSessionStorageItem",
    value: function setSessionStorageItem(key, value) {
      // Unset null, undefined
      if (isUnset(value)) {
        this.removeSessionStorageItem(key);
        return;
      }

      if (typeof sessionStorage === 'undefined' || !this.options.driver.sessionStorage) {
        return;
      }

      var keyWithNamespace = this.getKeyWithNamespace(key);
      sessionStorage.setItem(keyWithNamespace, encodeValue(value));
    }
  }, {
    key: "getSessionStorageItem",
    value: function getSessionStorageItem(key) {
      if (typeof sessionStorage === 'undefined' || !this.options.driver.sessionStorage) {
        return undefined;
      }

      var keyWithNamespace = this.getKeyWithNamespace(key);
      var value = sessionStorage.getItem(keyWithNamespace);
      return decodeValue(value);
    }
  }, {
    key: "getSessionStorageItems",
    value: function getSessionStorageItems() {
      return this.getBrowserStorageItems(exports.Driver.SESSION_STORAGE);
    }
  }, {
    key: "removeSessionStorageItem",
    value: function removeSessionStorageItem(key) {
      if (typeof sessionStorage === 'undefined' || !this.options.driver.sessionStorage) {
        return;
      }

      var keyWithNamespace = this.getKeyWithNamespace(key);
      sessionStorage.removeItem(keyWithNamespace);
    } // ------------------------------------
    // Cookies
    // ------------------------------------

  }, {
    key: "getCookies",
    value: function getCookies() {
      var isServer = this.options.isServer();
      var cookieStr = isServer ? this.options.getServerCookies ? this.options.getServerCookies() : '' : document.cookie;
      var items = decodeValue(cookie.parse(cookieStr || '') || {}); // eslint-disable-next-line no-restricted-syntax

      for (var _key2 in items) {
        items[_key2] = decodeValue(decodeURIComponent(items[_key2]));
      }

      return items;
    }
  }, {
    key: "setCookie",
    value: function setCookie(key, value) {
      if (!this.options.driver.cookie) {
        return;
      }

      if (typeof this.options.setCookie === 'function') {
        this.options.setCookie(key, value);
        return;
      }

      var keyWithNamespace = this.getKeyWithNamespace(key);

      var options = _objectSpread2({}, typeof this.options.driver.cookie === 'boolean' ? {} : this.options.driver.cookie);

      var valueEncoded = encodeValue(value); // Unset null, undefined

      if (isUnset(value)) {
        options.maxAge = -1;
      }

      var serializedCookie = cookie.serialize(keyWithNamespace, valueEncoded, options);
      var isServer = this.options.isServer();

      if (isServer) {
        this.options.setServerCookie(serializedCookie);
      } else if (this.options.setServerCookie) {
        // Set in browser
        document.cookie = serializedCookie;
      }
    }
  }, {
    key: "getCookie",
    value: function getCookie(key) {
      var _cookies$keyFull;

      if (!this.options.driver.cookie) {
        return undefined;
      }

      if (typeof this.options.getCookie === 'function') {
        return this.options.getCookie(key);
      }

      var keyFull = this.getKeyWithNamespace(key);
      var cookies = this.getCookies();
      return (_cookies$keyFull = cookies[keyFull]) !== null && _cookies$keyFull !== void 0 ? _cookies$keyFull : undefined;
    }
  }, {
    key: "removeCookie",
    value: function removeCookie(key) {
      this.setCookie(key, undefined);
    }
  }]);

  return Adapter;
}();

exports.Adapter = Adapter;
exports.decodeValue = decodeValue;
exports.encodeValue = encodeValue;
exports.isSet = isSet;
exports.isUnset = isUnset;
