let {
  GroupedList,
  IGroup,
  IGroupHeaderProps,
  IGroupFooterProps,
  Link,
  getTheme,
  mergeStyleSets,
  IRawStyle,
  IGroup,
  Fabric
} = window.Fabric;

const theme = getTheme();
const headerAndFooterStyles: IRawStyle = {
  minWidth: 300,
  minHeight: 40,
  lineHeight: 40,
  paddingLeft: 16
};
const classNames = mergeStyleSets({
  header: [headerAndFooterStyles, theme.fonts.xLarge],
  footer: [headerAndFooterStyles, theme.fonts.large],
  name: {
    display: 'inline-block',
    overflow: 'hidden',
    height: 24,
    cursor: 'default',
    padding: 8,
    boxSizing: 'border-box',
    verticalAlign: 'top',
    background: 'none',
    backgroundColor: 'transparent',
    border: 'none',
    paddingLeft: 32
  }
});

class GroupedListCustomExample extends React.Component {
  private _items: IExampleItem[] = createListItems(20);
  private _groups: IGroup[] = createGroups(4, 0, 0, 5);

  public render(): JSX.Element {
    return (
      <GroupedList
        items={this._items}
        onRenderCell={this._onRenderCell}
        groupProps={{
          onRenderHeader: this._onRenderHeader,
          onRenderFooter: this._onRenderFooter
        }}
        groups={this._groups}
      />
    );
  }

  private _onRenderCell(nestingDepth: number, item: IExampleItem, itemIndex: number): JSX.Element {
    return (
      <div data-selection-index={itemIndex}>
        <span className={classNames.name}>{item.name}</span>
      </div>
    );
  }

  private _onRenderHeader(props: IGroupHeaderProps): JSX.Element {
    const toggleCollapse = (): void => {
      props.onToggleCollapse!(props.group!);
    };

    return (
      <div className={classNames.header}>
        This is a custom header for {props.group!.name}
        &nbsp; (<Link onClick={toggleCollapse}>{props.group!.isCollapsed ? 'Expand' : 'Collapse'}</Link>)
      </div>
    );
  }

  private _onRenderFooter(props: IGroupFooterProps): JSX.Element {
    return <div className={classNames.footer}>This is a custom footer for {props.group!.name}</div>;
  }
}

const LOREM_IPSUM = (
  'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut ' +
  'labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut ' +
  'aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore ' +
  'eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt ' +
  'mollit anim id est laborum'
).split(' ');

const DATA = {
  color: ['red', 'blue', 'green', 'yellow'],
  shape: ['circle', 'square', 'triangle'],
  location: ['Seattle', 'New York', 'Chicago', 'Los Angeles', 'Portland']
};

interface IExampleItem {
  thumbnail: string;
  key: string;
  name: string;
  description: string;
  color: string;
  shape: string;
  location: string;
  width: number;
  height: number;
}

function createListItems(count: number, startIndex: number = 0): IExampleItem[] {
  return Array.apply(null, Array(count)).map((item: number, index: number) => {
    const size = 150 + Math.round(Math.random() * 100);

    return {
      thumbnail: `//placehold.it/${size}x${size}`,
      key: 'item-' + (index + startIndex) + ' ' + lorem(4),
      name: lorem(5),
      description: lorem(10 + Math.round(Math.random() * 50)),
      color: _randWord(DATA.color),
      shape: _randWord(DATA.shape),
      location: _randWord(DATA.location),
      width: size,
      height: size
    };
  });
}

function createGroups(
  groupCount: number,
  groupDepth: number,
  startIndex: number,
  itemsPerGroup: number,
  level: number = 0,
  key: string = '',
  isCollapsed?: boolean
): IGroup[] {
  if (key !== '') {
    key = key + '-';
  }
  const count = Math.pow(itemsPerGroup, groupDepth);
  return Array.apply(null, Array(groupCount)).map((value: number, index: number) => {
    return {
      count: count,
      key: 'group' + key + index,
      name: 'group ' + key + index,
      startIndex: index * count + startIndex,
      level: level,
      isCollapsed: isCollapsed,
      children:
        groupDepth > 1
          ? createGroups(groupCount, groupDepth - 1, index * count + startIndex, itemsPerGroup, level + 1, key + index)
          : []
    };
  });
}

function lorem(wordCount: number): string {
  return Array.apply(null, Array(wordCount))
    .map((item: number, idx: number) => {
      return LOREM_IPSUM[idx % LOREM_IPSUM.length];
    })
    .join(' ');
}

function isGroupable(key: string): boolean {
  return key === 'color' || key === 'shape' || key === 'location';
}

function _randWord(array: string[]): string {
  const index = Math.floor(Math.random() * array.length);
  return array[index];
}

ReactDOM.render(<GroupedListCustomExample />, document.getElementById('content'));
