//
// 文件管理 模块
//

const LANG_T = antSword['language']['toastr'];
const LANG = antSword['language']['filemanager']['files'];
const clipboard = require('electron').clipboard;
const Terminal = require('../terminal/');

class Files {

  // 需要参数 1.cell: 左侧layout.cell对象 2.manager 主对象（index.jsx）
  constructor(cell, manager) {
    const self = this;
    cell.setText(`<i class="fa fa-file-o"></i> ${LANG['title']}`);
    // 创建toolbar
    const toolbar = cell.attachToolbar();
    // 加载本地缓存书签栏
    let bookmark = JSON.parse(manager.storage('bookmarks').get('{}'));
    // 重新加载书签
    this.reloadToolbar = () => {
      let bookmark_opts = [{
        id: 'bookmark_add',
        type: 'button',
        icon: 'plus-circle',
        text: LANG['bookmark']['add'],
        enabled: !bookmark[manager.path]
      }];
      let global_bookmarks = manager.config.bookmarks || {};
      if (Object.keys(global_bookmarks).length > 0) {
        bookmark_opts.push({
          type: 'separator'
        });
        for (let gb in global_bookmarks) {
          bookmark_opts.push({
            id: 'bookmark_' + global_bookmarks[gb],
            text: antSword.noxss(gb),
            icon: 'bookmark',
            type: 'button',
            enabled: manager.path !== global_bookmarks[gb]
          });
        }
      }
      if (!$.isEmptyObject(bookmark)) {
        bookmark_opts.push({
          type: 'separator'
        });
      };
      for (let _ in bookmark) {
        bookmark_opts.push({
          id: 'bookmark_' + _,
          text: antSword.noxss(bookmark[_]),
          icon: 'bookmark-o',
          type: 'button',
          enabled: manager.path !== _
        });
      }
      // 添加清除按钮
      if (bookmark_opts.length > 2) {
        bookmark_opts.push({
          type: 'separator'
        });
        bookmark_opts.push({
          id: 'bookmark_remove',
          icon: 'remove',
          text: LANG['bookmark']['del'],
          type: 'button',
          enabled: !!bookmark[manager.path]
        });
        bookmark_opts.push({
          id: 'bookmark_clear',
          icon: 'trash-o',
          text: LANG['bookmark']['clear'],
          type: 'button'
        });
      };

      toolbar.clearAll();
      toolbar.loadStruct([{
        id: 'new',
        type: 'buttonSelect',
        icon: 'plus-circle',
        text: LANG['toolbar']['new'],
        openAll: true,
        options: [{
          id: 'new_folder',
          icon: 'folder-o',
          type: 'button',
          text: LANG['toolbar']['folder']
        }, {
          id: 'new_file',
          icon: 'file-o',
          type: 'button',
          text: LANG['toolbar']['file']
        }, {
          type: 'separator'
        }, {
          id: 'new_wget',
          icon: 'cloud-download',
          type: 'button',
          text: LANG['toolbar']['wget']
        }, {
          id: 'new_upload',
          icon: 'cloud-upload',
          type: 'button',
          text: LANG['toolbar']['upload']
        }]
      }, {
        type: 'separator'
      }, {
        id: 'up',
        type: 'button',
        icon: 'arrow-up',
        text: LANG['toolbar']['up']
      }, {
        type: 'separator'
      }, {
        id: 'refresh',
        type: 'button',
        icon: 'refresh',
        text: LANG['toolbar']['refresh']
      }, {
        type: 'separator'
      }, {
        id: 'home',
        type: 'button',
        icon: 'home',
        text: LANG['toolbar']['home']
      }, {
        type: 'separator'
      }, {
        id: 'bookmark',
        type: 'buttonSelect',
        icon: 'bookmark',
        text: LANG['toolbar']['bookmark'],
        openAll: true,
        options: bookmark_opts
      }, {
        type: 'separator'
      }, {
        id: 'path',
        width: 300,
        type: 'buttonInput',
        value: antSword.noxss(manager.path) || 'loading..'
      }, {
        id: 'read_path',
        type: 'button',
        icon: 'arrow-right',
        text: LANG['toolbar']['read']
      }, {
        type: 'separator'
      }]);
    }

    this.reloadToolbar();
    // reloadToolbar(); this.reloadToolbar = reloadToolbar; toolbar点击事件
    toolbar.attachEvent('onClick', (id) => {
      switch (id) {
        case 'up':
          self.gotoPath('..');
          break;
        case 'refresh':
          self.refreshPath();
          break;
        case 'read_path':
          let pwd = toolbar
            .getInput('path')
            .value;
          self.gotoPath(pwd);
          break;
        case 'home':
          self.gotoPath(manager.home);
          break;
        case 'new_folder':
          manager.createFolder();
          break;
        case 'new_file':
          manager.createFile();
          break;
        case 'new_wget':
          manager.wgetFile();
          break;
        case 'new_upload':
          manager.uploadFile();
          break;
        case 'bookmark_add':
          // 添加书签
          layer.prompt({
            value: antSword.noxss(self.manager.path),
            title: LANG['prompt']['add']['title']
          }, (value, i, e) => {
            bookmark[self.manager.path] = value;
            self
              .manager
              .storage('bookmarks')
              .set(JSON.stringify(bookmark));
            toastr.success(LANG['prompt']['add']['success'](self.manager.path), LANG_T['success']);
            self.reloadToolbar();
            layer.close(i);
          });
          break;
        case 'bookmark_remove':
          layer.confirm(LANG['prompt']['remove']['confirm'], {
            icon: 2,
            shift: 6,
            title: `<i class="fa fa-remove"></i> ${LANG['prompt']['remove']['title']}`
          }, (_) => {
            // 删除书签并刷新
            delete bookmark[self.manager.path];
            self
              .manager
              .storage('bookmarks')
              .set(JSON.stringify(bookmark));
            self.reloadToolbar();
            toastr.success(LANG['prompt']['remove']['success'], LANG_T['success']);
            layer.close(_);
          });
          break;
        case 'bookmark_clear':
          layer.confirm(LANG['prompt']['clear']['confirm'], {
            icon: 2,
            shift: 6,
            title: `<i class="fa fa-trash-o"></i> ${LANG['prompt']['clear']['title']}`
          }, (_) => {
            bookmark = {};
            self
              .manager
              .storage('bookmarks')
              .set('{}');
            self.reloadToolbar();
            toastr.success(LANG['prompt']['clear']['success'], LANG_T['success']);
            layer.close(_);
          });
          break;
        default:
          let arr = id.split('_');
          if (arr.length === 2 && arr[0] === 'bookmark') {
            self.gotoPath(arr[1]);
          };
      }
    });
    toolbar.attachEvent('onEnter', (id, value) => {
      switch (id) {
        case 'path':
          self.gotoPath(value);
          break;
      }
    });
    // 创建grid
    let grid = cell.attachGrid();

    grid.setHeader(`
      &nbsp;,
      ${LANG['grid']['header']['name']},
      ${LANG['grid']['header']['time']},
      ${LANG['grid']['header']['size']},
      ${LANG['grid']['header']['attr']}
    `);
    grid.setColTypes("ro,ro,ro,ro,ro");
    grid.setColSorting('str,str,str,str,str');
    grid.setInitWidths("40,*,150,100,100");
    grid.setColAlign("center,left,left,right,center");
    grid.enableMultiselect(true);
    // grid.enableDragAndDrop(true); grid.enableMultiline(true); grid右键 空白数据右键fix
    $('.objbox').on('contextmenu', (e) => {
      (e.target.nodeName === 'DIV' && grid.callEvent instanceof Function && antSword['tabbar'].getActiveTab().startsWith('tab_filemanager_')) ?
      grid.callEvent('onRightClick', [-1, -1, e]): null;
    });
    $('.objbox').on('click', (e) => {
      bmenu.hide();
    });
    grid.attachEvent('onRightClick', function(id, lid, event) {

      // 获取选中ID列表
      let _ids = (this.getSelectedId() || '').split(',');
      // 如果是空白右键
      if (id === -1) {
        _ids = [ // 如果没有选中？则选中右键对应选项
        ];
      } else if (_ids.length === 1) {
        this.selectRowById(id);
        _ids = [id];
      };
      let ids = [];
      _ids.map((_) => {
        ids.push(this.getRowAttribute(_, 'fname'));
      });
      id = ids[0] || '';

      // 获取剪贴板内容
      let _Clipboard = [];
      let _Clipboard_num = 0;
      for (let c in self.Clipboard) {
        _Clipboard.push({
          text: antSword.noxss(c),
          icon: 'fa fa-' + (c.endsWith('/') ?
            'folder-o' :
            'file-o'),
          action: ((source, name) => {
            return () => {
              manager.pasteFile(source, name);
            }
          })(self.Clipboard[c], c)
        });
        _Clipboard_num++;
        if (!(_Clipboard_num % 5)) {
          _Clipboard.push({
            divider: true
          });
        };
      }
      // 清除最后的divider if (_Clipboard.length % 5 && _Clipboard_num > 5) {
      // _Clipboard.pop() }; all item
      if (_Clipboard.length > 0) {
        _Clipboard.unshift({
          divider: true
        });
        _Clipboard.unshift({
          text: LANG['grid']['contextmenu']['paste']['all'],
          count: _Clipboard_num,
          icon: 'fa fa-th-list',
          action: () => {
            _Clipboard.map((c) => {
              if (c['divider'] || c['count'] || c['text'] === LANG['grid']['contextmenu']['paste']['clear']['title']) {
                return
              };

              let name = c['text'];
              let source = self.Clipboard[name];

              manager.pasteFile(source, name);

            });
          }
        });
        // 清空剪贴板
        !(_Clipboard[_Clipboard.length - 1].divider) ?
        _Clipboard.push({
          divider: true
        }): 0;
        _Clipboard.push({
          text: LANG['grid']['contextmenu']['paste']['clear']['title'],
          icon: 'fa fa-trash-o',
          action: () => {
            self.Clipboard = {};
            toastr.info(LANG['grid']['contextmenu']['paste']['clear']['info'], LANG_T['info']);
          }
        });
      };

      let isFolder = id.endsWith('/');
      let containsFolder = (ids.join("~assep~") + '~assep~').indexOf('/~assep~') > -1;
      // 可编辑文件后缀
      let isEdited = false;
      'php,asp,aspx,jsp,cfm,js,css,html,py,sh,bat,txt,log,ini,conf,sql'
      .split(',')
        .map((e) => {
          id
            .toLowerCase()
            .endsWith(`.${e}`) ?
            isEdited = true :
            0;
        });

      let menu = [{
        text: LANG['grid']['contextmenu']['refresh'],
        icon: 'fa fa-refresh',
        action: () => {
          self.refreshPath();
        }
      }, {
        divider: true
      }, {
        text: LANG['grid']['contextmenu']['wget'],
        icon: 'fa fa-cloud-download',
        action: manager
          .wgetFile
          .bind(manager)
      }, {
        text: LANG['grid']['contextmenu']['upload'],
        icon: 'fa fa-upload',
        action: manager
          .uploadFile
          .bind(manager)
      }, {
        text: LANG['grid']['contextmenu']['download'],
        icon: 'fa fa-download',
        disabled: isFolder || !id || containsFolder,
        action: () => {
          if (ids.length === 1) {
            manager.downloadFile(id, this.getRowAttribute(_ids[0], 'fsize'));
          } else if (ids.length > 1) {
            let dnames = [];
            for (let i = 0; i < ids.length; i++) {
              dnames.push({
                name: ids[i],
                size: this.getRowAttribute(_ids[i], 'fsize'),
              });
            }
            manager.downloadFileMulti(dnames);
          }
        }
      }, {
        divider: true
      }, {
        text: LANG['grid']['contextmenu']['copy']['title'],
        icon: 'fa fa-copy',
        subMenu: [{
          text: LANG['grid']['contextmenu']['copy']['title'],
          icon: 'fa fa-copy',
          disabled: !id,
          action: () => {
            // 如果只有一个id，则显示id名称，否则显示ids数量
            ids.map((id) => {
              let path = manager.path + id;
              // 判断是否已经复制
              if (id in self.Clipboard) {
                return toastr.warning(LANG['grid']['contextmenu']['copy']['warning'](id), LANG_T['warning']);
              };
              self.Clipboard[id] = path;
              toastr.info(LANG['grid']['contextmenu']['copy']['info'](id), LANG_T['info']);
            });
          }
        }, {
          text: LANG['grid']['contextmenu']['copy']['copyname'],
          icon: 'fa fa-file-word-o',
          disabled: !id || ids.length > 1,
          action: () => {
            clipboard.writeText(id);
            // 检测是否复制成功
            let txt = clipboard.readText();
            if (txt == id) {
              toastr.success(LANG['grid']['contextmenu']['copy']['copysuccess'], LANG_T['success']);
            } else {
              toastr.error(LANG['grid']['contextmenu']['copy']['copyfail'], LANG_T['error']);
            }
          }
        }, {
          text: LANG['grid']['contextmenu']['copy']['copypath'],
          icon: 'fa fa-file-powerpoint-o',
          disabled: !id || ids.length > 1,
          action: () => {
            let txt = `${self.manager.path}${id}`;
            clipboard.writeText(txt);
            // 检测是否复制成功
            let cptxt = clipboard.readText();
            if (cptxt == txt) {
              toastr.success(LANG['grid']['contextmenu']['copy']['copysuccess'], LANG_T['success']);
            } else {
              toastr.error(LANG['grid']['contextmenu']['copy']['copyfail'], LANG_T['error']);
            }
          }
        }]
      }, {
        text: LANG['grid']['contextmenu']['paste']['title'],
        icon: 'fa fa-paste',
        disabled: _Clipboard_num === 0,
        subMenu: _Clipboard
      }, {
        text: LANG['grid']['contextmenu']['preview'],
        icon: 'fa fa-eye',
        disabled: !id || ids.length > 1 || !self.checkPreview(id),
        action: () => {
          manager.previewFile(id, this.getRowAttribute(_ids[0], 'fsize'));
        }
      }, {
        text: LANG['grid']['contextmenu']['filehash'],
        icon: 'fa fa-legal',
        disabled: isFolder || !id || containsFolder,
        action: () => {
          manager.fileHash(id);
        }
      }, {
        divider: true
      }, {
        text: LANG['grid']['contextmenu']['edit']['title'],
        icon: 'fa fa-edit',
        disabled: /*!isEdited || */
          !id || ids.length > 1 || isFolder,
        subMenu: [{
          text: LANG['grid']['contextmenu']['edit']['opentab'],
          icon: 'fa fa-external-link',
          action: () => {
            manager.editFile(id, true);
          }
        }, {
          text: LANG['grid']['contextmenu']['edit']['openwindow'],
          icon: 'fa fa-arrows-alt',
          action: () => {
            manager.editFile(id, false);
          }
        }]
      }, {
        text: LANG['grid']['contextmenu']['delete'],
        icon: 'fa fa-trash-o',
        disabled: !id,
        action: () => {
          manager.deleteFile(ids);
        }
      }, {
        text: LANG['grid']['contextmenu']['rename'],
        icon: 'fa fa-font',
        disabled: !id || ids.length > 1,
        action: () => {
          manager.renameFile(id);
        }
      }, {
        text: LANG['grid']['contextmenu']['modify'],
        icon: 'fa fa-clock-o',
        disabled: !id || ids.length > 1,
        action: () => {
          // manager.retimeFile(id, this.rowsAr[id]['cells'][2].innerText);
          manager.retimeFile(id, this.getRowAttribute(_ids[0], 'data')[2]);
        }
      }, {
        text: LANG['grid']['contextmenu']['chmod'],
        icon: 'fa fa-users',
        disabled: !id || ids.length > 1,
        action: () => {
          manager.chmodFile(id, this.getRowAttribute(_ids[0], 'data')[4]);
        }
      }, {
        divider: true
      }, {
        text: LANG['grid']['contextmenu']['create']['title'],
        icon: 'fa fa-plus-circle',
        subMenu: [{
          text: LANG['grid']['contextmenu']['create']['folder'],
          icon: 'fa fa-folder-o',
          action: manager
            .createFolder
            .bind(manager)
        }, {
          text: LANG['grid']['contextmenu']['create']['file'],
          icon: 'fa fa-file-o',
          action: manager
            .createFile
            .bind(manager)
        }]
      }, {
        text: LANG['grid']['contextmenu']['terminal'],
        icon: 'fa fa-terminal',
        action: () => {
          new Terminal(self.manager.opts, {
            'path': self.manager.path
          });
        }
      }];

      bmenu(menu, event);

      return true;
    });

    // 选择事件
    grid.attachEvent('onRowSelect', (id, lid, event) => {
      bmenu.hide();
    });

    // 双击文件 :如果可预览并且小于 1MB，则进行预览 :如果size < 100kb，则进行编辑，否则进行下载
    grid.attachEvent('onRowDblClicked', (id, lid, event) => {
      const fname = grid.getRowAttribute(id, 'fname');
      const fsize = grid.getRowAttribute(id, 'fsize');
      if (!fname.endsWith('/')) {
        if (self.checkPreview(fname) && fsize <= 1000 * 1024) {
          manager.previewFile(fname, fsize);
        } else if (fsize <= 100 * 1024) {
          // 双击编辑size < 100kb 文件
          manager.editFile(fname, self.manager.config.openfileintab);
        } else {
          manager.downloadFile(fname, fsize);
        }
      } else {
        self.gotoPath(fname);
      }
    });

    // 键盘按下事件
    grid.attachEvent('onKeyPress', (code, cFlag, sFlag) => {
      switch (true) {
        case (code <= 90 && code >= 65) || (code <= 57 && code >= 48):
          // A-Z 0-9
          var input = String.fromCharCode(code);
          input = input.toLowerCase();
          var sid = 0;
          var ids = grid
            .getAllRowIds()
            .split(",");
          for (var i = 0; i < ids.length; i++) {
            var _id = parseInt(ids[i]);
            var fname = grid.getRowAttribute(_id, "fname");
            if (fname.startsWith(input)) {
              sid = _id - 1;
              grid.selectRow(sid);
              break;
            }
          }
          break
        case (code == 38):
          //up
          var ids = grid
            .getAllRowIds()
            .split(",");
          var sid = grid
            .getSelectedRowId()
            .toString();
          var cid = ids.indexOf(sid) <= 0 ?
            parseInt(ids[0]) - 1 :
            parseInt(ids[ids.indexOf(sid) - 1]) - 1;
          grid.selectRow(cid);
          break;
        case (code == 40):
          //down
          var ids = grid
            .getAllRowIds()
            .split(",");
          var sid = grid
            .getSelectedRowId()
            .toString();
          var cid = ids.indexOf(sid) >= ids.length - 1 ?
            parseInt(ids[ids.length - 1]) - 1 :
            parseInt(ids[ids.indexOf(sid) + 1]) - 1;
          grid.selectRow(cid);
          break;
        default:
          break;
      }
    });

    grid.init();

    this.grid = grid;
    this.cell = cell;
    this.toolbar = toolbar;
    this.manager = manager;

    // 剪贴板
    this.Clipboard = {};

    // 文件拖拽上传
    $(this.cell.cell).on({
      dragleave: (e) => {
        e.preventDefault()
      },
      drop: (e) => {
        e.preventDefault();
        let filePaths = [];
        let files = e.originalEvent['dataTransfer']['files'] || {};
        for (let i = 0; i < files.length; i++) {
          let f = files.item(i);
          filePaths.push(f['path']);
        }
        this
          .manager
          .uploadFile(filePaths);
      },
      dragenter: (e) => {
        e.preventDefault()
      },
      dragover: (e) => {
        e.preventDefault()
      }
    });
  }

