/*
 * @Author: 吴文洁 
 * @Date: 2020-06-10 13:54:01 
 * @Last Modified by: 吴文洁
 * @Last Modified time: 2020-07-23 09:33:21
 * @Description：选择备课文件弹窗 
 */

import React from 'react';
import { Modal, Button, Radio, Checkbox, message, Tooltip } from 'antd';
import _ from 'underscore';
import * as lodash from 'lodash';
import { LottieIcon } from 'xiaomai-b-components';

import Service from '@/common/js/service';
import { getEllipsText } from "@/domains/basic-domain/utils";
import { getFileTypeByName } from '@/domains/resource-disk/utils';
import {
  DEFAULT_SIZE_UNIT,
  FILE_TYPE_ICON_MAP,
  FILR_VERIFY_MAP,
  NON_COMPLIANT_FILE_MAP,
  SUPPORT_FILE_TYPE_MAP
} from "@/domains/resource-disk/constants";

import UploadProgressModal from '@/bu-components/UploadProgressModal';

import NonCompliantFileModal from './NonCompliantFileModal';

import './SelectPrepareFileModal.less';
import User from '@/common/js/user';

const defaultQuery = {
  size: 10,
  current: 1,
  folderIdType: 'FOLDER'
}

const defaultRootDisk = {
  folderName: '我的文件',
  disk: 'MYSELF',
  uploadPower: false
}

const FOLDERLIST_URL_MAP = {
  'MYSELF': 'public/hadesStore/folderList',
  'COMMON': 'public/hadesStore/folderList',
  'EMPLOYEE': 'public/hadesStore/employeeFolderList'
};

// 支持本地上传的文件类型
const localFileTypeMap = SUPPORT_FILE_TYPE_MAP.join(',');
const FileVerifyMap = FILR_VERIFY_MAP;
// 合法的文件名后缀
const FILE_SUFFIX_LIST = ['docx', 'doc', 'ppt', 'pptx', 'pdf', 'xlsx', 'xls', 'jpg', 'jpeg', 'png', 'mp3', 'mp4'];
// 禁止选择的文件类型
const DISABLE_FILE_FORMAT = ['text/csv', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];

// 最多可以选择20个文件
const MAX_SELECT_LENGTH = 20;

let count = 0;

