import PluginManager from '@jbrowse/core/PluginManager';
import TextSearchManager from '@jbrowse/core/TextSearch/TextSearchManager';
import assemblyManagerFactory, { assemblyConfigSchemaFactory, } from '@jbrowse/core/assemblyManager';
import RpcManager from '@jbrowse/core/rpc/RpcManager';
import { cast, getSnapshot, types } from '@jbrowse/mobx-state-tree';
import corePlugins from "../corePlugins.js";
import createConfigModel from "./createConfigModel.js";
import createSessionModel from "./createSessionModel.js";
import { version } from "../version.js";
export default function createModel(runtimePlugins, makeWorkerInstance = () => {
    throw new Error('no makeWorkerInstance supplied');
}) {
    const pluginManager = new PluginManager([...corePlugins, ...runtimePlugins].map(P => new P()));
    pluginManager.createPluggableElements();
    const Session = createSessionModel(pluginManager);
    const assemblyConfigSchema = assemblyConfigSchemaFactory(pluginManager);
    const assemblyManagerType = assemblyManagerFactory(assemblyConfigSchema, pluginManager);
    const rootModel = types
        .model('ReactCircularGenomeView', {
        config: createConfigModel(pluginManager, assemblyConfigSchema),
        session: Session,
        assemblyManager: types.optional(assemblyManagerType, {}),
        internetAccounts: types.array(pluginManager.pluggableMstType('internet account', 'stateModel')),
    })
        .volatile(self => ({
        error: undefined,
        adminMode: false,
        version,
        rpcManager: new RpcManager(pluginManager, self.config.configuration.rpc, {
            WebWorkerRpcDriver: {
                makeWorkerInstance,
            },
            MainThreadRpcDriver: {},
        }),
        textSearchManager: new TextSearchManager(pluginManager),
    }))
        .actions(self => ({
        setSession(sessionSnapshot) {
            self.session = cast(sessionSnapshot);
        },
        renameCurrentSession(sessionName) {
            const snapshot = JSON.parse(JSON.stringify(getSnapshot(self.session)));
            snapshot.name = sessionName;
            this.setSession(snapshot);
        },
        setError(error) {
            self.error = error;
        },
        addInternetAccount(internetAccount) {
            self.internetAccounts.push(internetAccount);
        },
        findAppropriateInternetAccount(location) {
            const selectedId = location.internetAccountId;
            if (selectedId) {
                const selectedAccount = self.internetAccounts.find(a => a.internetAccountId === selectedId);
                if (selectedAccount) {
                    return selectedAccount;
                }
            }
            for (const account of self.internetAccounts) {
                const handleResult = account.handlesLocation(location);
                if (handleResult) {
                    return account;
                }
            }
            return null;
        },
    }))
        .views(self => ({
        get jbrowse() {
            return self.config;
        },
        get pluginManager() {
            return pluginManager;
        },
    }));
    return { model: rootModel, pluginManager };
}
