"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.registerPreviewStyle = registerPreviewStyle;
exports.getPreviewStyles = getPreviewStyles;
exports.registerPreviewTemplate = registerPreviewTemplate;
exports.getPreviewTemplate = getPreviewTemplate;
exports.registerWidget = registerWidget;
exports.getWidget = getWidget;
exports.resolveWidget = resolveWidget;
exports.registerEditorComponent = registerEditorComponent;
exports.getEditorComponents = getEditorComponents;
exports.registerWidgetValueSerializer = registerWidgetValueSerializer;
exports.getWidgetValueSerializer = getWidgetValueSerializer;
exports.registerBackend = registerBackend;
exports.getBackend = getBackend;
exports.registerMediaLibrary = registerMediaLibrary;
exports.getMediaLibrary = getMediaLibrary;
exports.getEventListeners = getEventListeners;
exports.registerEventListener = registerEventListener;
exports.invokeEvent = invokeEvent;
exports.removeEventListener = removeEventListener;
exports.registerLocale = registerLocale;
exports.getLocale = getLocale;
exports.default = void 0;

var _immutable = require("immutable");

var _commonTags = require("common-tags");

var _EditorComponent = _interopRequireDefault(require("../valueObjects/EditorComponent"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _templateObject() {
  const data = _taggedTemplateLiteral(["\n        Multiple widgets registered with name \"", "\". Only the last widget registered with\n        this name will be used.\n      "]);

  _templateObject = function _templateObject() {
    return data;
  };

  return data;
}

function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

const allowedEvents = ['prePublish', 'postPublish', 'preUnpublish', 'postUnpublish'];
const eventHandlers = {};
allowedEvents.forEach(e => {
  eventHandlers[e] = [];
});
/**
 * Global Registry Object
 */

const registry = {
  backends: {},
  templates: {},
  previewStyles: [],
  widgets: {},
  editorComponents: (0, _immutable.Map)(),
  widgetValueSerializers: {},
  mediaLibraries: [],
  locales: {},
  eventHandlers
};
var _default = {
  registerPreviewStyle,
  getPreviewStyles,
  registerPreviewTemplate,
  getPreviewTemplate,
  registerWidget,
  getWidget,
  resolveWidget,
  registerEditorComponent,
  getEditorComponents,
  registerWidgetValueSerializer,
  getWidgetValueSerializer,
  registerBackend,
  getBackend,
  registerMediaLibrary,
  getMediaLibrary,
  registerLocale,
  getLocale,
  registerEventListener,
  removeEventListener,
  getEventListeners,
  invokeEvent
};
/**
 * Preview Styles
 *
 * Valid options:
 *  - raw {boolean} if `true`, `style` value is expected to be a CSS string
 */

exports.default = _default;

function registerPreviewStyle(style, opts) {
  registry.previewStyles.push(_objectSpread({}, opts, {
    value: style
  }));
}

function getPreviewStyles() {
  return registry.previewStyles;
}
/**
 * Preview Templates
 */


function registerPreviewTemplate(name, component) {
  registry.templates[name] = component;
}

function getPreviewTemplate(name) {
  return registry.templates[name];
}
/**
 * Editor Widgets
 */


function registerWidget(name, control, preview) {
  if (Array.isArray(name)) {
    name.forEach(widget => {
      if (typeof widget !== 'object') {
        console.error("Cannot register widget: ".concat(widget));
      } else {
        registerWidget(widget);
      }
    });
  } else if (typeof name === 'string') {
    // A registered widget control can be reused by a new widget, allowing
    // multiple copies with different previews.
    const newControl = typeof control === 'string' ? registry.widgets[control].control : control;
    registry.widgets[name] = {
      control: newControl,
      preview
    };
  } else if (typeof name === 'object') {
    const {
      name: widgetName,
      controlComponent: control,
      previewComponent: preview,
      globalStyles
    } = name;

    if (registry.widgets[widgetName]) {
      console.error((0, _commonTags.oneLine)(_templateObject(), widgetName));
    }

    if (!control) {
      throw Error("Widget \"".concat(widgetName, "\" registered without `controlComponent`."));
    }

    registry.widgets[widgetName] = {
      control,
      preview,
      globalStyles
    };
  } else {
    console.error('`registerWidget` failed, called with incorrect arguments.');
  }
}

function getWidget(name) {
  return registry.widgets[name];
}

function resolveWidget(name) {
  return getWidget(name || 'string') || getWidget('unknown');
}
/**
 * Markdown Editor Custom Components
 */


function registerEditorComponent(component) {
  const plugin = (0, _EditorComponent.default)(component);
  registry.editorComponents = registry.editorComponents.set(plugin.get('id'), plugin);
}

function getEditorComponents() {
  return registry.editorComponents;
}
/**
 * Widget Serializers
 */


function registerWidgetValueSerializer(widgetName, serializer) {
  registry.widgetValueSerializers[widgetName] = serializer;
}

function getWidgetValueSerializer(widgetName) {
  return registry.widgetValueSerializers[widgetName];
}
/**
 * Backend API
 */


function registerBackend(name, BackendClass) {
  if (!name || !BackendClass) {
    console.error("Backend parameters invalid. example: CMS.registerBackend('myBackend', BackendClass)");
  } else if (registry.backends[name]) {
    console.error("Backend [".concat(name, "] already registered. Please choose a different name."));
  } else {
    registry.backends[name] = {
      init: function init() {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }

        return new BackendClass(...args);
      }
    };
  }
}

function getBackend(name) {
  return registry.backends[name];
}
/**
 * Media Libraries
 */


function registerMediaLibrary(mediaLibrary, options) {
  if (registry.mediaLibraries.find(ml => mediaLibrary.name === ml.name)) {
    throw new Error("A media library named ".concat(mediaLibrary.name, " has already been registered."));
  }

  registry.mediaLibraries.push(_objectSpread({}, mediaLibrary, {
    options
  }));
}

function getMediaLibrary(name) {
  return registry.mediaLibraries.find(ml => ml.name === name);
}

function validateEventName(name) {
  if (!allowedEvents.includes(name)) {
    throw new Error("Invalid event name '".concat(name, "'"));
  }
}

function getEventListeners(name) {
  validateEventName(name);
  return [...registry.eventHandlers[name]];
}

function registerEventListener(_ref) {
  let {
    name,
    handler
  } = _ref;
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  validateEventName(name);
  registry.eventHandlers[name].push({
    handler,
    options
  });
}

async function invokeEvent(_ref2) {
  let {
    name,
    data
  } = _ref2;
  validateEventName(name);
  const handlers = registry.eventHandlers[name];
  let iterationData = null;

  for (const _ref3 of handlers) {
    const {
      handler,
      options
    } = _ref3;

    try {
      const dataToUse = iterationData || data;
      iterationData = await handler(dataToUse, options);
    } catch (e) {
      console.warn("Failed running handler for event ".concat(name, " with message: ").concat(e.message));
    }
  }

  return iterationData;
}

function removeEventListener(_ref4) {
  let {
    name,
    handler
  } = _ref4;
  validateEventName(name);

  if (handler) {
    registry.eventHandlers[name] = registry.eventHandlers[name].filter(item => item.handler !== handler);
  } else {
    registry.eventHandlers[name] = [];
  }
}
/**
 * Locales
 */


function registerLocale(locale, phrases) {
  if (!locale || !phrases) {
    console.error("Locale parameters invalid. example: CMS.registerLocale('locale', phrases)");
  } else {
    registry.locales[locale] = phrases;
  }
}

function getLocale(locale) {
  return registry.locales[locale];
}