import * as React from 'react';
import classNames from 'classnames/bind';
import CustomIcon from 'components/items/CustomIcon';
import PageForm from 'components/forms/PageForm';
import HeaderCms from 'components/global/HeaderCms';
import { Form } from 'react-final-form';

import PageCmsForm from 'components/forms/PageCmsForm';
import { Redirect, NavLink } from 'react-router-dom';
import { orderBy, find } from 'lodash';
import { config } from 'config/general';
import { clone } from 'store/utils/helper';
import isEqual from 'lodash/isEqual';
import styleIdentifiers from './pages.scss';

const styles = classNames.bind(styleIdentifiers);

interface PagesStateProps {
  loading: boolean;
  data: Record<string, any>[];
  loaded: boolean;
}

export interface PagesProps {
  user: Record<string, any>;
  pages: null | PagesStateProps;
  loadList: Function;
  history: Record<string, any>;
  match: Record<string, any>;
  sideMenuShow: Function;
  dialogShow: Function;
  addPage: Function;
  updatePage: Function;
  deletePage: Function;
  sideMenuHide: Function;
}

interface PagesState {
  content: Record<string, any> | null;
}

export default class Pages extends React.Component<PagesProps, PagesState> {
  constructor(props) {
    super(props);
    this.state = {
      initialValues: null,
    };
    this.autoRefresh();
  }

  componentDidMount() {
    const { loadList } = this.props;
    loadList({
      reset: true,
    });
  }

  componentDidUpdate() {
    this.handleFirstPage();
    this.handleCurrentPage();
  }

  componentWillUnmount() {
    if (this.intervalID) clearInterval(this.intervalID);
  }

  autoRefresh = () => {
    const { loadList } = this.props;

    if (!config.reloadContentTime) return;

    if (this.intervalID) clearInterval(this.intervalID);

    this.intervalID = setInterval(() => {
      loadList({
        noLoading: true,
      });
    }, config.reloadContentTime * 1000);
  };

  handleFirstPage = () => {
    const {
      user,
      pages,
      loadList,
      history,
      match: { params },
    } = this.props;
    if (user && user.loaded && (!pages || (!pages.loading && !pages.loaded))) {
      loadList();
    }
    if (pages && pages.loaded) {
      const first = pages && pages.data && pages.data[0];
      if (params && !params.id) history.push(`/paragraph/pages/${first.id}`);
    }
  };

  handleCurrentPage = () => {
    const { initialValues } = this.state;
    const page = this.currentPage();

    if (!page) return;

    const targetValues = {
      [config.cmsBaseName]: page.content,
    };

    // change initial values only if page has changed
    if (!isEqual(initialValues, targetValues)) {
      this.setState({
        initialValues: targetValues,
      });
    }
  };

  orderedPages = () => {
    const { pages } = this.props;

    const pageData = pages && pages.data;

    if (pageData)
      return orderBy(
        pageData,
        (item: Record<string, any>) => {
          if (config.orderByCMS && item[config.orderByCMS]) return item[config.orderByCMS];
          return 0;
        },
        [config.orderByDirectionCMS],
      );
    return [];
  };

  submitPage = (values: Record<string, any>) => {
    const { updatePage, addPage, history, sideMenuHide } = this.props;

    values.state = values.title;
    if (values.id) {
      updatePage({
        data: values,
        callback: () => sideMenuHide('right'),
      });
    } else {
      addPage({
        data: {
          ...values,
          content: '{}',
        },
        callback: res => {
          sideMenuHide('right');
          history.push(`/paragraph/pages/${res.id}`);
        },
      });
    }
  };

  deletePage = (item: Record<string, any>) => {
    const { deletePage, dialogShow, pages, history, sideMenuHide } = this.props;

    dialogShow({
      id: 'confirm',
      title: 'admin.addPage.delete',
      messages: 'admin.addPage.confirmDelete',
      action: {
        value: () => {
          deletePage({
            id: item.id,
            callback: () => {
              sideMenuHide('right');
              const first = pages && pages.data && pages.data[0];
              history.push(`/paragraph/pages/${first.id}`);
            },
          });
        },
      },
    });
  };

  showPageForm = (item: Record<string, any>) => {
    const { sideMenuShow } = this.props;

    sideMenuShow({
      id: 'right',
      content: (
        <Form
          component={PageForm}
          edit={item && item.id}
          onSubmit={this.submitPage}
          deleteItem={() => this.deletePage(item)}
          initialValues={item}
        />
      ),
    });
  };

  currentPage = () => {
    const {
      match: { params },
      pages,
    } = this.props;

    const pagesList = pages && pages.data;

    // eslint-disable-next-line
    const currentPage = find(pagesList, (item: Object) => item.id == params.id);

    if (!currentPage) return false;

    return currentPage;
  };

  editContent = (values: Record<string, any>) => {
    const page = this.currentPage();
    if (!page) return;
    const { updatePage } = this.props;

    updatePage({
      data: {
        ...page,
        content: values[config.cmsBaseName],
      },
    });
  };

  renderPage = (item: Record<string, any>, index: number) => {
    const { search } = this.props;
    if (search.filter && item.hide) return false;

    const link = `/paragraph/pages/${item.id}`;

    return (
      <div className={styles('item-wrapper', item.toComplete && 'to-complete')} key={index}>
        <NavLink
          to={link}
          className={styles('item', 'link-wrapper')}
          activeClassName={styles('state-active')}
          isActive={(match, location) => {
            return location?.pathname?.indexOf(link) >= 0;
          }}
        >
          <span>{item.label}</span>
          {!item.filterMatch && item.toComplete && (
            <span className={styles('to-complete')}>{item.stats.toComplete}</span>
          )}
          {item.filterMatch > 0 && (
            <span className={styles('filter-match')}>{item.filterMatch}</span>
          )}
        </NavLink>
        <div className={styles('edit')} onClick={() => this.showPageForm(item)}>
          <CustomIcon className={styles('icon')} icon="pen" />
        </div>
      </div>
    );
  };

  render() {
    const { user, pages, search } = this.props;

    const { initialValues } = this.state;

    if (user && user.loaded && !user.data) return <Redirect to="/paragraph/login" />;

    const page = this.currentPage();

    return (
      <div className={styles('Pages')}>
        {pages && (
          <>
            <div className={styles('nav-pages')}>
              <div className={styles('nav-content')}>
                {this.orderedPages().map(this.renderPage)}
              </div>
              <div className={styles('nav-footer')}>
                <div className={styles('nav-footer-content')} onClick={() => this.showPageForm({})}>
                  <span>Add page</span>
                </div>
              </div>
            </div>
            <div className={styles('nav-page-content')}>
              <HeaderCms />
              {page && initialValues && (
                <Form
                  pageId={page[config.idKey]}
                  initialValues={initialValues}
                  component={PageCmsForm}
                  search={search}
                  page={page}
                  completion={page.stats}
                  onSubmit={this.editContent}
                />
              )}
            </div>
          </>
        )}
      </div>
    );
  }
}
