/*
 *
 * Gallery
 *
 */

import PropTypes from 'prop-types';

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators, compose } from 'redux';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { createStructuredSelector } from 'reselect';
import moment from "moment";
import _ from "lodash";
import { CapHeading, CapHeader, CapInput, CapButton, CapIcon, CapDropdown, CapMenu, CapCustomCard, CapSlideBox, CapLabel, CapIllustration, CapNotification,} from '@capillarytech/cap-ui-library';
import { Popover } from 'antd';
import makeSelectGallery from './selectors';
import messages from './messages';
import * as actions from './actions';
import { UserIsAuthenticated } from '../../../utils/authWrapper';
import * as globalActions from '../../Cap/actions';
import {getMessageObject} from '../../../utils/messageUtils';
import * as commonUtil from '../../../utils/common';
import Pagination from '../../../v2Components/Pagination';
import imageGalleryIllustration from '../images/imageGalleryIllustration.svg';
import CapCustomSkeleton from '../../../v2Components/CapCustomSkeleton';
import './_gallery.scss';
import injectSaga from '../../../utils/injectSaga';
import injectReducer from '../../../utils/injectReducer';
import { v2GallerySagas } from './sagas';
import v2GalleryReducer from './reducer';
import { GALLERY_ALLOWED_EXTENSION } from './constants';
import CapPageSpinner from '../../../v2Components/CapPageSpinner';

