<template>
    <PageHeader :title="title">
        <template #action>
            <Switch true-color="#13ce66" size="large" false-color="#17233d" v-model="state" :true-value="1" :false-value="0">
                <template #open>增量</template>
                <template #close>全量</template>
            </Switch>
        </template>
        <template #content>
            <Space>
                <Select v-model="searchinfo.product" style="width:260px" placeholder="请输入项目">
                    <Option v-for="item in proList" :value="item" :key="item">{{ item }}</Option>
                </Select>
                <Input v-model="searchinfo.commit_source" placeholder="请输入初始分支" clearable style="width: 260px" />
                <Input v-model="searchinfo.commit_target" placeholder="请输入结束分支" clearable style="width: 260px" />
                <Input v-model="searchinfo.product_key" placeholder="请输入标签" clearable style="width: 260px" />
                <Button type="primary" @click="setReport()">获取报告</Button>
            </Space>
        </template>
    </PageHeader>

    <Tabs size="large" type="card" closable @on-tab-remove="handleTabRemove" draggable @on-drag-drop="handleDragDrop"
        :animated="false" v-model="choicedkey">
        <template v-for="item_1 in keys">
            <TabPane :label='item_1' :name="item_1">
                <a style="font-size: large;" @click="choicePath(-1)">{{ item_1 }}&nbsp;</a>
                <a v-for="m in path" @click="choicePath(m)" style="font-size: large;">/&nbsp;{{ m }}&nbsp;</a>
                <div class="demo-spin-article" style="height: 630px;overflow: auto;">
                    <table class="table table-bordered">
                        <thead>
                            <tr>
                                <td>&nbsp;</td>
                                <td colspan="9">
                                    <div align="center"><strong>代码覆盖率</strong></div>
                                </td>
                            </tr>
                            <tr>
                                <td>&nbsp;</td>
                                <td colspan="3">
                                    <div align="center"><strong>行覆盖</strong></div>
                                </td>
                                <td colspan="3">
                                    <div align="center"><strong>函数覆盖</strong></div>
                                </td>
                                <td colspan="3">
                                    <div align="center"><strong>类覆盖</strong></div>
                                </td>
                            </tr>
                        </thead>
                        <tbody>
                            <template v-for="item in dirInfo">
                                <tr v-if="!state||state&&item.change">
                                    <td :class="getStatus(item, 0, 1)" v-if="item.source == 'Total'">总计</td>
                                    <td :class="getStatus(item, 0, 1)" v-else>
                                        <template v-if="!render_type">
                                            <img src="@/assets/file-directory.svg"
                                                class="octicon">
                                            <a @click="path.push(item.source)">{{ item.source }}</a>
                                        </template>
                                        <template v-else>
                                            <template v-if="item.start != 0 && !item.start">
                                                <abbr :title="path.join('/').slice(0, path.join('/').indexOf('.'))">{{
                                                    item.source }}</abbr>
                                            </template>
                                            <template v-else>
                                                &nbsp;
                                                <a :href="'#' + item.start"><abbr :title="item.source + '()'">{{ item.source
                                                        }}</abbr></a>
                                            </template>
                                        </template>
                                    </td>
                                    <template v-for="i in [0, 1, 2]">
                                        <template v-if="getStatus(item, 0, i) != ''">
                                            <td :class="getStatus(item, 0, i) + ' big'">
                                                <div class="progress">
                                                    <div :class="'progress-bar ' + getStatus(item, 1, i)"
                                                        role="progressbar" :aria-valuenow="getProgerss(item, 0, i)"
                                                        aria-valuemin="0" aria-valuemax="100"
                                                        :style="'width: ' + getProgerss(item, 1, i) + '%'">
                                                        <span class="sr-only">{{ getProgerss(item, 0, i) }}% covered ({{
                                                            getStatus(item, 0, i)
                                                            }})</span>
                                                    </div>
                                                </div>
                                            </td>
                                            <td :class="getStatus(item, 0, i) + ' small'">
                                                <div align="right">{{ getProgerss(item, 0, i) }}%</div>
                                            </td>
                                            <td :class="getStatus(item, 0, i) + ' small'">
                                                <div align="right">
                                                    {{ getcoverInfo(item, i)[1] }}&nbsp;/&nbsp;{{ getcoverInfo(item,
                                                        i)[0]
                                                    }}
                                                </div>
                                            </td>
                                        </template>
                                    </template>
                                </tr>
                            </template>
                        </tbody>
                    </table>
                    <table style="width: 100%;" v-html="fileAll" v-if="render_type && !state">
                    </table>
                    <table style="width: 100%;" v-html="fileChange" v-if="render_type && state"></table>
                    <Spin size="large" fix :show="spinShow"></Spin>
                </div>
            </TabPane>
            <Modal v-model="modal" title="添加预警" @on-ok="addLogs" @on-cancel="modal = false">
                <p>该标签页已存在，确认提交将更改原同名标签</p>
            </Modal>
        </template>
    </Tabs>
</template>

