import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';

function promisifyRequest(request) {
  return new Promise(function (resolve, reject) {
    // @ts-ignore - file size hacks
    request.oncomplete = request.onsuccess = function () {
      return resolve(request.result);
    }; // @ts-ignore - file size hacks


    request.onabort = request.onerror = function () {
      return reject(request.error);
    };
  });
}

function createStore(dbName, storeName) {
  var request = indexedDB.open(dbName);

  request.onupgradeneeded = function () {
    return request.result.createObjectStore(storeName);
  };

  var dbp = promisifyRequest(request);
  return function (txMode, callback) {
    return dbp.then(function (db) {
      return callback(db.transaction(storeName, txMode).objectStore(storeName));
    });
  };
}

var defaultGetStoreFunc;

function defaultGetStore() {
  if (!defaultGetStoreFunc) {
    defaultGetStoreFunc = createStore('keyval-store', 'keyval');
  }

  return defaultGetStoreFunc;
}
/**
 * Get a value by its key.
 *
 * @param key
 * @param customStore Method to get a custom store. Use with caution (see the docs).
 */


function get(key) {
  var customStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetStore();
  return customStore('readonly', function (store) {
    return promisifyRequest(store.get(key));
  });
}
/**
 * Set a value with a key.
 *
 * @param key
 * @param value
 * @param customStore Method to get a custom store. Use with caution (see the docs).
 */


function set(key, value) {
  var customStore = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultGetStore();
  return customStore('readwrite', function (store) {
    store.put(value, key);
    return promisifyRequest(store.transaction);
  });
}
/**
 * Delete a particular key from the store.
 *
 * @param key
 * @param customStore Method to get a custom store. Use with caution (see the docs).
 */


function del(key) {
  var customStore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetStore();
  return customStore('readwrite', function (store) {
    store.delete(key);
    return promisifyRequest(store.transaction);
  });
}

class MdsIconSet {
  /**
   * Create a new icon set.  Icon sets have a name (ie, a namespace).  For
   * example, an icon with a name of "rh-logo" represents a "logo" icon from the
   * "rh" set.  Icon set names are always separated from the rest of the icon
   * name with a hyphen `-`.  This means that set names cannot contain a hyphen.
   *
   * @param  name the namespace of the icon set
   * @param  path the web-accessible path to the icon set (for instance, a CDN)
   * @param  resolveIconName an optional function to combine the path and an icon name into a final path.  The function will be passed the namespaced icon name (for example, "rh-api" where rh is the namespace and api is the individual icon's name)
   * @returns  an object with the status of the icon set installation, such as `{ result: true, text: 'icon set installed' }` or `{ result: false, text: 'icon set is already installed' }`
   */
  constructor(name, path, _resolveIconName) {
    this.name = name;
    this.path = path;
    this._resolveIconName = _resolveIconName;
  }
  /**
   * Run the icon set's name resolver to turn an icon name into an icon path, id, etc.
   */
  resolveIconName(iconName) {
    console.log(`resolveIconName - iconName: ${iconName} | name: ${this.name} | path: ${this.path}`);
    return this._resolveIconName(iconName, this.name, this.path);
  }
  get resolver() {
    return this._resolveIconName;
  }
}