const {CapCustomCardList} = CapCustomCard;
export class Gallery extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      searchText: '',
      selectedAsset: {},
      showImagePreviewModal: false,
      hoveredItem: '',
      showEmbeddedPreview: false,
      page: 1,
      perPageLimit: 25,
      totalCount: 0,
      searchLoader: false,
    };
    this.uploadImages = this.uploadImages.bind(this);
    this.openFileDialog = this.openFileDialog.bind(this);
    this.searchAsset = this.searchAsset.bind(this);
    this.openPreviewMode = this.openPreviewMode.bind(this);
    this.renderAssetPreviewModal = this.renderAssetPreviewModal.bind(this);
    this.toggleImagePreview = this.toggleImagePreview.bind(this);
    this.selectAsset = this.selectAsset.bind(this);
    this.handleGallery = this.handleGallery.bind(this);
    this.deleteAsset = this.deleteAsset.bind(this);
    this.handleOnHoverItem = this.handleOnHoverItem.bind(this);
    this.unmountEvent = this.unmountEvent.bind(this);
    this.handleSortingChange = this.handleSortingChange.bind(this);
    this.openEmbeddedPreviewMode = this.openEmbeddedPreviewMode.bind(this);
    this.hideEmbeddedPreviewMode = this.hideEmbeddedPreviewMode.bind(this);
    this.delayTimer = 0;
  }

  componentWillMount() {
    const params = {
      name: this.state.searchText,
      sortBy: 'Most Recent',
    };
    this.getAllAssets({params});
    this.props.actions.getUserList();
    window.addEventListener("message", this.handleGallery, false);
  }

  componentWillReceiveProps(nextProps) {
    if ( !_.isEqual(nextProps.Gallery.uploadAssetSuccess, this.props.Gallery.uploadAssetSuccess) && nextProps.Gallery.uploadAssetSuccess) {
      if (this.props.location.query.type === 'embedded' && nextProps.Gallery.uploadedAssetData) {
        const response = {
          action: "selectAsset",
          value: JSON.stringify(nextProps.Gallery.uploadedAssetData),
        };
        parent.postMessage(JSON.stringify(response), '*');
      }
      const message = getMessageObject('success', this.props.intl.formatMessage(messages.assetUploadSuccess), true);
      this.props.globalActions.addMessageToQueue(message);
      const params = {
        name: this.state.searchText,
      };
      this.getAllAssets({params, resetPage: true});
    }
    if (!this.props.Gallery.fetchingAllAssets && !_.isEmpty(this.props.Gallery.assetList) && this.props.Gallery.assetList[0] && this.props.Gallery.assetList[0].totalCount && this.state.totalCount === 0) {
      this.setState({totalCount: this.props.Gallery.assetList[0].totalCount});
    }
    if ( !_.isEqual(nextProps.Gallery.assetUploading, this.props.Gallery.assetUploading) && !nextProps.Gallery.uploadAssetSuccess && !nextProps.Gallery.assetUploading) {
      const message = getMessageObject('error', this.props.intl.formatMessage(messages.assetUploadFailed), true);
      this.props.globalActions.addMessageToQueue(message);
    }

    if (!nextProps.Gallery.deletingAsset && !nextProps.Gallery.assetDeleteError && !_.isEqual(nextProps.Gallery.deletingAsset, this.props.Gallery.deletingAsset)) {
      const message = getMessageObject('success', this.props.intl.formatMessage(messages.assetDeleteSuccess), true);
      this.props.globalActions.addMessageToQueue(message);
      const params = {
        name: this.state.searchText,
        sortBy: 'Most Recent',
      };
      this.getAllAssets({params, resetPage: true});
    }
    if (!nextProps.Gallery.deletingAsset && nextProps.Gallery.assetDeleteError && !_.isEqual(nextProps.Gallery.deletingAsset, this.props.Gallery.deletingAsset)) {
      const message = getMessageObject('error', this.props.intl.formatMessage(messages.assetDeleteFailed), true);
      this.props.globalActions.addMessageToQueue(message);
    }
  }

  componentWillUnmount() {
    window.removeEventListener("message", this.handleGallery, false);
  }

  getAllAssets = ({params, getNextPage, resetPage}, isReRender = false) => {
    let queryParams = params;
    let page = this.state.page;
    let shouldFetchGalleryAssets = false;
    if (!this.props.Gallery.fetchingAllAssets && ((resetPage || (page === 1 && this.state.totalCount === 0) || page <= (this.state.totalCount / this.state.perPageLimit)) || isReRender )) {
      if (getNextPage) {
        page += 1;
        shouldFetchGalleryAssets = true;
      }

      let totalCount = this.state.totalCount;
      if (resetPage) {
        page = 1;
        totalCount = 0;
        shouldFetchGalleryAssets = true;
      }
      if ((!params || _.isEmpty(params))) {
        queryParams = {
          sortBy: this.state.sortBy,
        };
      }
      if (this.state.searchText !== "") {
        queryParams = {...queryParams, name: this.state.searchText};
        shouldFetchGalleryAssets = true;
      }
      if (!this.props.Gallery.fetchingAllAssets && (_.isEmpty(this.props.Gallery.assetList) || shouldFetchGalleryAssets)) {
        this.setState({page, totalCount}, () => {
          queryParams.page = page;
          queryParams.perPage = this.state.perPageLimit;
          this.props.actions.getAllAssets('image', queryParams);
        });
      }
    }
  };
  handleGallery = (e) => {
    const type = e.data;
    switch (type) {
      case 'unmount':
        this.unmountEvent();
        break;
      default:
        break;
    }
  };

  handleSortingChange(value) {
    const params = {
      name: this.state.searchText,
      sortBy: value,
    };
    this.getAllAssets({params, resetPage: true});
  }
  unmountEvent() {
    window.removeEventListener("message", this.handleGallery, false);
  }

  handleOnHoverItem(isHovering, id) {
    if (isHovering) {
      this.setState({hoveredItem: id});
    } else {
      this.setState({hoveredItem: ''});
    }
  }

  toggleImagePreview() {
    this.setState({ showImagePreviewModal: !this.state.showImagePreviewModal });
  }

  selectAsset() {
    const response = {
      action: "selectAsset",
      value: JSON.stringify(this.state.selectedAsset),
    };
    parent.postMessage(JSON.stringify(response), '*');
  }

  openPreviewMode(selectedAsset) {
    const asset = selectedAsset;
    if (this.props.location.query.type !== 'embedded' || this.props.isFullMode) {
      this.toggleImagePreview();
    } else {
      asset.showButtons = asset.showButtons ? !asset.showButtons : true;
    }
    this.setState({selectedAsset: asset});
  }

  hideEmbeddedPreviewMode() {
    this.setState({selectedAsset: {}, showEmbeddedPreview: false});
  }

  openEmbeddedPreviewMode(selectAsset) {
    this.setState({selectedAsset: selectAsset, showEmbeddedPreview: true});
  }

  searchAsset(value) {
    this.setState({searchText: value, searchLoader: true}, () => {
      this.delay(() => {
        const params = {
          name: this.state.searchText,
        };
        if (this.state.sortBy) {
          params.sortBy = this.state.sortBy;
        }
        this.getAllAssets({params, resetPage: true});
        this.setState({
          searchLoader: false,
        });
      }, 1000);
    });
  }

  delay(callback, ms) {
    clearTimeout(this.delayTimer);
    this.delayTimer = setTimeout(callback, ms);
  }

  uploadImages(e, {files}) {
    e.preventDefault();
    const _URL = window.URL || window.webkitURL;
    for (const file in files) {
      if (files.hasOwnProperty(file)) {
        const {size = '', name = ''} = files[file];
        const fileSize = size / (1024 * 1024);
        const allowedExtensions = GALLERY_ALLOWED_EXTENSION;
        if (fileSize > 10 || !allowedExtensions?.test(name)) {
          const { formatMessage } = this.props.intl;
          const fileErrorMessage = {
            key: "image-gallery-upload-error",
            message: formatMessage(messages.invalidUploadFileError),
            description: formatMessage(messages.invalidUploadFileErrorDesc3),
          };
          CapNotification.error(fileErrorMessage);
          return;
        }
        const img = new Image();
        const that = this;
        img.src = _URL.createObjectURL(files[file]);
        img.onload = function () {
          const fileParams = {
            width: this.width,
            height: this.height,
            isGeneratePreview: true,
          };
          that.props.actions.uploadAsset(files[file], 'image', fileParams);
        };
      }
    }
  }
  getIllustrationProps={
    buttonClassName: 'upload-image-gallery',
    buttonLabel: <FormattedMessage {...messages.upload} />,
    onClick: (e) => this.openFileDialog(e),
    illustrationImage: imageGalleryIllustration,
    title: <FormattedMessage {...messages.addImages} />,
  }

  prepareData() {
    const data = [];
    const assetList = this.props.Gallery.assetList;
    _.forEach(assetList, (asset) => {
      const tmpData = {};
      tmpData.id = asset._id;
      const updateDateTime = (moment().format('DD-MM-YYYY') === moment(asset.updatedAt).format('DD-MM-YYYY')) ? moment(asset.updatedAt).format('hh:mma') : moment(asset.updatedAt).format('DD-MM-YYYY');
      tmpData.content = (
        <div className="image-container" onClick={() => this.openPreviewMode(asset)}>
          <img style={{width: '100%'}} src={asset.metaInfo.secure_file_path ? asset.metaInfo.secure_file_path : asset.metaInfo.public_url} alt={asset.name} />
          <div className={asset.showButtons ? 'overlay show-overlay' : 'overlay hide'}>
            <div>
              <CapButton type="secondary" className="select-button" onClick={(e) => this.selectAsset(e)}>
                <FormattedMessage {...messages.select} />
              </CapButton>
            </div>
            <div>
              <CapButton type="cancel" className="preview-button" onClick={() => this.openEmbeddedPreviewMode(asset)}>
                <FormattedMessage {...messages.preview} />
              </CapButton>
            </div>
          </div>
        </div>
      );
      tmpData.footer = (
        <div className="card-footer-wrapper">
          <div className="card-title-container">
            <div className="card-title-wrapper">
              <p className="card-title" onClick={() => this.openPreviewMode(asset)}>{asset.name}</p>
            </div>
            <div className="more-icon-wrapper">
              <Popover
                placement="leftTop"
                content={<div style={{ cursor: 'pointer'}}><p onClick={() => this.deleteAsset(asset)}>
                  <FormattedMessage {...messages.delete} />
                </p></div>} trigger="click">
                <i className="material-icons creative-icons">more_vert</i>
              </Popover>
            </div>
          </div>
          <p className="card-detail"><FormattedMessage {...messages.uploadedAt} />: {updateDateTime}</p>
        </div>
      );
      data.push(tmpData);
    });
    return data;
  }
  deleteAsset(asset) {
    this.props.actions.deleteAssetById(asset._id, asset.type);
  }
  getTemplateDataForGrid = ({templates, handlers, filterContent, isLoading, loadingTip, isInitialLoading}) => {
    const currentChannel = 'gallery';
    const { searchLoader, searchText } = this.state;
    const cardDataList = templates?.length ? _.map(templates, (template) => {
      template.name = commonUtil.getDecodedFileName(template?.name);
      const templateData =
        {
          key: `${currentChannel}-card-${template.name}`,
          title: <span title={template.name} >{template.name}</span>,
        };
      if (!this.props.isLineAsset) {
        templateData.extra = [
          <CapIcon
            className="view-gallery"
            style={{marginRight: '16px'}}
            type="eye"
            onClick={() => { this.openPreviewMode(template); }}
            />,
          <CapDropdown
            overlay={
              <CapMenu>
                <CapMenu.Item className="delete-gallery" onClick={() => this.deleteAsset(template)}>
                  <FormattedMessage {...messages.delete} />
                </CapMenu.Item>
              </CapMenu>
        }
      >
            <CapIcon type="more" />
          </CapDropdown>,
        ];
      }
      if (!this.props.isFullMode) {
        templateData.hoverOption = <CapButton onClick={(e) => handlers.selectAsset(e, template._id)}><FormattedMessage {...messages.select} /></CapButton>;
      }
      if (this.props.isLineAsset) {
        templateData.hoverOption = <CapButton onClick={() => this.props.onGalleryImageSelect(template)}><FormattedMessage {...messages.select} /></CapButton>;
      }
      if (this.props.isLibraryAsset) {
        templateData.hoverOption = <CapButton onClick={() => this.props.onGalleryImageSelect(template)}><FormattedMessage {...messages.select} /></CapButton>;
      }
      const secureFilePath = _.get(template, 'metaInfo.secure_file_path');
      templateData.url = secureFilePath || _.get(template, 'metaInfo.public_url');
      return templateData;
    }) : [];
    return (<div>
      {filterContent}
        {!(isInitialLoading && isLoading) && <div>
          {!_.isEmpty(templates) || !_.isEmpty(searchText) ? <div className={`v2-pagination-container ${this.props.isLineAsset ? 'gallery-upload' : ''}`}>
            <CapCustomCardList key={`${currentChannel}-card-list`} cardList={cardDataList} type={'Email'} />
            {!_.isEmpty(searchText) && _.isEmpty(templates) && (
              <div style={{ height: '65vh', textAlign: 'center', lineHeight: '65vh'}}>
                <CapHeading type="h6">{this.props.intl.formatMessage(messages.noTemplatesFound)}</CapHeading>
              </div>
            )}
          </div> : (
            _.isEmpty(templates) &&
            _.isEmpty(searchText) &&
            !searchLoader &&
            <CapIllustration {...this.getIllustrationProps} />
          )}
        </div>
        }
        {<CapCustomSkeleton loader={isInitialLoading && isLoading} />}
        {<CapPageSpinner spinning={!isInitialLoading && isLoading} />}

    </div>);
  }
  openFileDialog() {
    document.getElementById("fileName").click();
  }

  renderAssetPreviewModal() {
    const slideboxContent = (
      <div>
        <div style={{overflow: 'hidden', textAlign: 'center'}}>
          <div style={{ display: 'flex', justifyContent: 'center', height: '85vh', background: 'url(https://s3.amazonaws.com/test_files_cache_bkp/intouch_creative_assets/1720b7f7e78860c1f905.svg)' }}>
            <div style={{ height: "85vh", verticalAlign: 'middle' }}>
              <img style={{maxWidth: '100%', maxHeight: '100%'}} src={this.state.selectedAsset.metaInfo.secure_file_path ? this.state.selectedAsset.metaInfo.secure_file_path : this.state.selectedAsset.metaInfo.public_url} alt={this.state.selectedAsset.name} />
            </div>
          </div>
          <a href={this.state.selectedAsset.metaInfo.public_url} target="_blank" style={{ position: 'fixed', right: '55px', bottom: '18vh' }} ><i className="material-icons" style={{ color: '#2E89DF', cursor: 'pointer' }}>fullscreen</i></a>
        </div>
      </div>
    );
    const on = moment(this.state.selectedAsset.updatedAt).format('DD MMM YYYY hh:mm A');
    const by = commonUtil.getUserNameById(parseInt(this.state.selectedAsset.updatedBy, 10), commonUtil.getMergedUserList(this.props.Gallery.userList));
    const width = this.state.selectedAsset.metaInfo.width;
    const height = this.state.selectedAsset.metaInfo.height;
    const slideboxHeader = (<div>
      <CapHeader
        title={this.state.selectedAsset.name}
        description={<FormattedMessage
          {...messages.lastUpdated}
          values={{on, by }}
          />}
        />
      <CapLabel type="label2">
        {width && height && <span>
          <FormattedMessage {...messages.dimensions} />: {`${width}X${height} px`}
        </span>}
        {' '}
        <FormattedMessage {...messages.size} />:{' '}
        {(!isNaN(this.state.selectedAsset.metaInfo.file_size) ? `${(parseFloat(this.state.selectedAsset.metaInfo.file_size) / 1024).toFixed(2)} KB` : this.state.selectedAsset.metaInfo.file_size )}
      </CapLabel>
    </div>);
    return (
      <CapSlideBox
        header={slideboxHeader}
        content={slideboxContent}
        show={this.state.showImagePreviewModal}
        handleClose={this.toggleImagePreview}
        size="size-l"
      />
    );
  }
  render() {
    const assetList = this.props.Gallery.assetList;
    const filterContent = !_.isEmpty(assetList) || !_.isEmpty(this.state.searchText) ? (
      <div className="action-container" style={{ display: 'inline-flex', width: '100%'}}>
        <div style={{ marginTop: '8px', width: '50%'}}>
          <CapInput.Search
            className="search-text"
            style={{width: `${this.props.isLineAsset ? '324px' : '210px'}`}}
            placeholder={this.props.intl.formatMessage(messages.search)}
            value={this.state.searchText}
            onChange={(e) => this.searchAsset(e.target.value)}
            onClear={() => this.searchAsset('')}
          />
        </div>
        {
          !this.props.isLineAsset && (
            <div style={{ textAlign: 'right', marginTop: '16px', width: '50%'}}>
              <form encType="multipart/form-data" id="myForm">
                <input style={{ display: 'none'}} id="fileName" type="file" onClick={(e) => {e.target.value=null}} onChange={(e) => this.uploadImages(e, {files: e.target.files})} accept="image/*" multiple/>
                <CapButton className="upload-image-gallery" type={this.props.location.query.type !== 'embedded' ? 'primary' : 'secondary'} onClick={(e) => this.openFileDialog(e)} style={{float: 'right'}}>
                  <FormattedMessage {...messages.upload} />
                </CapButton>
              </form>
            </div>
          )
        }
      </div>
    ) : <input style={{ display: 'none'}} id="fileName" type="file" onClick={(e) => {e.target.value=null}} onChange={(e) => this.uploadImages(e, {files: e.target.files})} accept="image/*" multiple/>;
    const isLoading = this.props.Gallery.assetUploading || this.props.Gallery.fetchingAllAssets;
    const loadingTip = <FormattedMessage {...messages.loadingGallery} />;

    return (
      <div>
        {this.state.showEmbeddedPreview ?
          <div className="embedded-preview-wrapper">
            <div className="embedded-preview-header" onClick={this.hideEmbeddedPreviewMode}>
              <p className="embedded-preview-header-wrapper" style={{display: 'inline-flex'}}>
                <i className="material-icons">arrow_back</i>
                <span className="embedded-preview-header-text">
                  <FormattedMessage {...messages.backToGallery} />
                </span>
              </p>
            </div>
            <div style={{height: "75vh", width: '100%'}}>
              <div style={{overflow: 'hidden', textAlign: 'center'}}>
                <div style={{ display: 'table', height: '75vh', width: '85vw', background: 'url(https://s3.amazonaws.com/test_files_cache_bkp/intouch_creative_assets/1720b7f7e78860c1f905.svg)' }}>
                  <div style={{ height: "75vh", display: 'table-cell', verticalAlign: 'middle' }}>
                    <img style={{maxWidth: '100%', maxHeight: '100%'}} src={this.state.selectedAsset.metaInfo.secure_file_path ? this.state.selectedAsset.metaInfo.secure_file_path : this.state.selectedAsset.metaInfo.public_url} alt={this.state.selectedAsset.name} />
                  </div>
                </div>
                <a href={this.state.selectedAsset.metaInfo.public_url} target="_blank" style={{ position: 'fixed', right: '24px', bottom: '17vh' }} ><i className="material-icons" style={{ color: '#2E89DF', cursor: 'pointer' }}>fullscreen</i></a>
              </div>
              <div style={{ fontSize: '14px', color: '#333333', lineHeight: '24px', fontFamily: 'OpenSans', textAlign: 'center', paddingTop: '10px'}}>
                <p><span><FormattedMessage {...messages.dimensions} />: </span> <span>{`${this.state.selectedAsset.metaInfo.width}X${this.state.selectedAsset.metaInfo.height} px`}</span></p>
                <p><span><FormattedMessage {...messages.size} />: </span> <span>{this.state.selectedAsset.metaInfo.file_size}</span></p>
                <p><span><FormattedMessage {...messages.uploadedOn} />: </span> <span>{moment(this.state.selectedAsset.updatedAt).format('DD MMM YYYY hh:mm A')}</span></p>
                {/* <p><span>URL: </span> <span>{this.state.selectedAsset.metaInfo.publicUrl}</span></p> */}
              </div>
            </div>
          </div> :
          <Pagination onPageChange={() => { this.getAllAssets({getNextPage: true}); }}>
            {/* <CardGrid
              listItem={this.prepareData()}
              filterContent={filterContent}
              onHoverItem={this.handleOnHoverItem}
              onItemClick={this.handleOnHoverItem}
              enablePagination
            /> */}
            {this.getTemplateDataForGrid({isLoading, loadingTip, channel: this.state.channel, templates: assetList, filterContent, handlers: {selectAsset: this.selectAsset}, isInitialLoading: this.state.page === 1 && isLoading})}

          </Pagination>
          }
        {this.state.showImagePreviewModal && this.renderAssetPreviewModal()}
        {/*</Spin>*/}
      </div>
    );
  }
}

Gallery.propTypes = {
  actions: PropTypes.object.isRequired,
  Gallery: PropTypes.object,
  globalActions: PropTypes.object,
  location: PropTypes.object,
  intl: intlShape.isRequired,
  isFullMode: PropTypes.bool,
  isLineAsset: PropTypes.bool,
  onGalleryImageSelect: PropTypes.func,
};

const mapStateToProps = createStructuredSelector({
  Gallery: makeSelectGallery(),
});

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(actions, dispatch),
    globalActions: bindActionCreators(globalActions, dispatch),
  };
}

const withConnect = connect(mapStateToProps, mapDispatchToProps);
const withReducer = injectReducer({ key: 'gallery', reducer: v2GalleryReducer });
const withSaga = injectSaga({ key: 'gallery', saga: v2GallerySagas });

export default compose(
  UserIsAuthenticated,
  withSaga,
  withReducer,
  withConnect,
)(injectIntl(Gallery));
