import { OjListViewBase } from './OjListViewBase';
import { slotProxy, SlotProxy } from '../../';
import { By, WebElement } from 'selenium-webdriver';
import { executeWithModules } from '../../lib/oj-module-proxy';

/**
 * The component WebElement for [oj-list-view](../../jsdocs/oj.ojListView.html).
 * Do not instantiate this class directly, instead, use
 * [ojListView](../functions/elements.ojListView-1.html).
 */
export class OjListView extends OjListViewBase {
  /**
   * Sets the value of "selected" property.
   * Specifies the current selected items in the listview. See the Help documentation for more information.
   * @param selected The value to set for "selected"
   * @override
   * @typeparam K Type of keys
   */
  async changeSelected<K>(selected: Array<K>) {
    await this.whenReady();
    return executeWithModules(
      this.getDriver(),
      ['KeySet'],
      [this, selected],
      ({ KeySetImpl }, ele, selected) => {
        ele.selected = new KeySetImpl(selected);
      }
    );
  }

  /**
   * Gets the value of "selected" property.
   * Retrieves the current selected items in the listview. See the Help documentation for more information.
   * @override
   * @typeparam K Type of keys
   * @return The value of "selected" property.
   */
  async getSelected<K>(): Promise<Array<K>> {
    await this.whenReady();
    const selected: Array<K> = await this.getDriver().executeScript((ele: any) => {
      return Array.from(ele.selected.values());
    }, this);
    return selected;
  }

  /**
   * Retrieve a SlotProxy which represents a single listview item.
   * @param key The key within the Collection's dataset associated with the item.
   */
  async findItem<T>(itemLocator: { key: T }): Promise<SlotProxy> {
    // explicitly override scrollToKey to ensure changeScrollPosition regardless
    // of DataProvider or existing scrollToKey value
    await this.setProperty('scrollToKey', 'always');
    // Call changeScrollPosition to scroll the row into view and ensure it's
    // rendere in DOM
    // TODO: Base class should mark position properties as optional
    // @ts-ignore
    await this.changeScrollPosition({
      key: itemLocator.key
    });
    await this.whenBusyContextReady();
    const display = await this.getProperty('display');
    let el = await this.getDriver().executeScript<WebElement>(
      (ele: any, key: T) => ele.getNodeBySubId({ subId: 'oj-listview-item', key }),
      this,
      itemLocator.key
    );
    if (display === 'list') {
      el = el.findElement(By.css('[role="gridcell"]'));
    }
    return slotProxy(el, this);
  }
}
