import React, { memo, useState, useEffect, useRef } from 'react';
import Modal from 'react-modal';
import { useSelector, useDispatch } from 'react-redux';
import { FiUsers, FiX } from 'react-icons/fi';
import useModal from 'components/modals/useModal';
import Button from 'components/ui/Button';
import { join } from 'state/channels';
import { select } from 'state/tab';
import { searchChannels } from 'state/channelSearch';
import { linkify } from 'utils';

const Channel = memo(({ server, name, topic, userCount, joined }) => {
  const dispatch = useDispatch();

  const handleClick = () => dispatch(join([name], server));

  return (
    <div className="modal-channel-result">
      <div className="modal-channel-result-header">
        <h2 className="modal-channel-name" onClick={handleClick}>
          {name}
        </h2>
        <FiUsers />
        <span className="modal-channel-users">{userCount}</span>
        {joined ? (
          <span style={{ color: '#6bb758' }}>Joined</span>
        ) : (
          <Button
            className="modal-channel-button-join"
            category="normal"
            onClick={handleClick}
          >
            Join
          </Button>
        )}
      </div>
      <p className="modal-channel-topic">{linkify(topic)}</p>
    </div>
  );
});

const AddChannel = () => {
  const [modal, server, closeModal] = useModal('channel');

  const channels = useSelector(state => state.channels);
  const search = useSelector(state => state.channelSearch);
  const dispatch = useDispatch();
  const [q, setQ] = useState('');

  const inputEl = useRef();
  const resultsEl = useRef();
  const prevSearch = useRef('');

  useEffect(() => {
    if (modal.isOpen) {
      dispatch(searchChannels(server, ''));
      setTimeout(() => inputEl.current.focus(), 0);
    } else {
      prevSearch.current = '';
      setQ('');
    }
  }, [modal.isOpen]);

  const handleSearch = e => {
    let nextQ = e.target.value.trim().toLowerCase();
    setQ(nextQ);

    if (nextQ !== q) {
      resultsEl.current.scrollTop = 0;

      while (nextQ.charAt(0) === '#') {
        nextQ = nextQ.slice(1);
      }

      if (nextQ !== prevSearch.current) {
        prevSearch.current = nextQ;
        dispatch(searchChannels(server, nextQ));
      }
    }
  };

  const handleKey = e => {
    if (e.key === 'Enter') {
      let channel = e.target.value.trim();

      if (channel !== '') {
        closeModal(false);

        if (channel.charAt(0) !== '#') {
          channel = `#${channel}`;
        }

        dispatch(join([channel], server));
        dispatch(select(server, channel));
      }
    }
  };

  const handleLoadMore = () =>
    dispatch(searchChannels(server, q, search.results.length));

  let hasMore = !search.end;
  if (hasMore) {
    if (search.results.length < 10) {
      hasMore = false;
    } else if (
      search.results.length > 10 &&
      (search.results.length - 10) % 50 !== 0
    ) {
      hasMore = false;
    }
  }

  return (
    <Modal {...modal}>
      <div className="modal-channel-input-wrap">
        <input
          ref={inputEl}
          type="text"
          value={q}
          placeholder="Enter channel name"
          onKeyDown={handleKey}
          onChange={handleSearch}
        />
        <Button
          icon={FiX}
          className="modal-close modal-channel-close"
          onClick={closeModal}
        />
      </div>
      <div ref={resultsEl} className="modal-channel-results">
        {search.results.map(channel => (
          <Channel
            key={`${server} ${channel.name}`}
            server={server}
            joined={channels[server]?.[channel.name]?.joined}
            {...channel}
          />
        ))}
        {hasMore && (
          <Button
            className="modal-channel-button-more"
            onClick={handleLoadMore}
          >
            Load more
          </Button>
        )}
      </div>
    </Modal>
  );
};

export default AddChannel;