<template>
  <div class="wrap">
    <div class="left">
      <codemirror
        v-model="codeVal"
        :options="cmOption"
        class="code-mirror"
        @ready="ready"
        ref="codemirror"
      ></codemirror>
      <el-button
        class="run btn"
        type="primary"
        @click="runCode"
      >运行</el-button>
    </div>
    <div class="code-right answer">
      <p class="text-wrapper">{{ runResult }}</p>
      <div class="pic-wrap" v-if="picSrcList.length">
        <div class="pic-item" v-for="(img, i) in picSrcList" :key="i">
          <el-image 
            class="pic"
            :src="img" 
            :preview-src-list="picSrcList">
          </el-image>
          <el-button class="download-btn btn" type="primary" size="mini" @click="downloadPic(i)">下载图片</el-button>
          <a :ref="'picLink' + i" style="display: none;" download="运行结果.png" :href="img">下载图片</a>
        </div>
      </div>
      <div class="result-right t-color" v-show="isError">
        <img src="@/assets/img/yes.png" alt />运行成功
      </div>
      <div class="result-wrong" v-show="isError === 0">
        <img src="@/assets/img/error.png" alt />
        第{{errLine}}行出现错误
      </div>
    </div>
  </div>
</template>

<script>
import { codemirror } from "vue-codemirror";
import "codemirror/theme/ambiance.css"; // 这里引入的是主题样式
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/python/python.js";
import "codemirror/lib/codemirror.css";
// require active-line.js
import "codemirror/addon/selection/active-line.js";
// styleSelectedText
import "codemirror/addon/selection/mark-selection.js";
// hint
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/sql-hint.js";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/addon/hint/javascript-hint.js";
// highlightSelectionMatches
import "codemirror/addon/scroll/annotatescrollbar.js";
import "codemirror/addon/search/matchesonscrollbar.js";
import "codemirror/addon/search/match-highlighter.js";
// keyMap
import "codemirror/mode/clike/clike.js";
import "codemirror/mode/sql/sql.js";
import "codemirror/addon/edit/matchbrackets.js";
import "codemirror/addon/comment/comment.js";
import "codemirror/addon/dialog/dialog.js";
import "codemirror/addon/dialog/dialog.css";
import "codemirror/addon/search/searchcursor.js";
import "codemirror/addon/search/search.js";
import "codemirror/keymap/sublime.js";
// foldGutter
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/xml-fold.js";
// 编辑的主题文件
import "codemirror/theme/monokai.css";
import "codemirror/theme/base16-light.css";
import { Loading } from 'element-ui';
export default {
  props: ['code', 'codeId', 'projectId', 'retResult', 'readOnly'],
  data() {
    return {
      codeVal: this.code,
      runResult: '', // 运行结果
      isError: false, // 运行正确与否
      errLine: '', // 错误代码的位置
      picSrcList: [],
      loadIns: null, // loading实例
      cmOption: {
        readOnly: this.readOnly,
        scrollbarStyle: "native",
        tabSize: 2, // tab
        styleActiveLine: true, // 高亮选中行
        lineNumbers: true, // 显示行号
        styleSelectedText: true,
        line: true,
        foldGutter: true, // 块槽
        gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
        highlightSelectionMatches: { showToken: /\w/, annotateScrollbar: true }, // 可以启用该选项来突出显示当前选中的内容的所有实例
        mode: 'python',
        lineWrapping: true, //代码折叠
        autoCloseTags: true,// 自动闭合标签
        autoCloseBrackets: true,// 自动闭合括号
        // hint.js options
        hintOptions: {
          // 当匹配只有一项的时候是否自动补全
          completeSingle: false
        },
        // 快捷键 可提供三种模式 sublime、emacs、vim
        keyMap: "sublime",
        matchBrackets: true,
        showCursorWhenSelecting: true,
        theme: "monokai" // 主题
      }
    };
  },
  components: {
    codemirror
  },
  watch: {
    codeVal(val) {
      this.$emit("update:code", val)
    }
  },
  mounted() {
    
  },
  methods: {
    // 页面加载完后重置编辑框大小
    ready() {
      const code = this.$refs.codemirror.codemirror
      code.setSize("auto", "calc(100vh - 370px)");
      code.on('keypress', function() {
        // 显示智能提示
        code.showHint()
      });
    },
    // 运行代码
    runCode() {
      let code = this.codeVal
      if (!code) {
        this.$message({
          message: "警告哦，内容为空不可运行",
          type: "warning"
        })
      } else {
        this.loadIns = Loading.service({
          background: 'transparent'
        })
        code = code.replace(/\.savefig\(([\u4e00-\u9fa5\w]*?['"])/mg, str => {
          return str + Date.now()
        })
        // 把代码传给后端，在后端运行Python代码
        this.$post(this.api.runPythonCode, {
          code
        }).then(res => {
          const data = res.code
          const photo = data.photoUrl
          const result = data.runResult
          this.$emit('cache') // 每次运行代码都要把代码传给后端做缓存
          this.loadIns.close()
          this.picSrcList = []
          if (photo) this.picSrcList = photo.split(',')
          let imgList = ''
          let firtImg = ''
          try {
            imgList = eval(result)
          } catch (error) {}
          if (imgList && imgList.length) firtImg = imgList[0]
          // 如果是下载图片的代码，则要显示图片和运行结果，不用显示对错，换成显示下载图片
          if (photo) {
            this.isError = '' // 对错隐藏
            const text = result.replace(photo, '') // 结果里包含了图片路径，所以要把图片路径给去掉
            this.runResult = text
            this.picSrcList = photo.split(',')
          } else if (imgList instanceof Array && imgList.length && typeof firtImg === 'string' && (firtImg.includes('.jpg') || firtImg.includes('.png') || firtImg.includes('img'))) {
            /**
             * 这段是为要下载图片的项目案例写的，后端会返回图片名称的数组，前端负责循环这个数组，然后下载下来
             * 只有该系统有这段代码，因为其他7个系统没有下载图片的项目，后续如果加了，直接把这段代码复制过去即可
             */
            imgList.map((n,i) => {
              // util.downloadFile(`${i+1}.jpg`,n)
            })
            this.isError = 0
            this.runResult = '下载完成'
          } else {
            this.isError = data.retResult
            this.runResult = result
            this.errLine = parseInt(result.substring(result.indexOf("line") + 4, result.length))
          }
        }).catch(res => {
          res.status == 500 && this.$message.error('检测到代码里有非法代码，请检查是否有调用系统命令。')
          this.loadIns.close()
        })
      }
    },
    // 下载图片
    downloadPic(i) {
      this.$refs['picLink' + i][0].click()
    }
  }
};
</script>

<style lang="scss" scoped>
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-thumb {
  width: 5px;
  border-radius: 6px;
  background: rgba(173,173,173,.7);
}
.wrap {
  display: flex;
}
.left{
  position: relative;
  width: calc(100% - 400px);
}
.text-wrapper {
  white-space: pre-wrap;
}
/deep/.answer {
  .el-tab-pane {
    padding: 0 10px;
    height: 340px;
    overflow: hidden;
    overflow-y: auto;
    white-space: pre-wrap;
  }
  .el-dialog--center {
    width: 500px;
    height: 500px;
  }
  .el-dialog__title {
    font-size: 22px;
    font-weight: 500;
  }
  .el-tabs__nav-wrap::after {
    background-color: #333;
  }
  .el-tabs__active-bar {
    height: 0;
    background-color: #fff;
  }
  .el-tabs__header {
    background-color: #333;
  }
  .el-dialog--center .el-dialog__body {
    padding: 0;
  }
  .el-tabs__item {
    width: 80px;
    color: #fff;
  }
  .el-tabs--top .el-tabs__item.is-top:nth-child(2) {
    padding-left: 20px;
  }
  .el-tabs__item.is-active {
    color: #fff !important;
    background-color: #333 !important;
  }
  .tips-btn {
    margin-top: 10px;
    height: 40px;
    width: 90px;
    border: none;
    position: absolute;
    right: 0;
    background: rgba(255, 49, 49, 1);
    color: rgba(255, 255, 255, 1);
    &:hover,
    &:focus,
    &:active {
      background: rgba(255, 49, 49, 1);
      color: rgba(255, 255, 255, 1);
    }
  }
}
/deep/.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
  height: 30px;
  line-height: 30px;
}
.result-right {
  background-color: rgba(43, 40, 22, 1);
}
.result-wrong {
  background-color: rgba(43, 22, 22, 1);
  color: #f00;
}
.result-wrong,
.result-right {
  position: absolute;
  left: 20px;
  right: 20px;
  display: flex;
  align-items: center;
  bottom: 10px;
  padding: 5px 10px;
  img {
    width: 40px;
    height: 40px;
    margin-top: 5px;
    margin-right: 10px;
  }
}
.code-right {
  width: 500px;
  color: #fff;
  background: #1b1b1b;
  display: inline-block;
  position: relative;
  overflow-x: auto;
  p {
    font-size: 18px;
    margin: 10px;
    position: absolute;
    width: calc(100% - 14px);
    top: 0;
    bottom: -8px;
    overflow: auto;
  }
}
.pic-wrap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 5px;
  display: flex;
  max-width: calc(100% - 50px);
  margin: 0 auto;
  text-align: center;
  overflow: auto;
  .pic-item {
    margin: 0 5px 5px;
    &:only-child {
      .pic {
        width: 80%;
      }
    }
  }
  .pic {
    display: block;
    width: 100px;
    margin: 0 auto 10px;
  }
}
.code-mask{
  z-index: 2;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}
.run{
  z-index:99;
  position:absolute;
  right: 50px; 
  bottom:15px;
  width:100px;
  color:#fff;
}
.download-btn{
  color:#fff;
}
/deep/.answer-wrap{
  pre{
    width: 100%;
    white-space: pre-wrap;
  }
  img{
    max-width: 100%;
  }
}
</style>