import hash from 'murmurhash';
import * as nodePath from 'path'; /* type */
import { processNamespace } from './stylable-processor';

export function packageNamespaceFactory(
    findConfig: (fileName: string, options: { cwd: string }) => string | null,
    loadConfig: (filePath: string) => object,
    { dirname, relative }: Pick<typeof nodePath, 'relative' | 'dirname'>,
    hashSalt = '',
    prefix = '',
    normalizeVersion = (semver: string) => semver
): typeof processNamespace {
    return (namespace: string, stylesheetPath: string) => {
        const configPath = findConfig('package.json', { cwd: dirname(stylesheetPath) });
        if (!configPath) {
            throw new Error(`Could not find package.json for ${stylesheetPath}`);
        }
        const config = loadConfig(configPath) as { name: string; version: string };
        const fromRoot = relative(dirname(configPath), stylesheetPath).replace(/\\/g, '/');
        return (
            prefix +
            namespace +
            hash.v3(
                hashSalt + config.name + '@' + normalizeVersion(config.version) + '/' + fromRoot
            )
        );
    };
}

export function noCollisionNamespace({
    prefix = '',
    used: usedNamespaces = new Map<
        string,
        { prefix: string; namespace: string; stylesheetPath: string }
    >(),
} = {}): typeof processNamespace {
    return (namespace, stylesheetPath) => {
        const ns = prefix + namespace;
        const used = usedNamespaces.get(ns);
        if (used) {
            if (used.stylesheetPath !== stylesheetPath) {
                throw new Error(`namespace (${ns} of ${stylesheetPath}) is already in use`);
            }
        } else {
            usedNamespaces.set(ns, { prefix, namespace, stylesheetPath });
        }
        return ns;
    };
}
