//////////////////////////////////////////////////////////////
// Copyright (c) 2017 Ben Jackman
// All Rights Reserved
// please contact ben@jackman.biz
// for licensing inquiries
// Created by bjackman @ 6/8/17 3:00 PM
//////////////////////////////////////////////////////////////
import * as React from "react";
import * as _ from "lodash";

function tablify(data: any[]): { keys: string[], rows: any[][] } | null {
  const keys: string[] = []
  const rows: string[][] = []

  try {
    //Keys is first pass
    data.forEach(dr => {
      if (_.isObject(dr)) {
        const ks = _.keys(dr)
        keys.push(...ks.filter(k => !_.includes(keys, k)))
      } else {
        throw new Error("Bad Tacos")
      }
    })

    //Now just use the keys to build out the table
    data.forEach(dr => {
      if (_.isObject(dr)) {
        rows.push(keys.map(k => (dr as any)[k]))
      } else {
        throw new Error("Bad Tacos")
      }
    })

    return {keys, rows}
  } catch (e) {
    return null
  }
}





interface Props<T> {
  data : T[]
}

export class AutoTable<T> extends React.Component<Props<T>, {}> {
  shouldComponentUpdate(nextProps: Readonly<Props<T>>, nextState: Readonly<{}>, nextContext: any): boolean {
    //Should Component Update Called
    const ret = nextProps.data !== this.props.data
    // console.log("shouldComponentUpdate called for AutoTable", ret)
    return ret;
  }

  tableEl = React.createRef<HTMLTableElement>()

  componentDidMount(): void {
    this.tableEl.current!.border = "1"
  }

  render(): JSX.Element {
    const punt = (r: string = "") => {
      console.error("Punting to json Expected an array of objects " + r, this.props.data)
      return <textarea readOnly value={JSON.stringify(this.props.data)} cols={80} rows={20}/>
    }

    function prettify(c: any) {
      if (_.isObject(c) || _.isArray(c)) {
        return JSON.stringify(c)
      } else {
        return ""+c
      }
    }
    if (_.isArray(this.props.data)) {
      const res = tablify(this.props.data)
      if (res == null) {
        return punt("tablify failed")
      } else {
        const {keys, rows} = res
        return <table ref={this.tableEl}>
          <thead>
          <tr>
          {keys.map(k => <th key={k}>{k}</th>)}
          </tr>
          </thead>
          <tbody>
          {rows.map((r, i) => <tr key={i}>{
            r.map((c, i) => <td key={i}>{prettify(c)}</td>)
          }</tr>)}
          </tbody>
        </table>
      }
    } else {
      return punt("not given an array")
    }
  }
}
