/// Used to merge a module's default configuration with any custom
/// values passed to the module
///
/// @param {map} $map-old - The map which holds default configuration
/// @param {map} $map-new - The map which holds custom values
/// @param {string} $parser - Custom parser to use for configuration
@function create-config($map-old: (), $map-new: (), $parser: $sassConfigParser) {
  $map-old: map-merge((
    'extendOptions' : $extendOptions
  ), $map-old);

  // Merge theme values
  @if variable-exists('theme') and not variable-exists('CellThemeProcessed') {
    @if map-has-key($theme, 'modules') {
      $map-old: map-merge-deep($map-old, map-get-deep($theme, 'modules', map-get($map-old, 'name')));
    }
  }

  // Merge default and custom options
  $map-merged: map-merge-deep($map-old, $map-new);

  // Evaluate configuration values
  $map-merged: eval-config($map-merged);

  // Evaluate configuration values
  @if ($parser) {
    $map-merged: call(get-function($parser), $map-merged);
  }

  // Store config in global variable
  $config: $map-merged !global;
  $smart-config: smart-config($config) !global;

  // Return merged map
  @return $map-merged;
}

/// Evaluate properties from function-calls
@function eval-config($config) {
  $evaluated-config: ();

  @each $key, $value in $config {
    @if type-of($value) == 'map' {
      $evaluated-config: map-set($evaluated-config, $key, eval-config($value));
    }

    @else {
      @if type-of($value) == 'list' and type-of(nth($value, 1)) == 'string' and function-exists(nth($value, 1)) {
        $value: call(get-function(nth($value, 1)), nth($value, 2)...);
      }

      $evaluated-config: map-set($evaluated-config, $key, $value);
    }
  }

  @return $evaluated-config;
}

/// Convert configuration keys such as `component(item)` into the
/// paramater name, i.e. `item`, so they can be retreived with `this()`
@function smart-config($config) {
  $smart-config: ();

  @each $key, $value in $config {
    @if type-of($value) == 'map' {
      $smart-config: map-set($smart-config, get-param($key), smart-config($value));
    }

    @else {
      @if type-of($key) == 'string' {
        $key: get-param($key);
      }

      $smart-config: map-set($smart-config, $key, $value);
    }
  }

  @return $smart-config;
}