<script setup>
import { ref, getCurrentInstance, reactive, onMounted, watch } from 'vue'

const { proxy, ctx } = getCurrentInstance()

let Message = proxy.$Message
let request = proxy.$request

const page_id = ref(22)

const title = ref("代码覆盖率")

const path = ref([])

const keys = ref([])

const modal = ref(false)

const choicedkey = ref(null)

const spinShow=ref(false)

const proList = ref(['galaxy-crm', 'ServerSiteMirocs', 'PresaleMicros','FlowMicros'])


/**
 * 0-目录级渲染 1-文件级渲染
 */
const render_type = ref(0)

const dirInfo = ref([

])

const fileAll = ref(null)

const fileChange = ref(null)

const searchinfo = reactive({
    product: null,
    product_key: null,
    commit_source: null,
    commit_target: null
})

/**
 * 0-全量 1-增量
 */
const state = ref(localStorage.getItem('state')&&parseInt(localStorage.getItem('state'))||0)

/**
 * 
 * @param item 
 * @param who 0-行信息 1-方法信息 2-类信息
 */
function getcoverInfo(item, who) {
    let all = null
    let cover = null
    if (state.value == 0) {
        if (who == 0) {
            all = item.all_lines
            cover = item.cover_lines
        } else if (who == 1) {
            all = item.all_function
            cover = item.cover_function
        } else if (who == 2) {
            all = item.all_class
            cover = item.cover_class
        }
    } else {
        if (who == 0) {
            all = item.change_lines
            cover = item.add_cover_lines
        } else if (who == 1) {
            all = item.change_function
            cover = item.add_cover_function
        } else if (who == 2) {
            all = item.change_class
            cover = item.add_cover_class
        }
    }
    return [all, cover]
}


/**
* type 0-返回字符串类型，1-返回number类型
* who 0-行 1-函数 2-类
*/
function getProgerss(item, type, who) {
    let [all, cover] = getcoverInfo(item, who)
    if (!all) return type ? 0 : 0.00.toString()
    return type ? Math.round(cover * 100 / all) : (cover * 100 / all).toFixed(2)
}


/**
* type 0 外部 1-进度条
* who 0-行 1-函数 2-类
*/
function getStatus(item, type, who) {
    let [all, cover] = getcoverInfo(item, who)
    if (all == -1) return ''
    if (!cover && cover != 0) return ''
    if  ( all==0 || (cover / all) < 0.5) {
        return type ? 'bg-danger' : 'danger'
    } else if ((cover / all) < 0.9) {
        return type ? 'bg-warning' : 'warning'
    } else {
        return type ? 'bg-success' : 'success'
    }
}

function choicePath(a) {
    if (a == -1) {
        return path.value.length = 0
    }
    if (path.value.findIndex((each) => { return each == a }) == path.value.length - 1) return
    else {
        path.value = path.value.slice(0, path.value.findIndex((each) => { return each == a }) + 1)
    }
}

function getLogs(callback = () => { }) {
    request("get", "/codecover/logs", null, this, (a) => { keys.value = a.data; callback() })
}

function addLogs() {
    request("post", "/codecover/addlog", searchinfo, this, () => {
        choicedkey.value = searchinfo.product_key; searchinfo.product = null; searchinfo.product_key = null; searchinfo.commit_source = null; searchinfo.commit_target = null;getLogs(); 
    })
}

function setReport() {
    if (!(searchinfo.product && searchinfo.product_key && searchinfo.commit_source && searchinfo.commit_target)) {
        return Message.error('请完善信息')
    } else if (keys.value.indexOf(searchinfo.product_key) != -1) {
        return modal.value = true
    } else {
        addLogs()
    }
}

function handleTabRemove(q) {
    request("post", "/codecover/rmlog", { product_key: q }, this, () => {
        getLogs()
        if (choicedkey.value == q) choicedkey.value = keys.value[0]
    })
}

function handleDragDrop(name, newName, a, b, names) {
    console.info(a, b)
    request("post", "/codecover/swap", [keys.value[a], keys.value[b]], this, () => {
        getLogs()
    })
}


watch(
    () => choicedkey.value,
    (newVal, oldVal) => {
        path.value.length = 0
        render_type.value = 0
        console.info(newVal, oldVal)
        request("get", "/codecover/dirinfo", { key: newVal, path: path.value.join('/') }, this, (res) => {
            dirInfo.value = res.data
        })
    })

watch(
    () => path.value,
    (newVal, oldVal) => {
        if (newVal.length == 0 || newVal[newVal.length - 1].indexOf('.') == -1) {
            render_type.value = 0
            spinShow.value=true
            request("get", "/codecover/dirinfo", { key: choicedkey.value, path: newVal.join('/') }, this, (res) => {
                dirInfo.value = res.data;
                spinShow.value=false
            })
        } else {
            render_type.value = 1
            spinShow.value=true
            request("get", "/codecover/fileinfo", { key: choicedkey.value, path: newVal.join('/') }, this, (res) => {
                fileAll.value = res.data.all;
                fileChange.value = res.data.change;
                dirInfo.value = res.data.coverInfo;
                spinShow.value=false
            })
        }
    }, {
    deep: true
})

