import React from 'react';
import Graph from './Graph.jsx';
import logo from '../assets/logo.svg';
const cloneDeep = require('lodash.clonedeep');

// const formatted = require('../../formattedDataNoState');




class App extends React.Component {
  constructor() {
    super();
    this.state = {};
    this.treebuilder = this.treebuilder.bind(this);
  }

  componentWillMount() {
    return this.setState(this.props.store);
  }
  

  componentWillReceiveProps(nextProps) {
    const result = {};
    for (const key in nextProps.store) {
      if (this.props.store.hasOwnProperty(key)) {
        result[key] = Object.assign({}, this.state[key], nextProps.store[key]);
      } else {
        result[key] = nextProps.store[key];
      }
    }
    this.setState(Object.assign({}, this.state, result));
  }

  treebuilder(state) {
    const result = cloneDeep(formatted[formatted.monocleENTRY]);
    const bfs = this.bfs;

    function treeRecurse(node, root, newState) {
      if (!node.children) throw new Error('Invalid Node! Something went wrong with the parsing (no children array)');
      if (newState[node.name]) node.state = cloneDeep(newState[node.name]);

      if (node.children.length === 0) return; // base case
      const tempChildren = [];

      // iterating through children
      for (let j = 0; j < node.children.length; j++) {
        const child = cloneDeep(node.children[j]);

        // maybe check if it is object already
        if (formatted.hasOwnProperty(child.name)) child.children = cloneDeep(formatted[child.name].children); // adding children of child


        if (!Array.isArray(child.props)) {
          tempChildren.push(child);
          continue;
        }


        // if child is not made through an iterator
        if (!child.iterated) {
          const propsObj = {};

          // iterating through props to parse
          child.props.forEach(ele => {
            // if it has a prop or state find source and parse
            if (typeof ele.value === 'string' && ele.value.search(/(^props.|^state.)/) !== -1) {
              propsObj[ele.name] = eval(`node.${ele.value}`);
            } else propsObj[ele.name] = ele.value; // else just return the value
          });
          child.props = propsObj;
          tempChildren.push(child);

          // if it is made through an iterator
        } else {
          switch (child.iterated) {
            case 'forIn':
              for (const key in eval(`node.${child.source}`)) {
                const forInChild = cloneDeep(child);
                const propsObj = {};

                forInChild.props.forEach(ele => {
                  if (typeof ele.value === 'string' && ele.value.search(/(^props.|^state.)/) !== -1) {
                    propsObj[ele.name] = eval(`node.${ele.value}`);
                  } else if (ele.value.includes(key) && ele.value.search(/\wkey\w/) === -1) propsObj[ele.name] = ele.value.replace('key', key);
                  else propsObj[ele.name] = ele.value;
                });

                forInChild.props = propsObj;
                tempChildren.push(forInChild);
              }
              break;

            case 'forLoop':
              for (var i = 0; i < eval(`node.${child.source}.length`); i++) {
                const num = i;
                const forLoopChild = cloneDeep(child);
                const propsObj = {};

                forLoopChild.props.forEach(ele => {
                  if (typeof ele.value === 'string' && ele.value.search(/(^props.|^state.)/) !== -1) {
                    propsObj[ele.name] = eval(`node.${ele.value}`);
                  } else if (ele.value.includes('i') && ele.value.search(/\wi\w/) === -1) propsObj[ele.name] = ele.value.replace('i', i);
                  else propsObj[ele.name] = ele.value;
                });

                forLoopChild.props = propsObj;
                forLoopChild.num = num;
                tempChildren.push(forLoopChild);
              }
              break;

            case 'higherOrder':
              for (var i = 0; i < eval(`node.${child.source}.length`); i++) {
                const num = i;
                const forLoopChild = cloneDeep(child);
                const propsObj = {};

                forLoopChild.props.forEach(ele => {
                  if (typeof ele.value === 'string' && ele.value.search(/(^props.|^state.)/) !== -1) {
                    propsObj[ele.name] = eval(`node.${ele.value}`);
                  } else if (ele.value.includes('i') && ele.value.search(/\wi\w/) === -1) propsObj[ele.name] = ele.value.replace('i', i);
                  else propsObj[ele.name] = ele.value;
                });
                
                forLoopChild.props = propsObj;
                forLoopChild.num = num;
                tempChildren.push(forLoopChild);
              }
              break;

            default:
              throw new Error('unrecognized iterator');
          }
        }
      }
      node.children = tempChildren;
      node.children.forEach(ele => {
        treeRecurse(ele, root, state);
      });
    }

    treeRecurse(result, result, state);
    return result;
  }

  render() {
    const builtObj = this.treebuilder(this.state);
    const logoStyle = {
      width: '200px',
      height: '100px',
      zIndex: '1',
      position: 'absolute',
    };
    return (
      <div>
        <div style={logoStyle} dangerouslySetInnerHTML={{ __html: logo }} />
        <Graph treeData={builtObj} />
      </div>
    );
  }
}

App.propTypes = {
  store: React.PropTypes.object.isRequired,
};

App.defaultProps = {
  store: {},
};


export default App;
