'use strict';

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

var solidJs = require('solid-js');

function createProxy(source) {
    return new Proxy(function hmrCompWrapper(props, ...rest) {
        const s = source();
        if (!s || solidJs.$DEVCOMP in s) {
            return solidJs.createMemo(() => {
                const c = source();
                if (c) {
                    return solidJs.untrack(() => c(props));
                }
                return undefined;
            });
        }
        // no $DEVCOMP means it did not go through devComponent so source() is a regular function, not a component
        return s.call(this, props, ...rest);
    }, {
        get(_, property) {
            return source()[property];
        },
        set(_, property, value) {
            source()[property] = value;
            return true;
        }
    });
}

function isListUpdated(a, b) {
    if (a == null && b != null) {
        return true;
    }
    if (a != null && b == null) {
        return true;
    }
    if (a && b) {
        if (a.length !== b.length) {
            return true;
        }
        for (let i = 0, len = a.length; i < len; i++) {
            if (!Object.is(a[i], b[i])) {
                return true;
            }
        }
    }
    return false;
}

function hot$1({ component: Comp, id, signature, dependencies }, hot) {
    if (hot) {
        const [comp, setComp] = solidJs.createSignal(Comp, { internal: true });
        const prev = hot.data;
        // Check if there's previous data
        if (prev && prev[id]) {
            // Check if there's a new signature and dependency
            // This is always new in standard HMR
            if (signature && dependencies) {
                // Check if signature changed
                // or dependencies changed
                if (prev[id].signature !== signature ||
                    isListUpdated(prev[id].dependencies, dependencies)) {
                    // Remount
                    prev[id].dependencies = dependencies;
                    prev[id].signature = signature;
                    prev[id].setComp(() => Comp);
                }
            }
            else {
                prev[id].setComp(() => Comp);
            }
        }
        hot.dispose(data => {
            data[id] = prev
                ? prev[id]
                : {
                    setComp,
                    signature,
                    dependencies
                };
        });
        hot.accept();
        return createProxy(comp);
    }
    return Comp;
}

const HOT_DATA_PREFIX = "solid-refresh-ctx";
function hot({ component: Comp, id, signature, dependencies }, hot) {
    let Component = Comp;
    function handler(newModule) {
        const registration = newModule.$$registrations[id];
        if (!registration) {
            // For some reason, the registration was lost, invalidate
            return true;
        }
        registration.component.setComp = Comp.setComp;
        registration.component.signature = Comp.signature;
        registration.component.dependencies = Comp.dependencies;
        // Check if incoming module has signature
        if (registration.signature && registration.dependencies) {
            // Compare old signature and dependencies
            if (registration.signature !== Comp.signature ||
                isListUpdated(registration.dependencies, Comp.dependencies)) {
                // Remount
                Comp.dependencies = registration.dependencies;
                Comp.signature = registration.signature;
                Comp.setComp(() => registration.component);
            }
        }
        else {
            // No granular update, remount
            Comp.setComp(() => registration.component);
        }
        registration.component.signature = Comp.signature;
        registration.component.dependencies = Comp.dependencies;
        return false;
    }
    if (hot && hot.data) {
        const refreshData = (hot.data[HOT_DATA_PREFIX] = hot.data[HOT_DATA_PREFIX] || {});
        if (refreshData[id]) {
            Comp.setComp = refreshData[id].Comp.setComp;
            return { Component: refreshData[id].Component, handler };
        }
        const [comp, setComp] = solidJs.createSignal(Comp, { internal: true });
        Comp.setComp = setComp;
        Comp.dependencies = dependencies;
        Comp.signature = signature;
        Component = createProxy(comp);
        refreshData[id] = { Component, Comp };
    }
    return { Component, handler };
}

let warned = false;
function shouldWarnAndDecline() {
    const result = solidJs.DEV && Object.keys(solidJs.DEV).length;
    if (result) {
        return false;
    }
    if (!warned) {
        console.warn("To use solid-refresh, you need to use the dev build of SolidJS. Make sure your build system supports package.json conditional exports and has the 'development' condition turned on.");
        warned = true;
    }
    return true;
}

exports.esm = hot;
exports.shouldWarnAndDecline = shouldWarnAndDecline;
exports.standard = hot$1;
