'use strict';

const index = require('./index-cba1c3ae.js');

const appendToMap = (map, propName, value) => {
    const items = map.get(propName);
    if (!items) {
        map.set(propName, [value]);
    }
    else if (!items.includes(value)) {
        items.push(value);
    }
};
const debounce = (fn, ms) => {
    let timeoutId;
    return (...args) => {
        if (timeoutId) {
            clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(() => {
            timeoutId = 0;
            fn(...args);
        }, ms);
    };
};

/**
 * Check if a possible element isConnected.
 * The property might not be there, so we check for it.
 *
 * We want it to return true if isConnected is not a property,
 * otherwise we would remove these elements and would not update.
 *
 * Better leak in Edge than to be useless.
 */
const isConnected = (maybeElement) => !('isConnected' in maybeElement) || maybeElement.isConnected;
const cleanupElements = debounce((map) => {
    for (let key of map.keys()) {
        map.set(key, map.get(key).filter(isConnected));
    }
}, 2000);
const stencilSubscription = () => {
    if (typeof index.getRenderingRef !== 'function') {
        // If we are not in a stencil project, we do nothing.
        // This function is not really exported by @stencil/core.
        return {};
    }
    const elmsToUpdate = new Map();
    return {
        dispose: () => elmsToUpdate.clear(),
        get: (propName) => {
            const elm = index.getRenderingRef();
            if (elm) {
                appendToMap(elmsToUpdate, propName, elm);
            }
        },
        set: (propName) => {
            const elements = elmsToUpdate.get(propName);
            if (elements) {
                elmsToUpdate.set(propName, elements.filter(index.forceUpdate));
            }
            cleanupElements(elmsToUpdate);
        },
        reset: () => {
            elmsToUpdate.forEach((elms) => elms.forEach(index.forceUpdate));
            cleanupElements(elmsToUpdate);
        },
    };
};

const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) => {
    let states = new Map(Object.entries(defaultState !== null && defaultState !== void 0 ? defaultState : {}));
    const handlers = {
        dispose: [],
        get: [],
        set: [],
        reset: [],
    };
    const reset = () => {
        states = new Map(Object.entries(defaultState !== null && defaultState !== void 0 ? defaultState : {}));
        handlers.reset.forEach((cb) => cb());
    };
    const dispose = () => {
        // Call first dispose as resetting the state would
        // cause less updates ;)
        handlers.dispose.forEach((cb) => cb());
        reset();
    };
    const get = (propName) => {
        handlers.get.forEach((cb) => cb(propName));
        return states.get(propName);
    };
    const set = (propName, value) => {
        const oldValue = states.get(propName);
        if (shouldUpdate(value, oldValue, propName)) {
            states.set(propName, value);
            handlers.set.forEach((cb) => cb(propName, value, oldValue));
        }
    };
    const state = (typeof Proxy === 'undefined'
        ? {}
        : new Proxy(defaultState, {
            get(_, propName) {
                return get(propName);
            },
            ownKeys(_) {
                return Array.from(states.keys());
            },
            getOwnPropertyDescriptor() {
                return {
                    enumerable: true,
                    configurable: true,
                };
            },
            has(_, propName) {
                return states.has(propName);
            },
            set(_, propName, value) {
                set(propName, value);
                return true;
            },
        }));
    const on = (eventName, callback) => {
        handlers[eventName].push(callback);
        return () => {
            removeFromArray(handlers[eventName], callback);
        };
    };
    const onChange = (propName, cb) => {
        const unSet = on('set', (key, newValue) => {
            if (key === propName) {
                cb(newValue);
            }
        });
        const unReset = on('reset', () => cb(defaultState[propName]));
        return () => {
            unSet();
            unReset();
        };
    };
    const use = (...subscriptions) => {
        const unsubs = subscriptions.reduce((unsubs, subscription) => {
            if (subscription.set) {
                unsubs.push(on('set', subscription.set));
            }
            if (subscription.get) {
                unsubs.push(on('get', subscription.get));
            }
            if (subscription.reset) {
                unsubs.push(on('reset', subscription.reset));
            }
            if (subscription.dispose) {
                unsubs.push(on('dispose', subscription.dispose));
            }
            return unsubs;
        }, []);
        return () => unsubs.forEach((unsub) => unsub());
    };
    const forceUpdate = (key) => {
        const oldValue = states.get(key);
        handlers.set.forEach((cb) => cb(key, oldValue, oldValue));
    };
    return {
        state,
        get,
        set,
        on,
        onChange,
        use,
        dispose,
        reset,
        forceUpdate,
    };
};
const removeFromArray = (array, item) => {
    const index = array.indexOf(item);
    if (index >= 0) {
        array[index] = array[array.length - 1];
        array.length--;
    }
};

