import { Command, getRangeFromMatrix, flatten } from 'substance'
import { generateTable } from '../shared/tableHelpers'
import InsertNodeCommand from './InsertNodeCommand'

const DISABLED = { disabled: true }

export class InsertTableCommand extends InsertNodeCommand {
  createNode (tx, params) {
    let tableWrap = tx.createElement('table-wrap')
    tableWrap.append(
      tx.createElement('object-id').text(tableWrap.id),
      tx.createElement('title').text('Table title'),
      tx.createElement('caption').append(
        tx.createElement('p').text('Table caption')
      ),
      this.generateTable(tx, params.rows, params.columns)
    )
    return tableWrap
  }

  generateTable (tx, nrows, ncols) {
    return generateTable(tx, nrows, ncols)
  }
}

class BasicTableCommand extends Command {
  getCommandState (params, context) { // eslint-disable-line no-unused-vars
    const tableApi = context.api.getTableAPI()
    if (!tableApi.isTableSelected()) return DISABLED
    const selData = tableApi._getSelectionData()
    return Object.assign({ disabled: false }, selData)
  }

  execute (params, context) { // eslint-disable-line no-unused-vars
    const commandState = params.commandState
    if (commandState.disabled) return

    const tableApi = context.api.getTableAPI()
    return this._execute(tableApi, commandState)
  }
}

export class InsertCellsCommand extends BasicTableCommand {
  _execute (tableApi, { ncols, nrows }) {
    const mode = this.config.spec.pos
    const dim = this.config.spec.dim
    if (dim === 'row') {
      tableApi.insertRows(mode, nrows)
    } else {
      tableApi.insertCols(mode, ncols)
    }
    return true
  }
}

export class DeleteCellsCommand extends BasicTableCommand {
  _execute (tableApi, { startRow, startCol, nrows, ncols }) {
    const dim = this.config.spec.dim
    if (dim === 'row') {
      tableApi.deleteRows()
    } else {
      tableApi.deleteCols()
    }
    return true
  }
}

export class TableSelectAllCommand extends BasicTableCommand {
  _execute (tableApi) {
    tableApi.selectAll()
    return true
  }
}

export class ToggleCellHeadingCommand extends BasicTableCommand {
  getCommandState (params, context) { // eslint-disable-line no-unused-vars
    let commandState = super.getCommandState(params, context)
    if (commandState.disabled) return commandState

    let { table, startRow, endRow, startCol, endCol } = commandState
    let cells = getRangeFromMatrix(table.getCellMatrix(), startRow, startCol, endRow, endCol, true)
    cells = flatten(cells).filter(c => !c.shadowed)
    let onlyHeadings = true
    for (let i = 0; i < cells.length; i++) {
      if (!cells[i].getAttribute('heading')) {
        onlyHeadings = false
        break
      }
    }
    return Object.assign(commandState, {
      active: onlyHeadings,
      cellIds: cells.map(c => c.id)
    })
  }

  _execute (tableApi, { cellIds, heading }) {
    tableApi.toggleHeading(cellIds)
    return true
  }
}

export class ToggleCellMergeCommand extends BasicTableCommand {
  getCommandState (params, context) { // eslint-disable-line no-unused-vars
    let commandState = super.getCommandState(params, context)
    if (commandState.disabled) return commandState

    let { table, nrows, ncols, startRow, startCol } = commandState
    let cell = table.getCell(startRow, startCol)
    let rowspan = cell.rowspan
    let colspan = cell.colspan
    // ATTENTION: at the moment the selection is expressed in absolute
    // rows and cols, not considering colspans and rowspans
    // If a single cell with row- or colspan is selected, then
    // nrows=rowspan and ncols=colspan
    if (nrows > 1 || ncols > 1) {
      if (rowspan < nrows || colspan < ncols) {
        commandState.merge = true
      } else {
        commandState.active = true
        commandState.unmerge = true
      }
    }
    // only enable if one merge option is enabled
    // TODO: if table commands are enabled this command should
    // be shown even if disabled
    if (!commandState.merge && !commandState.unmerge) {
      return DISABLED
    }
    return commandState
  }

  _execute (tableApi, { merge, unmerge }) {
    if (merge) {
      tableApi.merge()
    } else if (unmerge) {
      tableApi.unmerge()
    }
    return true
  }
}

@@ -299,25 +299,23 @@
     let 
-tableWrap
+caption
  = tx.cr
@@ -331,34 +331,17 @@
 nt('
-table-wrap')%0A    tableWrap
+caption')
 .app
@@ -373,259 +373,304 @@
 nt('
-object-id').text(tableWrap.id),%0A      tx.createElement('title').text('Table title'),%0A      tx.createElement('caption').append(%0A        tx.createElement('p').text('Table caption')%0A      ),%0A      this.generateTable(tx, params.rows, params.columns)
+p')%0A    )%0A    let permission = tx.create(%7B%0A      type: 'permission'%0A    %7D)%0A    let table = this.generateTable(tx, params.rows, params.columns)%0A    let tableFigure = tx.create(%7B%0A      type: 'table-figure',%0A      caption: caption.id,%0A      content: table.id,%0A      permission: permission.id
 %0A    
-)
+%7D)%0A
 %0A   
@@ -686,12 +686,14 @@
 able
-Wrap
+Figure
 %0A  %7D

Insert table-figure instead of table-wrap.