// @flow
import * as PAGES from 'constants/pages';
import * as ICONS from 'constants/icons';
import React, { useEffect, useMemo } from 'react';
import Button from 'component/button';
import ClaimList from 'component/claimList';
import ClaimPreview from 'component/claimPreview';
import Page from 'component/page';
import Paginate from 'component/common/paginate';
import { PAGE_PARAM, PAGE_SIZE_PARAM } from 'constants/claim';
import Spinner from 'component/spinner';
import Yrbl from 'component/yrbl';
import { FormField, Form } from 'component/common/form';
import Icon from 'component/common/icon';
import debounce from 'util/debounce';
import classnames from 'classnames';

const FILTER_ALL = 'stream,repost';
const FILTER_UPLOADS = 'stream';
const FILTER_REPOSTS = 'repost';
const PAGINATE_PARAM = 'page';

type Props = {
  checkPendingPublishes: () => void,
  clearPublish: () => void,
  fetching: boolean,
  history: { replace: (string) => void, push: (string) => void },
  page: number,
  pageSize: number,
  myClaims: any,
  fetchAllMyClaims: () => void,
  location: { search: string },
  initialSearchTerm: string,
};

function FileListPublished(props: Props) {
  const {
    checkPendingPublishes,
    clearPublish,
    fetching,
    page,
    pageSize,
    myClaims,
    fetchAllMyClaims,
    location,
    history,
    initialSearchTerm,
  } = props;

  const [filterBy, setFilterBy] = React.useState(FILTER_ALL);
  const [searchText, setSearchText] = React.useState(initialSearchTerm);
  const [filteredClaims, setFilteredClaims] = React.useState([]);
  const { search } = location;
  const params = {};

  params[PAGE_PARAM] = Number(page);
  params[PAGE_SIZE_PARAM] = Number(pageSize);

  const paramsString = JSON.stringify(params);

  const doFilterClaims = () => {
    if (fetching) {
      return;
    }
    const filtered = myClaims.filter((claim) => {
      const value = claim.value || {};
      const src = value.source || {};
      const title = (value.title || '').toLowerCase();
      const description = (value.description || '').toLowerCase();
      const tags = (value.tags || []).join('').toLowerCase();
      const srcName = (src.name || '').toLowerCase();
      const lowerCaseSearchText = searchText.toLowerCase();
      const textMatches =
        !searchText ||
        title.indexOf(lowerCaseSearchText) !== -1 ||
        description.indexOf(lowerCaseSearchText) !== -1 ||
        tags.indexOf(lowerCaseSearchText) !== -1 ||
        srcName.indexOf(lowerCaseSearchText) !== -1;
      return textMatches && filterBy.includes(claim.value_type);
    });
    setFilteredClaims(filtered);
  };

  const debounceFilter = debounce(doFilterClaims, 200);

  useEffect(() => {
    checkPendingPublishes();
  }, [checkPendingPublishes]);

  useEffect(() => {
    const params = new URLSearchParams(search);
    params.set('searchText', searchText);
    history.replace('?' + params.toString());
    debounceFilter();
  }, [myClaims, searchText]);

  useEffect(() => {
    doFilterClaims();
  }, [myClaims, filterBy]);

  const urlTotal = filteredClaims.length;

  const urls = useMemo(() => {
    const params = JSON.parse(paramsString);
    const zeroIndexPage = Math.max(0, params.page - 1);
    const paginated = filteredClaims.slice(
      zeroIndexPage * params.page_size,
      zeroIndexPage * params.page_size + params.page_size
    );
    return paginated.map((claim) => claim.permanent_url);
  }, [filteredClaims, paramsString]);

  // Go back to the first page when the filtered claims change.
  // This way, we avoid hiding results just because the
  // user may be on a different page (page that was calculated
  // using a different state, ie, different filtered claims)
  useEffect(() => {
    const params = new URLSearchParams(search);
    params.set(PAGINATE_PARAM, '1');
    history.replace('?' + params.toString());
  }, [filteredClaims]);

  useEffect(() => {
    fetchAllMyClaims();
  }, [fetchAllMyClaims]);

  return (
    <Page>
      <div className="card-stack">
        {!!urls && (
          <>
            <ClaimList
              noEmpty
              header={
                <span>
                  <Button
                    label={__('All')}
                    aria-label={__('All uploads')}
                    onClick={() => setFilterBy(FILTER_ALL)}
                    className={classnames(`button-toggle`, {
                      'button-toggle--active': filterBy === FILTER_ALL,
                    })}
                  />
                  <Button
                    label={__('Uploads')}
                    onClick={() => setFilterBy(FILTER_UPLOADS)}
                    className={classnames(`button-toggle`, {
                      'button-toggle--active': filterBy === FILTER_UPLOADS,
                    })}
                  />
                  <Button
                    label={__('Reposts')}
                    onClick={() => {
                      setFilterBy(FILTER_REPOSTS);
                      setSearchText('');
                    }}
                    className={classnames(`button-toggle`, {
                      'button-toggle--active': filterBy === FILTER_REPOSTS,
                    })}
                  />
                </span>
              }
              headerAltControls={
                <div className="card__actions--inline">
                  <Button
                    button="secondary"
                    label={__('Refresh')}
                    icon={ICONS.REFRESH}
                    disabled={fetching}
                    onClick={fetchAllMyClaims}
                  />
                  <Button
                    icon={ICONS.PUBLISH}
                    button="primary"
                    label={__('Upload')}
                    navigate={`/$/${PAGES.UPLOAD}`}
                    onClick={() => clearPublish()}
                  />
                  <Form onSubmit={() => {}} className="wunderbar--inline">
                    <Icon icon={ICONS.SEARCH} />
                    <FormField
                      className="wunderbar__input--inline"
                      value={searchText}
                      onChange={(e) => setSearchText(e.target.value)}
                      type="text"
                      placeholder={__('Search Uploads')}
                      disabled={filterBy === FILTER_REPOSTS}
                    />
                  </Form>
                </div>
              }
              persistedStorageKey="claim-list-published"
              uris={fetching ? [] : urls}
              loading={fetching}
            />
            {fetching &&
              new Array(Number(pageSize)).fill(1).map((x, i) => <ClaimPreview key={i} placeholder="loading" />)}
            <Paginate totalPages={urlTotal > 0 ? Math.ceil(urlTotal / Number(pageSize)) : 1} />
          </>
        )}
      </div>
      {!fetching && myClaims.length === 0 && (
        <React.Fragment>
          {!fetching ? (
            <section className="main--empty">
              <Yrbl
                title={filterBy === FILTER_REPOSTS ? __('No Reposts') : __('No uploads')}
                subtitle={
                  filterBy === FILTER_REPOSTS
                    ? __("You haven't reposted anything yet. Do it.")
                    : __("You haven't uploaded anything yet. This is where you can find them when you do!")
                }
                actions={
                  filterBy !== FILTER_REPOSTS && (
                    <div className="section__actions">
                      <Button
                        button="primary"
                        navigate={`/$/${PAGES.UPLOAD}`}
                        label={__('Upload Something New')}
                        onClick={() => clearPublish()}
                      />
                    </div>
                  )
                }
              />
            </section>
          ) : (
            <section className="main--empty">
              <Spinner delayed />
            </section>
          )}
        </React.Fragment>
      )}
    </Page>
  );
}

export default FileListPublished;