class SelectPrepareFileModal extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      targetFolder: {},           // 当前选中的目录
      currentRootDisk: {},        // 当前所在根目录
      uploadFolderPath: {},       // 上传文件的目录，防止中途切换文件夹
      folderList: [],             // 文件列表
      folderPathList: [],         // 文件路径列表
      selectedFileList: [],       // 已勾选的文件
      nonCompliantFileList: [],   // 超出限制的文件列表
      query: defaultQuery,        // 初始请求参数
      showUploadModal: false,     // 上传进度弹窗
      showNonCompliantFileModal: false,
    }
  }
  
  componentWillReceiveProps(nextProps) {
    const { diskList = [],  currentRootDisk} = nextProps;
    if (nextProps.isOpen) {
      const _currentRootDisk = diskList[0] || currentRootDisk || defaultRootDisk;
      this.setState({
        query: defaultQuery,
        currentRootDisk: _currentRootDisk,
        folderPathList: [_currentRootDisk],
      }, () => {
        this.handleFetchFolderList();
      });
    }
  }

  // 获取文件列表
  handleFetchFolderList = (params = {}, loadMore = false) => {
    // 根据当前根节点获取文件列表
    const { selectType } = this.props;
    const { query, folderList, currentRootDisk } = this.state;
    const _params = {
      ...query,
      ...params,
      disk: params.disk || currentRootDisk.disk,
      storeId:User.getStoreId(),
      createId:User.getUserId()
    }

    if (selectType === 'video') {
      _params.fileType = 'VEDIOFILE';
    }

    Service.Hades(FOLDERLIST_URL_MAP[currentRootDisk.disk], _params).then((res) => {
      const { result = {} } = res;
      const { records = [], total = 0 } = result;
      this.setState({
        folderList: loadMore ? [...folderList, ...records] : records,
        totalCount: Number(total)
      });
    });
  }

  // 修改目录
  handleChangeFolder = (folder) => {
    this.setState({
      query: defaultQuery,
      folderPathList: [folder],
      currentRootDisk: folder,
      selectedFileList: [],          // 切换目录不保存之前已勾选的记录
    }, () => {
      this.handleFetchFolderList({ disk: folder.disk });
    });
  }

  // 选择文件/文件夹
  handleSelect = (folder) => {
    // 如果是文件，直接return, 否则进入下一级
    const { operateType = 'select', scene, selectedFileList = [] } = this.props;
    const { folderType, folderName, folderFormat } = folder;
    if (folderType === 'FOLDER') {
      this.handleSelectFolder(folder);
    }

    const suffix = _.last(folderName.split('.')).toLowerCase();

    // 文件是否已经被关联了
    const hasRelation = _.find(selectedFileList, (item) => item.resourceId === folder.resourceId);
    // 文件禁止点击的情况（移动、直播场景下文件为Excel、文件已经被关联了、文件后缀不合法)
    const disabled = operateType === 'move' ||
        (scene === 'liveCourse' && folderFormat === 'EXCEL') ||
        !!hasRelation || !FILE_SUFFIX_LIST.includes(suffix);

    if (folderType === 'FILE' && !disabled) {
      this.handleSelectFile(folder);
    }
  }

  // 选择文件夹
  handleSelectFolder = (folder) => {
    const { folderPathList, currentRootDisk } = this.state;

    // 更新文件路径
    folderPathList.push({
      id: folder.id,
      folderName: folder.folderName
    });

    this.setState({
      query: {
        ...this.state.query,
        current: 1
      },
      folderPathList,
      targetFolder: folder
    }, ()  => {

      // 判断是否是员工文件的根目录
      const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 2;
      // 根据父级目录id获取文件夹列表
      this.handleFetchFolderList({
        parentId: folder.id,
        folderIdType: employeeDisk ? 'USER' : 'FOLDER'
      });
    });
  }

  // 选择文件
  handleSelectFile = (file) => {
    const { selectedFileList } = this.state;
    const index = _.findIndex(selectedFileList, (item) => item.resourceId === file.resourceId);
    // 如果文件没有被勾选，则勾选
    if (index < 0) {
      selectedFileList.push(file);
    } else { // 如果文件已经被勾选了，则取消勾选
      selectedFileList.splice(index, 1);
    }
    this.setState({ selectedFileList });
  }

  handleSelectFileDone = () => {
    const { selectedFileList } = this.state;
    const {
      selectedFileList: prevSelectedFileList = [],
      maxSelectLength = MAX_SELECT_LENGTH
    } = this.props;

    const currSelectedFileList = [...(prevSelectedFileList || []), ...selectedFileList];
    // 最多选择20个文件，判断是否超出了20个
    if (currSelectedFileList.length > maxSelectLength) {
      // 最多还可选择的个数 = 总量（20） - 已经选择的个数（prevSelectedFileList）
      message.warning(`最多可选择${maxSelectLength - prevSelectedFileList.length}个文件`);
      return;
    }

    const addFolderIds = _.pluck(selectedFileList, 'id');

    this.props.onSelect(addFolderIds, selectedFileList);
    // 上传完成之后将selectedFileList置为空,上传进度弹窗也一起消失
    this.setState({
      showUploadModal: false,
      selectedFileList: []
    })
  }

  // 前往特定的文件夹
  handleChangeCurrentFolder = (folder, index) => {
    // 请求接口，获取当前folder下所有的文件
    const { folderPathList, currentRootDisk } = this.state;
    if (folderPathList.length === 1) return;

    folderPathList.splice(index+1, folderPathList.length);
    const targetFolder = folderPathList[folderPathList.length - 1];
    const { id = null } = targetFolder;
    // 判断是否是员工文件的根目录
    const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 2;

    this.setState({
      targetFolder,
      folderPathList
    }, () => {
      this.handleFetchFolderList({
        parentId: id,
        disk: currentRootDisk.disk,
        folderIdType: employeeDisk ? 'USER' : 'FOLDER'
      })
    });
  }

  // 移动到此目录
  handleMoveToTargetFolder = () => {
    const { targetFolder, folderPathList, folderList} = this.state;
    const query = {
      targetFolder,
      selectFolderPathList: folderPathList,
      selectFolderList: folderList
    }
    // 请求接口，完成之后刷新文件列表
    this.props.onMove(query);
  }

  // 滑动加载更多
  handleScrollEvent = () => {
    const { folderList, totalCount, currentRootDisk, folderPathList } = this.state;
    const hasMore = folderList.length < totalCount;

    const { fileListRef } = this.refs;
    const hasReachBottom = fileListRef.scrollTop + fileListRef.clientHeight === fileListRef.scrollHeight;
    if (!hasReachBottom || !hasMore) return;
    
    const currentFolder = folderPathList[folderPathList.length - 1];
    // 判断是否是员工文件的根目录
    const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 2;
    const query = _.clone(this.state.query);
    
    query.current = query.current + 1;
    this.setState({ query }, () => {
      this.handleFetchFolderList({
        disk: currentRootDisk.disk,
        folderIdType: employeeDisk ? 'USER' : 'FOLDER',
        parentId: currentFolder.id
      }, true);
    })
  }

  // 取消选择
  handleClose = () => {
    this.setState({
      query: defaultQuery,
      selectedFileList: []
    }, () => {
      this.props.onClose();
    })
  }

  handleChooseFile = async () => {
    // 校验是否已经欠费
    const { instId } = window.currentUserInstInfo;
    const res = await Service.Business("public/liveAssets/query", {
      instId,
    });
    // balance小于等于0表示已经欠费，旗舰版用户不需要校验余额
    const ultimateRes = await Service.Business('public/inst/checkInstProduct', {
      instId,
      productCodeList: ['ULTIMATESELL', 'PIP_TO_ULTIMATE', 'HIGH_TO_ULTIMATE']
    });
    
    const { result: { balance } } = res;

    if (balance <= 0 && !ultimateRes.result) {
      this.handleShowNoticeModal(balance);
      return;
    }
    const dom = document.querySelector('#detailFileInput');
    dom.click();
  }

  // 上传文件
  handleUpload = (event) => {
    const { selectType } = this.props;
    const fileList = event.target.files;
    // 判断文件的大小是否超出了限制
    const nonCompliantFileList = [];
    const _fileList = [...fileList];
    _fileList.map((file, index) => {
      let { size, type, name } = file;

      if (localFileTypeMap.indexOf(type) > -1 && size > FileVerifyMap[type].maxSize * DEFAULT_SIZE_UNIT) {
        nonCompliantFileList.push(file);
        _fileList.splice(index, 1);
      }
      file.key = count++;
      return file;
    });
    // 不符合规则的文件列表
    if (nonCompliantFileList.length > 0) {
      const { confirm } = NON_COMPLIANT_FILE_MAP[selectType];
      if (confirm) {
        Modal.info({
          ...confirm,
          icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>
        });
        return;
      }
      this.setState({
        fileList: _fileList,
        nonCompliantFileList,
        showNonCompliantFileModal: true,
      })
    } else {
      this.handleShowUploadModal(_fileList);
    }

    // 清空文件，防止第二次无法上传同一个文件
    const dom = document.querySelector('#detailFileInput');
    dom.value = '';
  }

  // 显示上传进度弹窗
  handleShowUploadModal = async (fileList) => {
    if (fileList.length) {
      const { folderPathList } = this.state;
      this.setState({
        showUploadModal: true,
        localFileList: fileList,
        uploadFolderPath: folderPathList[folderPathList.length - 1]
      });
    }
  }

  handleUploadDone = (file, resourceId) => {
    const { folderPathList, currentRootDisk, uploadFolderPath } = this.state;
    const { scene } = this.props;

    const currentFolder = folderPathList[folderPathList.length - 1];
    const { id = null } = uploadFolderPath || currentFolder;
    let { size, type, name } = file;

    if (!type) {
      type = getFileTypeByName(name)
    }

    const params = {
      name,
      resourceId,
      folderSize: size,
      folderFormat: type,
      folderTypeEnum: resourceId ? 'FILE' : 'FOLDER',
      disk: currentRootDisk.disk,
      createUser:"STORE_USER",
      parentId: id,
      storeId:User.getStoreId(),
      createId:User.getUserId()
    }

    Service.Hades('public/hadesStore/saveFolder', params).then((res) => {
      const { query, selectedFileList, currentRootDisk } = this.state;
      const _query = _.clone(query);
      const _selectedFileList = [...selectedFileList, res.result];
      _query.current = 1;

      this.setState({
        query: _query,
        selectedFileList: scene === 'liveCourse' ?
          _selectedFileList.filter(item => { return !DISABLE_FILE_FORMAT.includes(item.folderFormat)}) :
          _selectedFileList,
      }, () => {
        if (resourceId && !_.isEqual(uploadFolderPath, currentFolder)) return;
        // 上传之后根目录不变
        this.handleFetchFolderList({ parentId: id, disk: currentRootDisk.disk });
      });
    });
  }

  // 取消上传
  handleHiddenUploadModal = () => {
    this.setState({
      showUploadModal: false,
      localFileList: []
    });
  }

  // 余额欠费提示弹窗
  handleShowNoticeModal = (balance) => {
    Modal.info({
      title: '无法继续操作',
      content: '直播系统已升级，请联系运营老师。',
      icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>
    })
  }

  renderFooter = () => {
    const { selectedFileList, currentRootDisk } = this.state;
    const { operateType, selectType } = this.props;

    const {
      accept = '.ppt,.pptx,.doc,.docx,.pdf,.jpg,.jpeg,.png,.mp3,.mp4,.xlsx,.xls',
      tooltip = '支持文件类型：ppt、word、excel、pdf、jpg、mp3、mp4'
    } = NON_COMPLIANT_FILE_MAP[selectType] || {};
    
    const selectedFileLength = selectedFileList.length;
    const hasSelect = !!selectedFileLength;
    
    // 是否有上传权限
    const hasManagementAuthority = currentRootDisk.uploadPower;

    return [
      <input
        multiple
        type="file"
        style={{ display: 'none' }}
        id="detailFileInput"
        accept={accept}
        onChange={(e) => this.handleUpload(e)}
        key="inputFile"
      />,
      <div
        key="footerLeft"
        className={`footer__left prepare-lesson-upload ${operateType === 'select' && hasManagementAuthority ? 'visible' : 'hidden'}`}
      >
        <Tooltip title={tooltip}>
          <span
            className="footer__left"
            onClick={this.handleChooseFile}
          >上传文件</span>
        </Tooltip>
      </div>,
      <div className="footer__right" key="footerRight">
        <Button
          onClick={() => {
            this.setState({
              showUploadModal: false,
              selectedFileList: []
            });
            this.props.onClose();
          }}
        >取消</Button>
        <Choose>
          <When condition={operateType === 'select'}>
            <Button
              key="cancel"
              type="primary"
              disabled={!hasSelect}
              onClick={this.handleSelectFileDone}
            >{`确定${hasSelect ? `(${selectedFileLength})` : ''}`}</Button>
          </When>
          <Otherwise>
            <Button
              type="primary"
              onClick={this.handleMoveToTargetFolder}
            >移动到此目录</Button>
          </Otherwise>
        </Choose>
      </div>
    ]
  }

  render() {
    const {
      folderPathList, folderList, selectedFileList,
      currentRootDisk, showUploadModal, localFileList,
      showNonCompliantFileModal, nonCompliantFileList
    } = this.state;
    const {
      scene,
      isOpen,
      diskList = [],
      operateType = 'move',
      footer = this.renderFooter(),
      selectedFileList: prevSelectedFileList = [],
    } = this.props;

    const currentFolder = folderPathList[folderPathList.length - 1];
    const title = operateType === 'move' ? '移动到' : '选择文件';
    const currSelectedFileList = [...(prevSelectedFileList || []), ...selectedFileList];

    // 判断是否是员工文件的根目录
    const employeeDisk = currentRootDisk.disk === 'EMPLOYEE' && folderPathList.length === 1;

    return (
      <Modal
        visible={isOpen}
        title={title}
        footer={footer}
        maskClosable={false}
        width={680}
        onCancel={this.handleClose}
        className="select-prepare-file-modal"
      >
        {
          // 机构可见磁盘大于1且在选择文件的情况下才显示tabs
          operateType === 'select' && diskList.length > 1 && 
          <div className="radio-buttons">
            <Radio.Group
              defaultValue={currentRootDisk.disk}
              value={currentRootDisk.disk}
            >
              {
                diskList.map((item, index) => {
                  return (
                    <Radio.Button
                      value={item.disk}
                      key={`folder-item${index}`}
                      onClick={() => this.handleChangeFolder(item)}
                    >
                      {item.folderName}
                    </Radio.Button>
                  )
                })
              }
            </Radio.Group>
          </div>
        }
       
        <div className="bread-crumbs">
          {
            folderPathList.map((folderPath, index) => {
              return (
                <div
                  className="file-path"
                  key={`file-path${index}`}
                  onClick={() => this.handleChangeCurrentFolder(folderPath, index)}
                >
                  {folderPath.folderName}
                </div>
              )
            })
          }
        </div>
        <Choose>
          <When condition={!_.isEmpty(folderList)}>
            <div
              onScrollCapture={() => this.handleScrollEvent()}
              style={{ height: '320px', overflowY: 'scroll' }}
              ref="fileListRef"
            >
              <div className="file-list">
                {
                  folderList.map((folder, index) => {
                    const { folderType, folderSize, folderFormat, folderName } = folder;
                    const isFolder = folderType === 'FOLDER';

                    let _size = `${(folderSize / DEFAULT_SIZE_UNIT).toFixed(1)}M`;
                    if (folderSize < 0.1 * DEFAULT_SIZE_UNIT) {
                      _size = `${(folderSize / 1024).toFixed(1)}kb`;
                    }
                    
                    let imgSrc = !isFolder ?
                      FILE_TYPE_ICON_MAP[folderFormat] :
                      'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871430788.png';

                    if (employeeDisk) {
                      imgSrc = 'https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1594871440736.png'
                    }

                    const suffix = _.last(folderName.split('.')).toLowerCase();
                    
                    // 判断文件是否被选中了
                    const hasSelect = _.find(currSelectedFileList, (item) => item.resourceId === folder.resourceId);

                    // 判断文件是否已经被关联了
                    const hasRelation = _.find((prevSelectedFileList || []), (item) => item.resourceId === folder.resourceId);

                    // 文件禁止点击的情况（移动、直播场景下文件为Excel、文件已经被关联了、文件不合法)
                    const disabled = (!isFolder && operateType === 'move') || (scene === 'liveCourse' && folder.folderFormat === 'EXCEL') || !!hasRelation || (!isFolder && !FILE_SUFFIX_LIST.includes(suffix));
                    if(isFolder){
                      return (
                        <div
                          className={`file-item ${!disabled ? 'enable' : 'disable'}`}
                          key={`file-item${index}`}
                          onClick={
                            lodash.debounce(() => this.handleSelect(folder), 500)
                          }
                        >
                          <div className="file-item__cover">
                            <img src={imgSrc} alt="file-item__img" width="24" />
                            <span>{getEllipsText(folderName, 20)}</span>
                          </div>
                          {/* 文件夹不显示大小 */}
                          { !isFolder && <div className="file-item__size">{_size}</div> }
  
                          {/* 当选择文件的时候，显示复选框 */}
                          {
                            !isFolder && operateType === 'select' &&
                            <Checkbox
                              checked={!!hasSelect}
                              disabled={!!hasRelation}
                            />
                          }
  
                          {/* 文件不显示展开的图标 */}
                          {
                            isFolder &&
                            <div className="file-item__expend-icon">
                              <span className="icon iconfont">&#xe71b;</span>
                            </div>
                          }
                        </div>
                      )
                    }
                   
                  })
                }
              </div>
            </div>
          </When>
          <Otherwise>
            <LottieIcon
              title={<span className="desc">这个文件夹是空的</span>}
            />
          </Otherwise>
        </Choose>
        
        <UploadProgressModal
          isOpen={showUploadModal}
          fileList={localFileList}
          currentFolder={currentFolder}
          onUpload={this.handleUploadDone}
          onCancel={this.handleHiddenUploadModal}
        />

        <NonCompliantFileModal
          isOpen={showNonCompliantFileModal}
          fileList={nonCompliantFileList}
          onClose={() => {
            this.setState({ showNonCompliantFileModal: false });
          }}
          onOk={() => {
            this.setState({ showNonCompliantFileModal: false  });
            this.handleShowUploadModal(this.state.fileList)
          }}
        />

        { this.state.chargeModal }
      </Modal>
    )
  }
}

export default SelectPrepareFileModal;