import React from 'react'
import NestedTableRow from './NestedTableRow'
import NestedTableCol from './NestedTableCol'
import NestedTableCell from './NestedTableCell'
import { TableRow, TableCol, TableSorter } from './data'
import './NestedTable.scss'

class NestedTable extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      expandedRows: {}
    }
  }

  /**
   * NestedTableRow calls this when its expand button is clicked.  This will update our state's hash of hidden values
   * for levels, thus propogating the necessary NestedTableRow components to show/hide accordingly.
   */
  handleExpand (rowId) {
    let state = Object.assign({}, this.state)
    state.expandedRows[rowId] = !state.expandedRows[rowId]
    this.setState(state)
    if (this.props.onExpand !== undefined) {
      this.props.onExpand(rowId)
    }
  }

  generateRowComponents (row, components) {
    // Generate the cell componenets within our row component.
    const cols = this.props.cols.map((col, idx) => {
      return (
        <NestedTableCell
          key={`${row.id}_${col.id}`}
          row={row}
          col={col}
          values={this.props.values}
          sorter={this.props.sorter}
          loading={this.props.loading}
          urlPrefix={this.props.urlPrefix}
          loadedValues={this.props.loadedValues}
        />
      )
    })

    // Generate our row componenet and add it to the list of componenets.
    components.push(
      <NestedTableRow
        key={row.rowId}
        id={row.rowId}
        content={row.content}
        onExpand={row.expands ? (id) => this.handleExpand(id) : null}
        expandedRows={this.state.expandedRows}
        level={row.rowLevel}
        url={row.url}
        childRows={row.children}
      >
        {cols}
      </NestedTableRow>
    )

    // Now handle the row's chidlren if there are any, and add them to the list of componenets if need be.
    if (row.children.length === 0) {
      return
    } else {
      for (let child of row.children) {
        this.generateRowComponents(child, components)
      }
    }
  }

  getRows () {
    const rows = []
    for (let row of this.props.rows) {
      this.generateRowComponents(row, rows)
    }
    return rows
  }

  getCols () {
    return this.props.cols.map((col, idx) => {
      return (
        <NestedTableCol
          key={`col_${idx}`}
          id={col.id}
          onToggleSort={this.props.onSortByCol}
          sorter={this.props.sorter}
          tooltip={col.description}
        >
          {col.name}
        </NestedTableCol>
      )
    })
  }

  render () {
    const cols = this.getCols()
    const rows = this.getRows()
    if (cols.length === 0 || rows.length === 0) {
      return null
    }
    return (
      <div style={{ overflowX:'auto' }}>
        <table className='nested-table'>
          <thead>
            <tr>
              <th />
              {cols}
            </tr>
          </thead>
          <tbody>
            {rows}
          </tbody>
        </table>
      </div>
    )
  }
}

NestedTable.propTypes = {
  rows: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableRow)).isRequired,
  cols: React.PropTypes.arrayOf(React.PropTypes.instanceOf(TableCol)).isRequired,
  sorter: React.PropTypes.instanceOf(TableSorter),
  values: React.PropTypes.object.isRequired,
  loading: React.PropTypes.bool,
  urlPrefix: React.PropTypes.string,
  onSortByCol: React.PropTypes.func,
  onExpand: React.PropTypes.func,
  loadedValues: React.PropTypes.object
}

export default NestedTable
