(function (win) {
  'use strict';

  function hasOwn(object, key) {
    return Object.prototype.hasOwnProperty.call(object, key);
  }

  function assignIfPresent(target, source, key) {
    if (!source || !hasOwn(source, key)) {
      return;
    }
    var value = source[key];
    if (value === undefined || value === null || value === '') {
      return;
    }
    target[key] = value;
  }

  function cleanMap(map) {
    if (!map || typeof map !== 'object' || Array.isArray(map)) {
      return null;
    }

    var out = {};
    Object.keys(map).forEach(function (key) {
      var value = map[key];
      if (value === undefined || value === null || value === '') {
        return;
      }
      out[key] = value;
    });
    return Object.keys(out).length ? out : null;
  }

  function build(config) {
    var input = (config && typeof config === 'object') ? config : {};
    var result = {
      type: (typeof input.type === 'string' && input.type.trim() !== '') ? input.type.trim() : 'bmi'
    };

    assignIfPresent(result, input, 'theme');

    if (typeof input.branding !== 'undefined') {
      result.branding = !!input.branding;
    }

    var colorMap = cleanMap(input.colors);
    if (colorMap) {
      result.colors = colorMap;
    }

    var designMap = cleanMap(input.design);
    if (designMap) {
      result.design = designMap;
    }

    var formattingMap = cleanMap(input.formatting);
    if (formattingMap) {
      result.formatting = formattingMap;
    }

    var accessibilityMap = cleanMap(input.accessibility);
    if (accessibilityMap) {
      result.accessibility = accessibilityMap;
    }

    var measurementMap = cleanMap(input.measurement);
    if (measurementMap) {
      result.measurement = measurementMap;
    }

    if (win.VareoncalcShadowPreview && typeof win.VareoncalcShadowPreview.normalizeConfig === 'function') {
      return win.VareoncalcShadowPreview.normalizeConfig(result);
    }
    if (win.VareoncalcPreviewBridge && typeof win.VareoncalcPreviewBridge.normalizeConfig === 'function') {
      return win.VareoncalcPreviewBridge.normalizeConfig(result);
    }
    return result;
  }

  win.VAREONCALC_PREVIEW_CONFIG = win.VAREONCALC_PREVIEW_CONFIG || {};
  win.VAREONCALC_PREVIEW_CONFIG.pro = {
    build: build
  };
})(window);