watch(
    () => state.value,
    (newVal, oldVal) => {
        localStorage.setItem('state',newVal)
    })

onMounted(() => {
    getLogs(() => { if (keys.value.length > 0) { choicedkey.value = keys.value[0] } })
})
</script>

<style>
.table {
    width: 100%;
    margin-bottom: 1rem;
    border-collapse: collapse;
    color: #212529;
}

.table-bordered {
    border: 1px solid #dee2e6;
}

.table>thead>tr>td,
.table>tbody>tr>td {
    border: 1px solid #dee2e6;
    vertical-align: top;
}

.table td,
.table th {
    padding: .75rem;
    vertical-align: top;
    border-top: 1px solid #dee2e6;
}

.table tbody>tr>td,
.table thead>tr>td {
    padding-top: 3px;
    padding-bottom: 3px;
}

.danger {
    background-color: #f2dede;
}

.nochange{
    background-color: #dcdee2;
}

.bg-danger {
    background-color: #dc3545 !important;
}

.bg-warning {
    background-color: #ffc107 !important
}

.bg-success {
    background-color: #28a745 !important;
}

.progress-bar {
    display: -ms-flexbox;
    display: flex;
    -ms-flex-direction: column;
    flex-direction: column;
    -ms-flex-pack: center;
    justify-content: center;
    overflow: hidden;
    color: #fff;
    text-align: center;
    white-space: nowrap;
    background-color: #007bff;
    transition: width .6s ease;
}

.progress {
    display: -ms-flexbox;
    display: flex;
    height: 1rem;
    overflow: hidden;
    line-height: 0;
    font-size: .75rem;
    background-color: #e9ecef;
    border-radius: .25rem;
}

.table .progress {
    margin-bottom: inherit;
}

body {
    font-family: sans-serif;
    font-size: 1em;
    font-kerning: normal;
    font-variant-ligatures: common-ligatures;
    text-rendering: optimizeLegibility;
    padding-top: 10px;
}

.popover {
    max-width: none;
}

.octicon {
    margin-right: .25em;
    vertical-align: baseline;
    width: 0.75em;
}

.table-bordered>thead>tr>td {
    border-bottom-width: 1px;
}

.table tbody>tr>td,
.table thead>tr>td {
    padding-top: 3px;
    padding-bottom: 3px;
}

.table-condensed tbody>tr>td {
    padding-top: 0;
    padding-bottom: 0;
}

.table .progress {
    margin-bottom: inherit;
}

.table-borderless th,
.table-borderless td {
    border: 0 !important;
}

.table tbody tr.covered-by-large-tests,
li.covered-by-large-tests,
tr.success,
td.success,
li.success,
span.success {
    background-color: #dff0d8;
}

.table tbody tr.covered-by-medium-tests,
li.covered-by-medium-tests {
    background-color: #c3e3b5;
}

.table tbody tr.covered-by-small-tests,
li.covered-by-small-tests {
    background-color: #99cb84;
}

.table tbody tr.danger,
.table tbody td.danger,
li.danger,
span.danger {
    background-color: #f2dede;
}

.table tbody tr.warning,
.table tbody td.warning,
li.warning,
span.warning {
    background-color: #fcf8e3;
}

.table tbody td.info {
    background-color: #d9edf7;
}

td.big {
    vertical-align: middle;
    width: 117px;
}

td.small {}

td.codeLine {
    font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
    white-space: pre-wrap;
}

td span.comment {
    color: #888a85;
}

td span.default {
    color: #2e3436;
}

td span.html {
    color: #888a85;
}

td span.keyword {
    color: #2e3436;
    font-weight: bold;
}

pre span.string {
    color: #2e3436;
}

span.success,
span.warning,
span.danger {
    margin-right: 2px;
    padding-left: 10px;
    padding-right: 10px;
    text-align: center;
}

#toplink {
    position: fixed;
    left: 5px;
    bottom: 5px;
    outline: 0;
}

svg text {
    font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif;
    font-size: 11px;
    color: #666;
    fill: #666;
}

.scrollbox {
    height: 245px;
    overflow-x: scroll;
    overflow-y: scroll;
}

table+.structure-heading {
    border-top: 1px solid lightgrey;
    padding-top: 0.5em;
}

.legend {
    font-weight: bold;
    margin-right: 2px;
    padding-left: 10px;
    padding-right: 10px;
    text-align: center;
}

.covered-by-small-tests {
    background-color: #99cb84;
}

.covered-by-medium-tests {
    background-color: #c3e3b5;
}

.covered-by-large-tests {
    background-color: #dff0d8;
}

.not-covered {
    background-color: #f2dede;
}

.not-coverable {
    background-color: #fcf8e3;
}

.vertical-center-modal {
    display: flex;
    align-items: center;
    justify-content: center;
}

.vertical-center-modal .ivu-modal {
    top: 0;
}
</style>