  checkPreview(name) {
    // 可预览文件后缀
    let isPreviewed = false;
    'jpeg,jpg,png,gif,bmp,ico'
    .split(',')
      .map((e) => {
        name
          .toLowerCase()
          .endsWith(`.${e}`) ?
          isPreviewed = true :
          0;
      });
    return isPreviewed;
  }

  // 刷新当前目录 如果传递路径参数，则刷新该路径下的文件，不跳转，否则刷新&&跳转
  refreshPath(p) {
    let path = p || this.manager.path;
    // delete this.manager.cache[path];
    this
      .manager
      .cache
      .del('filemanager-files-' + Buffer.from(path).toString('base64'));
    // 删除文件夹缓存
    for (let _ in this.manager.folder.cache) {
      if (_.indexOf(path) === 0 && _ != path) {
        delete this.manager.folder.cache[_];
      }
    }
    if (!p) {
      this.gotoPath('.')
    };
  }

  // 跳转目录
  gotoPath(path) {
    let self = this;
    this
      .cell
      .progressOn();
    try {
      this
        .manager
        .getFiles(path, (files) => {
          self.parse(files);
          self
            .manager
            .folder
            .parse(files);
          // self.cell.progressOff();
        });
    } catch (e) {
      toastr.error(e, LANG_T['error']);
      self
        .cell
        .progressOff();
    }
  }

