/**
 * Copyright Schrodinger, LLC
 *
 * @fileoverview Dropdown picker
 */
import React, { PureComponent } from 'react'
import { SelectOption } from './types'
import clsx from 'clsx'
import styles from './styles.module.scss'

export class Option extends PureComponent<Props> {

  static defaultProps = {
    search: '',
  }

  render(): JSX.Element {
    const classes = clsx(this.props.className, {
      [styles.disabled]: this.props.disabled,
    })

    return (
      <li className={classes} onClick={this.props.disabled ? undefined : this.onClick}>
        <span title={this.props.value}>
          {this.renderValue()}
        </span>
      </li>
    )
  }

  renderValue(): string | Array<(JSX.Element|string|null)> {
    const { search, value } = this.props
    const terms = search.toLowerCase().trim()

    if (terms === '' || value.toLowerCase().indexOf(terms) < 0) {
      return this.props.value
    }

    // We need to sanitize special regex chars from the user input
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
    const escapedTerms = terms.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    const parts = value.split(new RegExp(`(${escapedTerms})`, 'ig'))

    return parts.map((part, idx) => {
      if (part.trim() === '') {
        return null
      }
      if (part.toLowerCase() === terms) {
        return (
          <span className={styles['highlighted']} key={`${part}-${idx}`}>
            {part}
          </span>
        )
      }
      return part
    })
  }

  onClick = (): void => {
    this.props.onClick(this.props.optionKey)
  }
}

/**
 * Props
 */
export interface Props {
  /**
   * Option's internal value (id)
   */
  optionKey: SelectOption['key']

  /**
   * Option's display value
   */
  value: SelectOption['value']

  /**
   * onClick event handler
   */
  onClick: (key: SelectOption['key']) => void

  /**
   * Extra classes for the list item
   */
  className?: string

  /**
   * Search filter (if any), used to highlight matches
   */
  search: string

  /**
   * Option is disabled
   */
  disabled?: boolean
}