class IconsSetController {
  constructor() {
    this._iconsSets = new Map();
    this.cacheExp = 60 * 60 * 1000 * 24;
    this.memoryCache = {};
    // Try to retrieve svg from cache
    this.isCacheAvailable = async (url) => {
      try {
        const loaderItem = await get(`loader_${url}`);
        if (!loaderItem) {
          return false;
        }
        const item = JSON.parse(loaderItem);
        if (Date.now() < item.expiry) {
          return item.data;
        }
        del(`loader_${url}`);
        return false;
      }
      catch (e) {
        console.error('isCacheAvailable error', e);
        return false;
      }
    };
    // Set svg to cache
    this.setCache = async (url, data) => {
      try {
        await set(`loader_${url}`, JSON.stringify({
          data,
          expiry: Date.now() + this.cacheExp,
        }));
      }
      catch (e) {
        console.error('setCache error', e);
      }
    };
  }
  addIconSet(name, path, resolveIconName) {
    let resolveFunction = resolveIconName;
    const existingSet = this._iconsSets.get(name);
    if (!resolveFunction && existingSet && typeof existingSet.resolver === 'function') {
      resolveFunction = existingSet.resolver;
    }
    else if (resolveFunction && typeof resolveFunction !== 'function') {
      console.error('MdsIconSvg: the third input of addIconSet should be a function that parses and returns the icons\'s filename.');
      return false;
    }
    else if (!resolveFunction) {
      console.error(`MdsIconSvg: the set ${name} needs a resolve function for the icon names.`);
      return false;
    }
    this._iconsSets.set(name, new MdsIconSet(name, path, resolveFunction));
    return true;
  }
  getIconSet(iconName) {
    if (!iconName)
      return { set: null };
    return { set: this._iconsSets.get(iconName.split('/')[0]) };
  }
  setSvgPath(svgPath) {
    this._svgPath = svgPath;
  }
  getSvgPath() {
    return this._svgPath;
  }
  async fetchSvg(src) {
    try {
      const lsCache = await this.isCacheAvailable(src);
      if (this.memoryCache[src] || lsCache) {
        return this.memoryCache[src] || lsCache;
      }
      const response = await fetch(src);
      if (!response.ok) {
        throw Error(`Request for '${src}' returned ${response.status} (${response.statusText})`);
      }
      const body = await response.text();
      const bodyLower = body.toLowerCase().trim();
      if (!(bodyLower.startsWith('<svg') || bodyLower.startsWith('<?xml'))) {
        throw Error(`Resource '${src}' returned an invalid SVG file`);
      }
      this.setCache(src, body);
      this.memoryCache[src] = body;
      return body;
    }
    catch (e) {
      console.error('fetchSvg error', e);
      return '';
    }
  }
}
const IconsSetService = new IconsSetController();

const mdsIconCss = ".static{position:static}.fixed{position:fixed}.absolute{position:absolute}.border{border-width:1px}.fill-label-blue-05{fill:rgb(var(--label-blue-05))}.fill-label-green-06{fill:rgb(var(--label-green-06))}.shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}:host{display:inline-flex;aspect-ratio:1 / 1;width:1.5rem;align-items:center;justify-content:center}.icon{display:inline-flex;align-items:center;justify-content:center;font-style:normal}.icon svg{height:auto;width:100%}";

const MdsIcon = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
  constructor() {
    super();
    this.__registerHost();
    this.__attachShadow();
  }
  componentWillLoad() {
    this.updateIconHref();
  }
  static setSvgPathStatic(path) {
    IconsSetService.setSvgPath(path);
  }
  /**
   * Set the path to the directory of svg files
   * @param svgPath path to the directory of svg files
   */
  async setSvgPath(svgPath) {
    IconsSetService.setSvgPath(svgPath);
    this.updateIconHref();
  }
  async updateIconHref() {
    if (!this.name)
      return Promise.resolve();
    const svgPath = IconsSetService.getSvgPath() || window.sessionStorage.getItem(MdsIcon._svgPathKey);
    this._iconHref = svgPath && !this.name.startsWith('http') ? window.location.origin.concat(svgPath.concat(this.name).concat('.svg')) : this.name;
    this.svgHTML = await IconsSetService.fetchSvg(this._iconHref);
  }
  render() {
    return (h(Host, null, this.svgHTML && h("i", { class: "icon", innerHTML: this.svgHTML })));
  }
  get hostElement() { return this; }
  static get watchers() { return {
    "name": ["updateIconHref"]
  }; }
  static get style() { return mdsIconCss; }
}, [1, "mds-icon", {
    "name": [513],
    "svgHTML": [32],
    "_iconHref": [32],
    "setSvgPath": [64]
  }]);
MdsIcon._svgPathKey = 'mdsIconSvgPath';
function defineCustomElement() {
  if (typeof customElements === "undefined") {
    return;
  }
  const components = ["mds-icon"];
  components.forEach(tagName => { switch (tagName) {
    case "mds-icon":
      if (!customElements.get(tagName)) {
        customElements.define(tagName, MdsIcon);
      }
      break;
  } });
}
defineCustomElement();

export { MdsIcon as M, defineCustomElement as d };
