<template>
  <div class="h-full flex flex-col">
    <div class="bg-white border-b p-5">
      <div v-for="(status,index) in statuses" :key="index" class="inline-block py-1 px-2 rounded border ml-1">
        {{ status.name }} : {{ status.value }}
      </div>
    </div>
    <a-row class="h-0 grow">
      <a-col class="border-r h-full overflow-y-auto" :span="16">
        <div class="p-5 border-t border-b" v-if="0 < params.length">
          <a-row>
            <a-col :span="8" v-for="group in params" :key="group.name" class="p-1">
              <fieldset class="border">
                <legend>{{ group.name }}</legend>
                <div class="p-1" v-for="item in group.items" :key="item.key">
                  <service-configuration-param-value-edit 
                    :param="item" 
                    v-model:value="item.value"
                    @save-request="actionServiceParamSave"  
                  ></service-configuration-param-value-edit>
                </div>
              </fieldset>
            </a-col>
          </a-row>
          <div class="p-1">
            <a-button class="mr-1" @click="actionServiceParamReload">刷新</a-button>
            <a-button @click="actionServiceParamSave">保存</a-button>
          </div>
        </div>
        <div class="p-5">
          <fieldset v-for="(group,groupIndex) in actions" :key="groupIndex" class="border my-1 p-1">
            <legend>{{ group.name }}</legend>
            <div v-for="action in group.items" :key="action.key" :class="{'inline-block ml-1':0 === action.params.length}">
              <a-button v-if="0 === action.params.length" class="my-1"
                :loading="action.isExecuting"
                @click="actionServiceExecute(action)"
              >{{ action.name }}</a-button>
              <div v-else class="border rounded-md my-1 px-3 bg-white">
                <span>{{ action.name }}</span>
                <div class="inline-block mx-2" v-for="actionParam in action.params" :key="actionParam.key">
                  {{ actionParam.name }} : 
                  <a-switch v-if="'java.lang.Boolean' === actionParam.type" v-model:checked="actionParam.value" />
                  <a-input v-else-if="'java.lang.String' === actionParam.type" class="w-24" v-model:value="actionParam.value" />
                  <a-input-number v-else-if="'java.lang.Integer' === actionParam.type" class="w-24" v-model:value="actionParam.value" />
                  <a-select v-else-if="'Enum' === actionParam.type" v-model:value="actionParam.value" :dropdownMatchSelectWidth="false">
                    <a-select-option v-for="(enumItem,enumIndex) in actionParam.options" :key="enumIndex" :value="enumItem.value">{{ enumItem.name }}</a-select-option>
                  </a-select>
                  <span v-else>{{ actionParam }}</span>
                </div>
                <a-button class="m-1" :loading="action.isExecuting" @click="actionServiceExecute(action)">执行</a-button>
              </div>
            </div>
          </fieldset>
        </div>
      </a-col>
      <a-col :span="8" class="p-5 h-full">
        <service-configuration-action-log :log="actionLog"/>
      </a-col>
    </a-row>
  </div>
</template>
<script setup>
import { onUnmounted, ref, watch } from 'vue';
import ApiClient from '@/utils/ApiClient';
import ServiceConfigurationParamValueEdit from './ServiceConfigurationParamValueEdit.vue'
import ServiceConfigurationActionLog from './ServiceConfigurationActionLog.vue'
/** @var {Object} */
const props = defineProps({
    serviceKey : String,
});
/** @var {Array} */
const params = ref([]);
/** @var {Array} */
const actions = ref([]);
/** @var {Array} */
const statuses = ref([]);
/** @var {Object} */
const actionLog = ref(null);
/** @var {Integer} */
let statusRefreshTimer = null;
// watch service key
watch(() => props.serviceKey, handleServiceKeyChange);
// on unmounted
onUnmounted(() => {
    if ( null !== statusRefreshTimer ) {
        clearTimeout(statusRefreshTimer);
        statusRefreshTimer = false;
    }
});

// on mounted
async function handleServiceKeyChange() {
    actionLog.value = null;
    if ( null !== statusRefreshTimer ) {
        clearTimeout(statusRefreshTimer);
        statusRefreshTimer = null;
    }
    if ( null === props.serviceKey ) {
        return ;
    }

    await actionServiceParamReload();
    await serviceActionReload();
    await refreshServiceStatusList();
}

// refresh service status list
async function refreshServiceStatusList() {
    try {
        let client = ApiClient.getClient();
        statuses.value = await client.call('service-config/service-status-list', {serviceKey:props.serviceKey});
        if ( false !== statusRefreshTimer ) {
            statusRefreshTimer = setTimeout(refreshServiceStatusList, 500);
        }
    } catch ( e ) {/** nothing to do here */}
}

// service param reload
async function actionServiceParamReload() {
    try {
        params.value = [];
        let client = ApiClient.getClient();
        let list = await client.call('service-config/service-params-list', {serviceKey:props.serviceKey});
        for ( var item of list ) {
            let groupName = item.group;
            let group = params.value.find( i => i.name === groupName);
            if ( undefined === group ) {
                group = {name:groupName, items:[]};
                params.value.push(group);
            }
            group.items.push(item);
        }
        params.value.sort((a,b) => b.items.length - a.items.length || b.name.localeCompare(a.name));
    } catch ( e ) {/** nothing to do here */}
}

// service param save
async function actionServiceParamSave() {
    try {
        let values = {};
        for ( let group of params.value ) {
            for ( let item of group.items ) {
                values[item.key] = item.value;
            }
        }
        let client = ApiClient.getClient();
        await client.call('service-config/service-params-update', {serviceKey:props.serviceKey,params:values});
        await actionServiceParamReload();
    } catch ( e ) {/** nothing to do here */}
}

// service actions reload
async function serviceActionReload() {
    try {
        actions.value = [];
        let client = ApiClient.getClient();
        let list = await client.call('service-config/service-action-list', {serviceKey:props.serviceKey});
        for ( let item of list ) {
            let group = actions.value.find(i => i.name === item.group);
            if ( undefined === group ) {
                group = {name:item.group, items:[]};
                actions.value.push(group);
            }
            group.items.push(item);
            group.items.sort((a,b) => a.params.length - b.params.length);
        }
        actions.value.sort((a,b) => a.name.localeCompare(b.name));
    } catch ( e ) {/** nothing to do here */}
}

// service action execute
async function actionServiceExecute(action) {
    try {
        let client = ApiClient.getClient();
        let params = {};
        params.serviceKey = props.serviceKey;
        params.action = action.key;
        params.params = [];
        params.paramTypes = [];
        for ( let item of action.params ) {
            params.params.push(item.value);
            let type = item.type;
            if ( 'Enum' === type ) {
                type = item.typeEnum;
            }
            params.paramTypes.push(type);
        }

        actionLog.value = {};
        actionLog.value.action = params.action;
        actionLog.value.params = params.params;
        actionLog.value.response = null;
        action.isExecuting = true;
        actionLog.value.response = await client.call('service-config/service-action-exec',params);
        action.isExecuting = false;
    } catch ( e ) {
        /** nothing to do here */
    } finally {
        action.isExecuting = false;
    }
}
</script>