whole_func_string: function moveGroup(state, action) {
    const place_at = getLayerIndexById(state.layers, action.placeAt);
    const n_layers = state.layers.length;
  
    // sanity check the new index.
    if (place_at < 0 || place_at > n_layers) {
      return state;
    }
  
    // find the starting and ending points of the group
    let group_start = null;
    let group_end = null;
    for (let i = 0, ii = n_layers; i < ii; i++) {
      const group = getGroup(state.layers[i]);
      if (group === action.group) {
        if (group_start === null || i < group_start) {
          group_start = i;
        }
        if (group_end === null || i > group_end) {
          group_end = i;
        }
      }
    }
  
  
    // get the real index of the next spot for the group,
    // if the placeAt index is mid group then place_at should
    // be the index of the FIRST member of that group.
    let place_start = place_at;
    const place_group = getGroup(state.layers[place_at]);
    const place_ahead = (place_at > group_start);
  
    // when placing a group before or after another group
    // the bounds of the target group needs to be found and the
    // appropriate index chosen based on the direction of placement.
    if (place_group) {
      let new_place = -1;
      if (place_ahead) {
        for (let i = n_layers - 1; i >= 0 && new_place < 0; i--) {
          if (getGroup(state.layers[i]) === place_group) {
            new_place = i;
          }
        }
      } else {
        for (let i = 0, ii = n_layers; i < ii && new_place < 0; i++) {
          if (getGroup(state.layers[i]) === place_group) {
            new_place = i;
          }
        }
      }
      place_start = new_place;
    }
  
    // build a new array for the layers.
    let new_layers = [];
  
    // have the group layers ready to concat.
    const group_layers = state.layers.slice(group_start, group_end + 1);
  
    for (let i = 0, ii = n_layers; i < ii; i++) {
      const layer = state.layers[i];
      const in_group = (getGroup(layer) === action.group);
  
      if (place_ahead && !in_group) {
        new_layers.push(layer);
      }
      if (i === place_start) {
        new_layers = new_layers.concat(group_layers);
      }
      if (!place_ahead && !in_group) {
        new_layers.push(layer);
      }
    }
  
    return Object.assign({}, state, {
      layers: new_layers,
    }, incrementVersion(state.metadata, LAYER_VERSION_KEY));
  }
func_code_string: function moveGroup(state, action) {
    const place_at = getLayerIndexById(state.layers, action.placeAt);
    const n_layers = state.layers.length;
  
    // sanity check the new index.
    if (place_at < 0 || place_at > n_layers) {
      return state;
    }
  
    // find the starting and ending points of the group
    let group_start = null;
    let group_end = null;
    for (let i = 0, ii = n_layers; i < ii; i++) {
      const group = getGroup(state.layers[i]);
      if (group === action.group) {
        if (group_start === null || i < group_start) {
          group_start = i;
        }
        if (group_end === null || i > group_end) {
          group_end = i;
        }
      }
    }
  
  
    // get the real index of the next spot for the group,
    // if the placeAt index is mid group then place_at should
    // be the index of the FIRST member of that group.
    let place_start = place_at;
    const place_group = getGroup(state.layers[place_at]);
    const place_ahead = (place_at > group_start);
  
    // when placing a group before or after another group
    // the bounds of the target group needs to be found and the
    // appropriate index chosen based on the direction of placement.
    if (place_group) {
      let new_place = -1;
      if (place_ahead) {
        for (let i = n_layers - 1; i >= 0 && new_place < 0; i--) {
          if (getGroup(state.layers[i]) === place_group) {
            new_place = i;
          }
        }
      } else {
        for (let i = 0, ii = n_layers; i < ii && new_place < 0; i++) {
          if (getGroup(state.layers[i]) === place_group) {
            new_place = i;
          }
        }
      }
      place_start = new_place;
    }
  
    // build a new array for the layers.
    let new_layers = [];
  
    // have the group layers ready to concat.
    const group_layers = state.layers.slice(group_start, group_end + 1);
  
    for (let i = 0, ii = n_layers; i < ii; i++) {
      const layer = state.layers[i];
      const in_group = (getGroup(layer) === action.group);
  
      if (place_ahead && !in_group) {
        new_layers.push(layer);
      }
      if (i === place_start) {
        new_layers = new_layers.concat(group_layers);
      }
      if (!place_ahead && !in_group) {
        new_layers.push(layer);
      }
    }
  
    return Object.assign({}, state, {
      layers: new_layers,
    }, incrementVersion(state.metadata, LAYER_VERSION_KEY));
  }
func_documentation_string: Move a group relative to another group.
  
  @param {Object} state Current state.
  @param {Object} action Action to handle.
  
  @returns {Object} The new state.