import React, {Component, PropTypes} from 'react'
import {GridDiv, BoardLayout, RightPane, CounterDiv} from '../styles/Grid'
import Tile from './Tile'
import update from 'immutability-helper';
import Score from './Score'
import Hint from './Hint'
import FinalPopup from './FinalPopup'
import Generator from '../helpers/generator'
import ReactCountdownClock from 'react-countdown-clock'

export default class Grid extends Component {

  state = {
    showFinalPopup: false,
    grid: undefined,
    curSelectionPos: [],
    curSelectionLetters: [],
    completedSelectionPos: [],
    completedWords: [],
    hintsTaken: 0
  }

  sameRow = (selection, row) => {
    return selection.every((s) => s.row === row)
  }

  componentWillMount() {
    const matrix = Generator.generateGrid(this.words);
    this.setState({grid: matrix, startedAt: new Date()})
  }

  sameCol = (selection, col) => {
    return selection.every((s) => s.col === col)
  }

  areAdjacentTiles = (selection) => {
    for (let i = 0; i < selection.length - 1; i++) {
      if (Math.abs(selection[i] - selection[i + 1]) !== 1) {
        return false
      }
    }
    return true
  }

  get words() {
    return this.props.data.map((w) => w.word)
  }

  adjacentColumn = (selection, newCol) => {
    const selectedCols = selection.map((s) => s.col)
    selectedCols.push(newCol)
    return this.areAdjacentTiles(selectedCols)
  }

  adjacentRow = (selection, newRow) => {
    const selectedRows = selection.map((s) => s.row)
    selectedRows.push(newRow)
    return this.areAdjacentTiles(selectedRows)
  }

  requestedHint = () => {
    this.setState({hintsTaken: this.state.hintsTaken + 1})
  }

  hasCompleted = () => {
    return this.state.completedWords.length === this.words.length
  }

  checkIfPlayerWon = () => {
    if (this.hasCompleted()) {
      this.setState({showFinalPopup: true})
    }
  }

  timeup = () => {
    this.props.updateStats(this.stats())
    this.setState({showFinalPopup: true})
  }

  stats = () => {
    const {completedWords, hintsTaken, startedAt} = this.state
    const stats = {
      completed: this.hasCompleted(),
      score: completedWords.length,
      totalScore: this.words.length,
      completedAt: new Date(),
      ...{hintsTaken, startedAt}
    }
    return stats
  }

  checkIfWordCompleted = () => {
    const {curSelectionPos, curSelectionLetters} = this.state
    const currentWord = curSelectionLetters.join('')
    if (this.words.some((w) => w === currentWord)) {
      this.setState(update(this.state,
        {
          curSelectionPos: {$set: []},
          curSelectionLetters: {$set: []},
          completedSelectionPos: {
            $push: curSelectionPos
          },
          completedWords: {
            $push: [currentWord]
          }
        }), () => {
        this.props.updateStats(this.stats())
        this.checkIfPlayerWon()
      })
    }
  }

  handleSelect = (row, col, letter) => {
    const {curSelectionPos} = this.state
    const firstSelection = curSelectionPos.length === 0

    const adjacentTileSelected = (this.sameRow(curSelectionPos, row) && this.adjacentColumn(curSelectionPos, col)) ||
      (this.sameCol(curSelectionPos, col) && this.adjacentRow(curSelectionPos, row))

    if (firstSelection || adjacentTileSelected) {
      this.setState(update(this.state, {
        curSelectionPos: {
          $push: [{...{row, col}}]
        },
        curSelectionLetters: {
          $push: [letter]
        }
      }), this.checkIfWordCompleted)
    } else {
      this.setState({curSelectionPos: [{row, col}], curSelectionLetters: [letter]})
    }
  }

  render() {
    const {completedWords, grid} = this.state
    return <BoardLayout>
      <GridDiv>
        {
          grid && grid.map((row, i) => {
            return row.map((letter, j) => {
              const id = `${i}${j}`
              const selected = this.state.curSelectionPos.some((sel) => sel.row === i && sel.col === j)
              const completed = this.state.completedSelectionPos.some((sel) => sel.row === i && sel.col === j)
              return <Tile id={id}
                           key={id}
                           letter={letter}
                           selected={selected}
                           completed={completed}
                           row={i}
                           col={j}
                           notifySelect={this.handleSelect}
              />
            })
          })
        }
      </GridDiv>
      <RightPane>
        <Score score={completedWords.length} total={this.words.length}/>
        <Hint allWords={this.props.data} completedWords={completedWords} opened={this.requestedHint}/>
        <FinalPopup show={this.state.showFinalPopup} completed={this.hasCompleted()} onExit={this.props.onExit}/>
        <CounterDiv>
          <ReactCountdownClock seconds={300}
                               color="ivory"
                               alpha={0.9}
                               size={85}
                               weight={10}
                               onComplete={this.timeup}/>
        </CounterDiv>

      </RightPane>
    </BoardLayout>
  }
}

Grid.PropTypes = {
  data: PropTypes.array.isRequired,
  updateStats: PropTypes.func,
  onExit: PropTypes.func
}
@@ -707,16 +707,165 @@
 w)%0A  %7D%0A%0A
+  formattedCurrentTime = () =%3E %7B%0A    const date = new Date()%0A    return new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toJSON();%0A  %7D%0A%0A
   compon
@@ -980,23 +980,40 @@
 rtedAt: 
-new Dat
+this.formattedCurrentTim
 e()%7D)%0A  
@@ -2312,24 +2312,53 @@
 rds.length,%0A
+      started_at: startedAt,%0A
       totalS
@@ -2356,17 +2356,18 @@
    total
-S
+_s
 core: th
@@ -2393,28 +2393,42 @@
     
-completedAt: new Dat
+ended_at: this.formattedCurrentTim
 e(),
@@ -2438,33 +2438,42 @@
     
-...
+metadata: 
 %7Bhints
-T
+_t
 aken
-, startedAt
+: hintsTaken
 %7D%0A  

Add better formatted stats on interaction