  // 解析数据
  parse(files) {

    let data = [];
    let self = this;
    let _id = 1;
    files.map((file) => {
      if (!file['name'] || ['./', '../'].indexOf(file['name']) != -1) {
        return
      };
      data.push({
        id: _id,
        fname: file['name'],
        fsize: parseInt(file['size']),
        // 如果是可执行文件（exe、dll..），则设置为红色字体
        style: /\.exe$|\.dll$|\.bat$|\.sh$|\.com$/.test(file['name']) ?
          'color:red' : '',
        data: [
          self.fileIcon(file['name']),
          antSword.noxss(file['name'].replace(/\/$/, '')),
          antSword.noxss(file['time']),
          antSword.noxss(self.fileSize(parseInt(file['size']))),
          antSword.noxss(file['attr'])
        ]
      });
      _id++;
    });

    this
      .cell
      .setText(`<i class="fa fa-file-o"></i> ${LANG['title']} (${data.length})`);
    this
      .grid
      .clearAll();
    this
      .grid
      .parse({
        'rows': data
      }, 'json');

    // 设置path路径
    this
      .toolbar
      .getInput('path')
      .value = this.manager.path;

    this
      .cell
      .progressOff();
    this.reloadToolbar();
  }

  // 文件大小计算
  fileSize(t) {
    let i = false;
    let b = [
      "b",
      "Kb",
      "Mb",
      "Gb",
      "Tb",
      "Pb",
      "Eb"
    ];
    for (let q = 0; q < b.length; q++)
      if (t > 1024)
        t = t / 1024;
      else if (i === false)
      i = q;
    if (i === false)
      i = b.length - 1;
    return Math.round(t * 100) / 100 + " " + b[i];
  }

