/* global global */
import { EventEmitter } from './eventemitter';
import BrowserStorage from './storage';
import { Collection } from './collection';
import { Model } from './model';
import { sync } from './helpers';

/**
 * @public
 */
interface SkeletorType {
  Collection: typeof Collection;
  EventEmitter: typeof EventEmitter;
  Model: typeof Model;
  sync: typeof sync;
  VERSION?: string;
  noConflict?: () => SkeletorType;
}

/**
 * @public
 */
const skeletor: SkeletorType = {
  Collection,
  EventEmitter,
  Model,
  sync,
};

// Establish the root object, `window` (`self`) in the browser, or `global` on the server.
// We use `self` instead of `window` for `WebWorker` support.
const root =
  (typeof self == 'object' && self.self === self && self) ||
  (typeof global == 'object' && global.global === global && global);

// Current version of the library. Keep in sync with `package.json`.
skeletor.VERSION = '0.0.1';

// Save the previous value of the `Skeletor` variable, so that it can be
// restored later on, if `noConflict` is used.
const previousSkeletor = root.Skeletor;

// Runs Skeletor.js in *noConflict* mode, returning the `Skeletor` variable
// to its previous owner. Returns a reference to this Skeletor object.
/**
 * @public
 */
function noConflict() {
  root.Skeletor = previousSkeletor;
  return this;
}
skeletor.noConflict = noConflict;

root.Skeletor = skeletor;
export default skeletor;

export { noConflict, Collection, EventEmitter, Model, BrowserStorage, sync };

export type { LocalForageWithExtensions } from './storage';
export type {
  ClassConstructor,
  CollectionOptions,
  Comparator,
  EventCallback,
  EventCallbackMap,
  EventContext,
  EventHandler,
  EventHandlersMap,
  EventListenerMap,
  FetchOrCreateOptions,
  IEventEmitter,
  ListeningMap,
  ListeningType,
  ModelAttributes,
  ModelOptions,
  ObjectListenedTo,
  ObjectWithId,
  Options,
  SyncOperation,
  SyncOptions,
} from './types';

export type { CollectionIterator } from './collection';
export type { SkeletorType };
export type { EventEmitterObject } from './eventemitter';