const createStore = (defaultState, shouldUpdate) => {
    const map = createObservableMap(defaultState, shouldUpdate);
    map.use(stencilSubscription());
    return map;
};

const config = {
  env: "local",
  url: "http://localhost:3333",
  firebase: {
    apiKey: "AIzaSyAz5C9TRxQ9bUkTwVaD6Yc-Iisw57UslPM",
    authDomain: "fireenjin-live.firebaseapp.com",
    databaseURL: "https://fireenjin-live.firebaseio.com",
    projectId: "fireenjin-live",
    storageBucket: "fireenjin-live.appspot.com",
    messagingSenderId: "756564610596",
    appId: "1:756564610596:web:4fdf5a6ddfd319a93392b1",
    measurementId: "G-Q0ZHGFCQFN",
  },
  dynamicLinkDomain: "fireenjin.page.link",
};

function env(key, fallback) {
  const value = !key
    ? config
    : key && key.indexOf(".") >= 0
      ? key.split(".").reduce((p, c) => (p && p[c]) || null, config)
      : key && typeof config[key] !== "undefined"
        ? config[key]
        : null;
  return fallback &&
    ((!value && value !== false && value !== 0) ||
      typeof value === "undefined" ||
      value === null)
    ? fallback
    : value;
}

const { state, onChange } = createStore({
  config: env(),
  version: (localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) && localStorage.getItem("fireenjin:version")
    ? localStorage.getItem("fireenjin:version")
    : "1.1.0",
  profile: ((localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) && localStorage.getItem("fireenjin:profile")
    ? JSON.parse(localStorage.getItem("fireenjin:profile"))
    : {}),
  session: null,
  templates: ((localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) &&
    localStorage.getItem("fireenjin:templates")
    ? JSON.parse(localStorage.getItem("fireenjin:templates"))
    : []),
  partials: ((localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) && localStorage.getItem("fireenjin:partials")
    ? JSON.parse(localStorage.getItem("fireenjin:partials"))
    : []),
  template: ((localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) && localStorage.getItem("fireenjin:template")
    ? JSON.parse(localStorage.getItem("fireenjin:template"))
    : {}),
  isOnline: false,
  editorSizes: ((localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) &&
    localStorage.getItem("fireenjin:editorSizes")
    ? JSON.parse(localStorage.getItem("fireenjin:editorSizes"))
    : [50, 50]),
  isPreviewing: ((localStorage === null || localStorage === void 0 ? void 0 : localStorage.getItem) &&
    localStorage.getItem("fireenjin:isPreviewing")
    ? JSON.parse(localStorage.getItem("fireenjin:isPreviewing"))
    : false),
});
onChange("editorSizes", (value) => {
  localStorage.setItem("fireenjin:editorSizes", JSON.stringify(value));
});
onChange("isPreviewing", (value) => {
  localStorage.setItem("fireenjin:isPreviewing", JSON.stringify(value));
});
onChange("profile", (value) => {
  localStorage.setItem("fireenjin:profile", JSON.stringify(value));
});
onChange("version", (value) => {
  localStorage.setItem("fireenjin:version", value);
});
onChange("template", (value) => {
  localStorage.setItem("fireenjin:template", JSON.stringify(value));
});
onChange("templates", (value) => {
  localStorage.setItem("fireenjin:templates", JSON.stringify(value));
});
onChange("partials", (value) => {
  localStorage.setItem("fireenjin:partials", JSON.stringify(value));
});

exports.env = env;
exports.state = state;