  // 返回文件图标
  fileIcon(name) {
    let icons = {};
    const _icons = {
      'exe,dll': 'file',
      'jpg,png,gif,ico,bmp': 'file-image-o',
      'mp4,mpeg,avi,rm,rmvb': 'file-movie-o',
      'mp3,mid,wav': 'file-sound-o',
      'pdf': 'file-pdf-o',
      'ppt': 'file-powerpoint-o',
      'xls,xlsx': 'file-excel-o',
      'doc,docx': 'file-word-o',
      'zip,tar,7z,gz,rar': 'file-archive-o',
      'txt,ttf,tiff,ini,log,chm,conf,cfg': 'file-text-o',
      'php,asp,jsp,sql,cfm,aspx,html,js,py,rb,pl,go,css,less,jsx,xml,sh,bat,h,cpp,c': 'file-code-o'
    };
    for (let _ in _icons) {
      let _arr = _.split(',');
      _arr.map((a) => {
        icons[a] = _icons[_];
      });
    }
    // 默认图标
    let icon = 'file-o';
    // 判断是否为文件夹
    if (name.endsWith('/')) {
      icon = 'folder-o';
    } else {
      let _ = name.split('.');
      let ext = _[_.length - 1].toLowerCase();
      icon = icons[ext] || icon;
    };
    return `<i class="fa fa-${icon} fa-lg"></i>`;
  }

}

// export default Files;
module.exports = Files;