import React from 'react';
import objectAssign from 'object-assign';
import DiodeContainerQuery from '../query/DiodeContainerQuery';
import type DiodeQuery from '../query/DiodeQuery';

export type DiodeContainer = {
  query: DiodeContainerQuery,
  displayName: string,
  componentName: string
}

export type DiodeContainerSpec = {
  children?: Array<React.Component>,
  queries?: {
    [key: string]: DiodeQuery
  }
}

type DiodeResponse = {
  [queryType: string]: any
};

type DiodeContainerProps = any;

function createContainerComponent(Component, spec) {
  const componentName = Component.displayName || Component.name;
  const containerName = `Diode(${componentName})`;

  class DiodeContainer extends React.Component {
    constructor(...args) {
      super(...args);
      this.query = spec.query;
    }

    _parseDiodeResponse(diodeResponse: DiodeResponse): DiodeContainerProps {
      const { query } = this;
      return Object.keys(query.map).reduce((props, key) => {
        props[key] = diodeResponse[query.map[key].type];
        return props;
      }, {});
    }

    render() {
      /* eslint no-use-before-define: 0 */
      // see https://github.com/babel/babel-eslint/issues/249
      const { __diodeResponse, ...prop } = this.props;

      // Child container doesn't need to parse diodeResponse again
      // as parent already know what query types the children need,
      // so __diodeResponse will not be passed to child container
      let diodeProps;
      if (__diodeResponse) {
        diodeProps = this._parseDiodeResponse(__diodeResponse);
      }

      return (
        <Component {...prop} {...diodeProps} />
      );
    }
  }

  DiodeContainer.displayName = containerName;
  DiodeContainer.propTypes = {
    __diodeResponse: React.PropTypes.object
  };

  return DiodeContainer;
}

function createContainer(
  Component: React.Component,
  spec: DiodeContainerSpec
): DiodeContainer {
  const componentName = Component.displayName || Component.name;
  const containerName = `Diode(${componentName})`;
  const query = spec.query = new DiodeContainerQuery(spec.queries, spec.children);

  let Container;
  function ContainerConstructor(props, context) {
    if (!Container) {
      Container = createContainerComponent(Component, spec);
    }
    return new Container(props, context);
  }

  ContainerConstructor.setWrapperInfo = function setWrapperInfo(wrapperInfo) {
    objectAssign(spec.wrapperInfo, wrapperInfo);
  };

  ContainerConstructor.getWrapperInfo = function getWrapperInfo(key) {
    return spec.wrapperInfo[key];
  };

  ContainerConstructor.query = query;
  ContainerConstructor.displayName = containerName;
  ContainerConstructor.componentName = componentName;

  return ContainerConstructor;
}

module.exports = {
  create: createContainer
};

@@ -1,12 +1,29 @@
+/**%0A * @flow%0A */%0A
 import React
@@ -150,24 +150,26 @@
 %0Aimport type
+ %7B
  DiodeQuery 
@@ -163,24 +163,26 @@
 %7B DiodeQuery
+ %7D
  from '../qu
@@ -190,21 +190,21 @@
 ry/Diode
-Query
+Types
 ';%0A%0Aexpo
@@ -364,31 +364,30 @@
 : Array%3C
-React.Component
+DiodeContainer
 %3E,%0A  que
@@ -436,95 +436,8 @@
 %0A%7D%0A%0A
-type DiodeResponse = %7B%0A  %5BqueryType: string%5D: any%0A%7D;%0A%0Atype DiodeContainerProps = any;%0A%0A
 func
@@ -746,827 +746,63 @@
     
-_parseDiodeResponse(diodeResponse: DiodeResponse): DiodeContainerProps %7B%0A      const %7B query %7D = this;%0A      return Object.keys(query.map).reduce((props, key) =%3E %7B%0A        props%5Bkey%5D = diodeResponse%5Bquery.map%5Bkey%5D.type%5D;%0A        return props;%0A      %7D, %7B%7D);%0A    %7D%0A%0A    render() %7B%0A      /* eslint no-use-before-define: 0 */%0A      // see https://github.com/babel/babel-eslint/issues/249%0A      const %7B __diodeResponse, ...prop %7D = this.props;%0A%0A      // Child container doesn't need to parse diodeResponse again%0A      // as parent already know what query types the children need,%0A      // so __diodeResponse will not be passed to child container%0A      let diodeProps;%0A      if (__diodeResponse) %7B%0A        diodeProps = this._parseDiodeResponse(__diodeResponse);%0A      %7D%0A%0A      return (%0A        %3CComponent %7B...prop%7D %7B...diodeP
+render() %7B%0A      return (%0A        %3CComponent %7B...this.p
 rops

Remove diodeResponse parsing in DiodeContainer (fix #15)