import * as React from 'react';
import * as s from 'styled-components';
import { ThemableComponents, } from './GeneratedTheme';
function validateKey(key) {
    if (typeof key !== 'string' && typeof key !== 'number') {
        throw new Error('Simple map only supports string/number keys');
    }
    return '$' + key;
}
export class SimpleMap {
    constructor() {
        this._pairs = {};
    }
    get(key) {
        const k = validateKey(key);
        return k in this._pairs ? this._pairs[k] : null;
    }
    set(key, value) {
        const k = validateKey(key);
        this._pairs[k] = value;
    }
    delete(key) {
        const k = validateKey(key);
        if (k in this._pairs) {
            delete this._pairs[k];
        }
    }
}
export class ThemeRegister {
    constructor() {
        this.css = s.css;
        this.injectGlobal = s.injectGlobal;
        this.keyframes = s.keyframes;
        this.styled = s.default;
        this.withTheme = s.withTheme;
        this.ThemeProvider = s.ThemeProvider;
        this._abstractComponents = new SimpleMap();
        this._componentThemes = new SimpleMap();
        this._registeredComponents = new SimpleMap();
        this._renderInputLayout = null;
    }
    layoutInput(render) {
        this._renderInputLayout = render;
        return this;
    }
    getInputLayout() {
        return this._renderInputLayout;
    }
    register(component, theme) {
        const AbstractComponent = this._abstractComponents.get(component);
        if (AbstractComponent != null) {
            this._registeredComponents.set(component, theme(AbstractComponent));
        }
        else {
            this._componentThemes.set(component, theme);
        }
        return this;
    }
    registerAbstractComponent(component, implementation) {
        this._abstractComponents.set(component, implementation);
        const theme = this._componentThemes.get(component);
        this._registeredComponents.set(component, theme == null ? implementation : theme(implementation));
        const Component = (props) => {
            const ThemedComponent = this._registeredComponents.get(component) || implementation;
            return <ThemedComponent {...props}/>;
        };
        Component.displayName = implementation.displayName
            ? `ThemedWrapper(${implementation.displayName})`
            : 'ThemedWrapper';
        return Component;
    }
}
export { ThemableComponents };
const theme = new ThemeRegister();
export const abstractComponentRegister = theme;
export default function define() {
    return theme;
}
