const { ipcRenderer } = require('electron');

/** 包名 */
const PACKAGE_NAME = 'ccc-quick-finder';

// 创建 Vue 实例
new Vue({

  /**
   * 挂载目标
   * @type {string | Element}
   */
  el: "#app",

  /**
   * 数据对象
   */
  data: {
    /** 输入框占位符文本 */
    placeholder: '',
    /** 确认按钮文本 */
    button: '',
    /** 输入的关键字 */
    keyword: '',
    /** 关键词匹配返回的结果 */
    results: [],
    /** 当前选中的项目 */
    selected: null,
    /** 当前选中的项目下标 */
    selectedIndex: -1,
    /** 分段加载定时器 */
    loadHandler: null,
  },

  /**
   * 实例函数
   * @type {{ [key: string]: Function }}
   */
  methods: {

    /**
     * 输入框更新回调
     * @param {*} event 
     */
    onInputChange(event) {
      // 取消分帧加载
      if (this.loadHandler) {
        clearTimeout(this.loadHandler);
        this.loadHandler = null;
      }
      // 取消当前选中
      this.selected = null;
      this.selectedIndex = -1;
      // 关键字为空或无效时不进行搜索
      const keyword = this.keyword;
      if (keyword === '' || keyword.includes('...')) {
        this.results.length = 0;
        return;
      }
      // 发消息给主进程进行关键词匹配
      ipcRenderer.send(`${PACKAGE_NAME}:match-keyword`, keyword);
    },

    /**
     * 确认按钮点击回调
     * @param {*} event 
     */
    onEnterBtnClick(event) {
      const selected = this.selected;
      if (!selected) {
        if (this.keyword !== '') {
          // 输入框文本错误动画
          const input = this.$refs.input;
          input.classList.add('search-input-error');
          setTimeout(() => input.classList.remove('search-input-error'), 500);
        }
      } else {
        this.keyword = selected.name;
        // 发消息给主进程
        ipcRenderer.send(`${PACKAGE_NAME}:open`, selected.path);
      }
      // 聚焦到输入框(此时焦点在按钮或列表上)
      this.focusOnInputField();
    },

    /**
     * 上箭头按键回调
     * @param {*} event 
     */
    onUpBtnClick(event) {
      // 阻止默认事件(光标移动)
      event.preventDefault();
      // 循环选择
      if (this.selectedIndex > 0) {
        this.selectedIndex--;
      } else {
        this.selectedIndex = this.results.length - 1;
      }
      // 更新选择
      this.updateSelected();
    },

    /**
     * 下箭头按键回调
     * @param {*} event 
     */
    onDownBtnClick(event) {
      // 阻止默认事件(光标移动)
      event.preventDefault();
      // 循环选择
      if (this.selectedIndex >= this.results.length - 1) {
        this.selectedIndex = 0;
      } else {
        this.selectedIndex++;
      }
      // 更新选择
      this.updateSelected();
    },

    /**
     * 更新当前的选择
     */
    updateSelected() {
      this.selected = this.results[this.selectedIndex];
      this.keyword = this.selected.name;
      // 只有当目标元素不在可视区域内才滚动
      const id = `item-${this.selectedIndex}`;
      document.getElementById(id).scrollIntoViewIfNeeded(false);
    },

    /**
     * 左箭头按键回调
     * @param {*} event 
     */
    onLeftBtnClick(event) {
      // 是否已选中项目
      if (!this.selected) return;
      // 阻止默认事件(光标移动)
      event.preventDefault();
      // 在资源管理器中显示并选中文件
      this.showFileInAssets();
    },

    /**
     * 右箭头按键回调
     * @param {*} event 
     */
    onRightBtnClick(event) {
      // 是否已选中项目
      if (!this.selected) return;
      // 阻止默认事件(光标移动)
      event.preventDefault();
      // 在资源管理器中显示并选中文件
      this.showFileInAssets();
    },

    /**
     * 在资源管理器中显示并选中文件
     */
    showFileInAssets() {
      // 当前选中文件路径
      const path = this.selected.path;
      // 发消息给主进程
      ipcRenderer.send(`${PACKAGE_NAME}:focus`, path);
    },

    /**
     * 结果点击回调
     * @param {{ name: string, path: string, extname: string }} value 数据
     * @param {number} index 下标
     */
    onResultClick(value, index) {
      this.selectedIndex = parseInt(index);
      this.selected = value;
      this.keyword = value.name;
      // 添加组件
      this.onEnterBtnClick(null);
      // 聚焦到输入框(此时焦点在列表上)
      // 换成在 onEnterBtnClick 里统一处理了
      // this.focusOnInputField();
    },

    /**
     * 聚焦到输入框
     */
    focusOnInputField() {
      this.$refs.input.focus();
    },

    /**
     * (主进程)获取语言回调
     * @param {*} event 
     * @param {string} lang 语言
     */
    onGetLangReply(event, lang) {
      const texts = lang.includes('zh') ? zh : en;
      this.placeholder = texts.placeholder;
      this.button = texts.button;
    },

    /**
     * (主进程)匹配关键词回调
     * @param {*} event 
     * @param {{ name: string, path: string, extname: string }[]} results 结果
     */
    onMatchKeywordReply(event, results) {
      // 确保清除已有数据
      this.results.length = 0;
      // 当只有一个结果时直接选中
      if (results.length === 1) {
        this.results = results;
        this.selectedIndex = 0;
        this.selected = results[0];
        return;
      }
      // 结果数量多时分段加载
      if (results.length >= 300) {
        // 每次加载的数量
        const threshold = 150;
        // 分段加载函数
        const load = () => {
          const length = results.length,
            count = length >= threshold ? threshold : length,
            part = results.splice(0, count);
          // 加载一部分
          this.results.push(...part);
          // 是否还有数据
          if (results.length > 0) {
            // 下一波继续
            this.loadHandler = setTimeout(load);
          } else {
            // Done
            this.loadHandler = null;
          }
        }
        // 开始加载
        load();
        return;
      }
      // 数量不多,更新结果列表
      this.results = results;
    },

    /**
     * 获取图标
     * @param {string} extname 扩展名
     * @returns {string}
     */
    getIcon(extname) {
      const iconName = iconMap[extname] || 'asset';
      return `../../images/assets/${iconName}.png`;
    },

  },

  /**
   * 生命周期:实例被挂载
   */
  mounted() {
    // 监听事件
    ipcRenderer.on(`${PACKAGE_NAME}:get-lang-reply`, this.onGetLangReply.bind(this));
    ipcRenderer.on(`${PACKAGE_NAME}:match-keyword-reply`, this.onMatchKeywordReply.bind(this));
    // 发送事件:获取语言
    ipcRenderer.send(`${PACKAGE_NAME}:get-lang`);
    // (下一帧)聚焦到输入框
    this.$nextTick(() => this.focusOnInputField());
  },

  /**
   * 生命周期:实例销毁前
   */
  beforeDestroy() {
    // 取消事件监听
    ipcRenderer.removeAllListeners(`${PACKAGE_NAME}:get-lang-reply`);
    ipcRenderer.removeAllListeners(`${PACKAGE_NAME}:match-keyword-reply`);
  },

});

/** 多语言:中文 */
const zh = {
  placeholder: '请输入文件名称...',
  button: 'GO'
}

/** 多语言:英语 */
const en = {
  placeholder: 'Enter file name...',
  button: 'GO'
}

/** 文件扩展名对应图标表 */
const iconMap = {
  '.anim': 'animation-clip',
  '.prefab': 'prefab',
  '.fire': 'scene',
  '.scene': 'scene',
  '.effect': 'shader',
  '.mesh': 'mesh',
  '.FBX': 'mesh',
  '.mtl': 'material',
  '.pmtl': 'physics-material',
  '.pac': 'auto-atlas',
  '.ts': 'typescript',
  '.js': 'javascript',
  '.coffee': 'coffeescript',
  '.json': 'json',
  '.md': 'markdown',
  '.html': 'html',
  '.css': 'css',
  '.txt': 'text',
  '.ttf': 'ttf-font',
  '.fnt': 'bitmap-font',
  '.mp3': 'audio-clip',
  '.png': 'atlas',
  '.jpg': 'atlas',
  '.plist': 'sprite-atlas',
}