import React, { useCallback, useState, useMemo, useLayoutEffect } from 'react';
import { CampaignDetails } from 'backend-api/models';
import { Button, BUTTON_SIZE, BUTTON_TYPE, THEME, Typography, TYPOGRAPHY_TYPE, Input } from 'gdb-web-shared-components';
import { bem } from 'utils/bem';
import { Loading } from 'common-v2/types';
import { Modal, ModalContentProps, ErrorView } from 'common-v2/components';
import { toggleElementInArray } from 'common-v2/utils';
import { getErrorViewConfig } from './transducers';
import { AssignedCampaignsList, CampaignList } from './components';
import { SManageCampaignsModal, BEM_CLASS } from './s-manage-campaigns-modal';

interface ManageCampaignsModalProps {
  isOpened: boolean;
  loading: Loading;
  processing: Loading;
  infiniteLoading: Loading;
  campaignsTotalCount: number;
  searchValue: string;
  formatDate(date?: Date): void;
  onClose(): void;
  refresh(): void;
  onScrollEnd(): void;
  onApply(selectedCampaigns: CampaignDetails[]): void;
  onSearchChange: React.ChangeEventHandler<HTMLInputElement>;
  clearSearch(): void;
  campaigns: CampaignDetails[];
  assignedCampaigns: CampaignDetails[];
}

const classes = bem(BEM_CLASS);

export const ManageCampaignsModal = React.memo(
  ({
    isOpened,
    loading,
    processing,
    onClose,
    infiniteLoading,
    searchValue,
    formatDate,
    onSearchChange,
    clearSearch,
    campaignsTotalCount,
    refresh,
    onScrollEnd,
    campaigns,
    onApply,
    assignedCampaigns,
  }: ManageCampaignsModalProps) => {
    const [selectedCampaigns, setSelectedCampaigns] = useState<CampaignDetails[]>(assignedCampaigns);

    const isApplying = processing === Loading.Started || processing === Loading.Finished;
    const selectedIds = useMemo(() => selectedCampaigns.map(campaign => campaign.id), [selectedCampaigns]);

    const clearSelectedCampaigns = useCallback(() => {
      setSelectedCampaigns([]);
    }, [setSelectedCampaigns]);

    const toggleCampaign = useCallback(
      (campaign: CampaignDetails) => {
        setSelectedCampaigns(selected => toggleElementInArray(selected, campaign));
      },
      [setSelectedCampaigns]
    );

    const unselectCampaign = useCallback(
      (id: number) => {
        setSelectedCampaigns(selected => selected.filter(val => val.id !== id));
      },
      [setSelectedCampaigns]
    );

    const applyHandler = useCallback(() => onApply(selectedCampaigns), [selectedCampaigns, onApply]);

    const renderBody = useCallback(
      (props: ModalContentProps) => {
        switch (loading) {
          case Loading.Failed: {
            const viewConfig = getErrorViewConfig(
              <span>
                An error occurred while loading Campaigns
                <br />
                data. Please try again
              </span>
            );

            return (
              <div className={classes('container')}>
                <ErrorView config={viewConfig} action={refresh} />
              </div>
            );
          }
          default: {
            return (
              <div className={classes('container')}>
                <section className={classes('body')}>
                  <div className={classes('content')}>
                    <Input
                      value={searchValue}
                      placeholder="Search by Name or ID"
                      onChange={onSearchChange}
                      icon="search"
                      theme={THEME.light}
                      onClearClick={clearSearch}
                      isClearable={searchValue.length > 0}
                      className={classes('input-root')}
                      inputClassName={classes('input')}
                    />

                    <CampaignList
                      campaigns={campaigns}
                      campaignsTotalCount={campaignsTotalCount}
                      infiniteLoading={infiniteLoading}
                      loading={loading}
                      formatDate={formatDate}
                      disabled={isApplying}
                      onScrollEnd={onScrollEnd}
                      selectedIds={selectedIds}
                      toggleCampaign={toggleCampaign}
                    />
                  </div>
                  <div className={classes('divider')} />
                  <aside className={classes('sidebar')}>
                    <AssignedCampaignsList
                      disabled={isApplying}
                      campaigns={selectedCampaigns}
                      onCampaignDelete={unselectCampaign}
                      sideButton={
                        <Button
                          disabled={isApplying}
                          size={BUTTON_SIZE.small}
                          type={BUTTON_TYPE.tertiary}
                          theme={THEME.light}
                          onClick={clearSelectedCampaigns}
                          caption="Clear all"
                        />
                      }
                    />
                  </aside>
                </section>

                <footer className={classes('footer')}>
                  <Button
                    className={classes('button')}
                    disabled={isApplying}
                    caption="Cancel"
                    type={BUTTON_TYPE.secondary}
                    theme={THEME.light}
                    onClick={props.closeModal}
                  />
                  <Button
                    disabled={isApplying || loading === Loading.Started}
                    className={classes('button')}
                    caption={!isApplying ? 'Apply' : undefined}
                    type={BUTTON_TYPE.primary}
                    onClick={applyHandler}
                    icon={isApplying ? 'ellipsis' : undefined}
                  />
                </footer>
              </div>
            );
          }
        }
      },
      [
        applyHandler,
        campaigns,
        campaignsTotalCount,
        clearSearch,
        clearSelectedCampaigns,
        infiniteLoading,
        isApplying,
        loading,
        onScrollEnd,
        onSearchChange,
        refresh,
        searchValue,
        selectedCampaigns,
        selectedIds,
        formatDate,
        toggleCampaign,
        unselectCampaign,
      ]
    );

    const renderContent = useCallback(
      (props: ModalContentProps) => (
        <SManageCampaignsModal>
          <header className={classes('header')}>
            <Typography className={classes('title')} type={TYPOGRAPHY_TYPE.heading2}>
              Managing Campaigns
            </Typography>
            <Button
              type={BUTTON_TYPE.tertiary}
              size={BUTTON_SIZE.smallRound}
              theme={THEME.light}
              icon="cross"
              onClick={props.closeModal}
            />
          </header>

          {renderBody(props)}
        </SManageCampaignsModal>
      ),
      [renderBody]
    );

    useLayoutEffect(() => {
      if (isOpened) {
        setSelectedCampaigns(assignedCampaigns);
      }
    }, [assignedCampaigns, isOpened]);

    return <Modal isOpened={isOpened} renderContent={renderContent} onClose={onClose} />;
  }
);
