<template>
  <div>
    <q-field :label="displayName" labelColor="primary" stack-label
    v-model="processingProps"
    :rules="rulesExp"
    lazy-rules="ondemand"
    ref="fieldRef"
    >
      <template v-slot:control>
        <q-card flat class="full-width">
          <q-card-actions vertical>
            <q-btn color="grey-3" text-color="black" @click="() => { dgIsShow = true }">クリックで設定</q-btn>
          </q-card-actions>
          <q-card-section class="text-caption">
            <div v-if="processingObjectsInputDisplay && processingObjectsInputDisplay.length>0">
              <div v-for="(item) in processingObjectsInputDisplay" :key="item">{{ item }}</div>
            </div>
            <div v-else>{{ placeholder }}</div>
          </q-card-section>
        </q-card>
      </template>
    </q-field>
    <show-dialog v-model:visible="dgIsShow" name="集計処理" @close="closeDg" min-width="50vw" min-height="60vh">
      <div class="q-mx-md q-mb-md">
        <q-input v-model="processingProps.name" type="text" label-color="primary" label="集計結果の変数名"
          placeholder="集計結果を格納する変数名を入力してください" stack-label />
      </div>

      <div class="q-mx-md">
        <div class="row q-col-gutter-x-xs flex-center">
          <div class="col-5">
            <div class="q-mx-xs">データソース</div>
          </div>
          <div class="col-2">
            <div class="q-mx-xs">集計計算</div>
          </div>
          <div class="col-4">
            <div class="q-mx-xs">集計結果変数名</div>
          </div>
          <div class="col-1"><q-btn flat round dense icon="add" size="sm" @click="addProcessingObject" />
          </div>
        </div>
        <div class="q-my-sm" v-for="(item, index) in processingObjects" :key="item.id">
          <div class="row q-col-gutter-x-xs flex-center">
            <div class="col-5">
              <ConditionObject v-model="item.field" />
            </div>
            <div class="col-2 q-pa-sm">
              <q-select v-model="item.logicalOperator" :options="logicalOperators"  outlined dense></q-select>
            </div>
            <div class="col-4">
              <q-input v-model="item.vName" type="text"  outlined dense />
            </div>
            <div class="col-1">
              <q-btn flat round dense icon="delete" size="sm" @click="() => deleteProcessingObject(index)" />

            </div>
          </div>
        </div>
      </div>
    </show-dialog>
  </div>
</template>

<script lang="ts">
import { v4 as uuidv4 } from 'uuid';
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
import ConditionObject from '../ConditionEditor/ConditionObject.vue';
import ShowDialog from '../ShowDialog.vue';

type Props = {
  props?: {
    name: string;
    modelValue?: {
      fields: {
        type: string;
        label: string;
        code: string;
      }[]
    } | string
  }
};

type ProcessingObjectType = {
  field?: {
    sharedText: string;
    objectType: 'field';
  };
  logicalOperator?: string;
  vName?: string;
  id: string;
}

type ValueType = {
  name: string;
  actionName: string,
  displayName: string,
  vars: ProcessingObjectType[];
}

export default defineComponent({
  name: 'DataProcessing',
  inheritAttrs: false,
  components: {
    ShowDialog,
    ConditionObject,
  },
  props: {
    context: {
      type: Array<Props>,
      default: '',
    },
    displayName: {
      type: String,
      default: '',
    },
    name: {
      type: String,
      default: '',
    },
    modelValue: {
      type: Object as () => ValueType,
    },
    placeholder: {
      type: String,
      default: '',
    },
    //例：[val=>!!val ||'入力してください']
    rules: {
      type: String,
      default: undefined
    },
    required: {
      type: Boolean,
      default: false
    }
  },

  setup(props, { emit }) {
    const fieldRef=ref();
    const source = props.context.find(element => element?.props?.name === 'sources')

    if (source) {
      provide('sourceFields', computed(() => {
        const modelValue = source.props?.modelValue;
        if (modelValue && typeof modelValue !== 'string') {
          return modelValue.fields;
        }
        return null;
      }));
      provide('sourceApp', computed(() => source.props?.modelValue?.app?.id));
    }

    const actionName = props.context.find(element => element?.props?.name === 'displayName')

    const processingProps: ValueType = props.modelValue && props.modelValue.vars
      ? reactive(props.modelValue)
      : reactive({
        name: '',
        actionName: actionName?.props?.modelValue as string,
        displayName: '結果（戻り値）',
        vars: [
        {
          id: uuidv4(),
          field:{
            objectType:'field',
            sharedText:''
          }
        }]
      });

    const closeDg = () => {
      fieldRef.value.validate();
      emit('update:modelValue', processingProps);
    }

    const processingObjects = processingProps.vars;

    const deleteProcessingObject = (index: number) => {
      if(processingObjects.length >0){
        processingObjects.splice(index, 1);
      }
      if(processingObjects.length===0){
        addProcessingObject();
      }
    }
    const processingObjectsInputDisplay = computed(() =>
      processingObjects ?
        processingObjects
          .filter(item => item.field && item.logicalOperator && item.vName)
          .map(item => {
            return`var(${processingProps.name}.${item.vName}) = ${item.field?.sharedText}`
          })
        : []
    );

    const addProcessingObject=()=>{
      processingObjects.push({
        id: uuidv4(),
        field:{
          objectType:'field',
          sharedText:''
        }
      });
    }
    //集計処理方法
    const logicalOperators = ref([
      {
        'operator': '',
        'label': 'なし'
      },
      {
        'operator': 'SUM',
        'label': '合計'
      },
      {
        'operator': 'AVG',
        'label': '平均'
      },
      {
        'operator': 'MAX',
        'label': '最大値'
      },
      {
        'operator': 'MIN',
        'label': '最小値'
      },
      {
        'operator': 'COUNT',
        'label': 'カウント'
      },
      {
        'operator': 'FIRST',
        'label': '最初の値'
      }
    ]);
    const checkInput=(val:ValueType)=>{
      if(!val){
        return false;
      }
      if(!val.name){
        return '集計結果の変数名を入力してください';
      }
      if(!val.vars || val.vars.length==0){
        return '集計処理を設定してください';
      }
      if(val.vars.some((x)=>!x.vName)){
        return '集計結果変数名を入力してください';
      }
      return true;
    }
    const customExp = props.rules === undefined ? [] : eval(props.rules);
    const requiredExp = props.required ? [(val: any) => checkInput(val)] : [];
    const rulesExp = [...requiredExp, ...customExp];

    watchEffect(() => {
      emit('update:modelValue', processingProps);
    });
    return {
      uuidv4,
      dgIsShow: ref(false),
      closeDg,
      processingObjects,
      processingProps,
      addProcessingObject,
      deleteProcessingObject,
      logicalOperators,
      processingObjectsInputDisplay,
      rulesExp,
      fieldRef
    };
  },
});
</script>
<style lang="scss"></style>
