import React from 'react';
import generateEntityId from 'utils/entities';
import { quoteService } from '../../../services';
import classnames from 'classnames';
import PriceFlasher from 'components/ui/PriceFlasher';
import { numberShorthand, numberPercent } from 'utils/formatters';
import { openSecurity } from 'actions/workspaces';
import includes from 'lodash/includes';
import map from 'lodash/map';

export default class WatchlistTable extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sortColumn: 'symbol',
      sortOrder: -1
    };
    this.entityId = generateEntityId();
  }
  componentWillMount() {
    // loop through symbols
    this.props.symbols.forEach(symbol =>
      quoteService.addSubscriber(this.entityId, {symbol}, this.updateQuotes.bind(this))
    );
  }
  componentWillReceiveProps(nextProps) {
    if (nextProps.symbols !== this.props.symbols) {
      // Unsubscribe to current ones that will be removed
      this.props.symbols.filterNot((s) => nextProps.symbols.contains(s)).forEach(symbol =>
        quoteService.removeSubscriber(this.entityId, {symbol})
      );
      // Subscribe to new ones that need to be added
      nextProps.symbols.filterNot((s) => this.props.symbols.contains(s)).forEach(symbol =>
        quoteService.addSubscriber(this.entityId, {symbol}, this.updateQuotes.bind(this))
      );
    }
  }
  componentWillUnmount() {
    this.props.symbols.forEach(symbol =>
      quoteService.removeSubscriber(this.entityId, {symbol})
    );
  }
  getSortOrder() {
    const sortOrder = this.props.symbols.sortBy(symbol => {
      const quote = quoteService.getTicker(symbol);
      if (includes(['askPrice', 'bidPrice', 'price', 'percentChange', 'nominalChange', 'volume', 'dayHigh', 'dayLow', 'yearHigh', 'yearLow'], this.state.sortColumn)) {
        if (!quote) {
          return 0;
        }
        return parseFloat(quote.get(this.state.sortColumn));
      }
      if (this.state.sortColumn === 'company') {
        return quote.get('companyName').toUpperCase();
      }
      return symbol;
    }).toJS();

    if (this.state.sortOrder === -1) {
      return sortOrder.reverse();
    }
    return sortOrder;
  }
  getSortIcon(column) {
    let icon = null;

    if (column === this.state.sortColumn) {
      if (this.state.sortOrder === 1) {
        icon = (<i className="bzpro-icon-dropup"></i>);
      } else {
        icon = (<i className="bzpro-icon-dropdown"></i>);
      }
    }
    return icon;
  }
  changeSortOrder(column) {
    return (event) => {
      if (this.state.sortColumn === column) {
        if (this.state.sortOrder === 1) {
          this.setState({sortOrder: -1});
        } else if (this.state.sortOrder === -1) {
          this.setState({sortOrder: 0, sortColumn: null});
        }
      } else {
        this.setState({sortColumn: column, sortOrder: 1});
      }

      bzTrack.track('Watchlist: Table Change Sort Order', {
        column: column,
        order: this.state.sortOrder === 1 ? -1 : 0
      });
    };
  }

  updateQuotes() {
    this.forceUpdate();
  }

  clickSymbol(symbol) {
    openSecurity(symbol);
    bzTrack.track('Watchlist: Table Open Security Widget', {symbol});
  }

  renderHeader(colName, i) {
    const { display } = this.props;
    const prop = display[colName];
    let alignClass;

    if (prop.visible) {
      if (colName === 'symbol' || colName === 'company') {
        alignClass = 'u-alignLeft';
      }
      return (<th className={alignClass} key={i}><span onClick={this.changeSortOrder(colName)}>{prop.name} {this.getSortIcon(colName)}</span></th>);
    }

    return null;
  }

  renderCell(prop, cellData) {
    return prop.visible ? cellData : null;
  }

  render() {
    const columns = [ 'symbol', 'company', 'price', 'bidPrice', 'askPrice',
                      'nominalChange', 'percentChange', 'yearHigh', 'yearLow',
                      'dayHigh', 'dayLow', 'volume' ];
    const { symbol, company, price, bidPrice, askPrice, nominalChange,
            percentChange, yearHigh, yearLow, dayHigh, dayLow, volume } = this.props.display;

    return (
      <table className="Watchlist-data">
        <thead>
          <tr>
            {columns.map((v, i) => this.renderHeader(v, i))}
            <th></th>
          </tr>
        </thead>
        <tbody>
          {map(this.getSortOrder(), (symbolName) => {
            const quote = quoteService.getTicker(symbolName) || {};
            const changeClass = classnames({'u-upText': quote.nominalChange > 0, 'u-downText': quote.nominalChange < 0});
            return (
              <tr key={symbolName}>
                {this.renderCell(symbol, <td className="Watchlist-symbol u-alignLeft" onClick={() => this.clickSymbol(symbolName)}>{symbolName}</td>)}
                {this.renderCell(company, <td className="u-alignLeft" >{quote.companyName}</td>)}
                {this.renderCell(price, <PriceFlasher price={quote.price}/>)}
                {this.renderCell(bidPrice, <PriceFlasher price={quote.bidPrice}/>)}
                {this.renderCell(askPrice, <PriceFlasher price={quote.askPrice}/>)}
                {this.renderCell(nominalChange, <td className={changeClass}>{quote.nominalChange || '- -'}</td>)}
                {this.renderCell(percentChange, <td className={changeClass}>{numberPercent(quote.percentChange, false)}</td>)}
                {this.renderCell(yearHigh, <td>{quote.fiftyTwoWeekHigh || '- -'}</td>)}
                {this.renderCell(yearLow, <td>{quote.fiftyTwoWeekLow || '- -'}</td>)}
                {this.renderCell(dayHigh, <td>{quote.dayHigh || '- -'}</td>)}
                {this.renderCell(dayLow, <td>{quote.dayLow || '- -'}</td>)}
                {this.renderCell(volume, <td><span>{numberShorthand(quote.volume)}</span></td>)}
                <td>
                  <button className="Watchlist-removeSymbol" onClick={this.props.removeSymbol(symbolName)}>
                    <i className="bzpro-icon-close"></i>
                  </button>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    );
  }
}

WatchlistTable.propTypes = {
  symbols: React.PropTypes.object,
  removeSymbol: React.PropTypes.func,
  display: React.PropTypes.object
};
