<script setup lang="ts">
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import { computed, watch } from "vue";
import ParameterNumberInput from "@/components/parameter-schema/form-mode/ParameterNumberInput.vue";
import MarkdownRenderer from "@/components/MarkdownRenderer.vue";
import ParameterBooleanInput from "@/components/parameter-schema/form-mode/ParameterBooleanInput.vue";
import ParameterEnumInput from "@/components/parameter-schema/form-mode/ParameterEnumInput.vue";
import ParameterStringInput from "@/components/parameter-schema/form-mode/ParameterStringInput.vue";

const props = defineProps({
  parameterGroup: {
    type: Object,
    required: true,
    validator(value: Record<string, never>) {
      return "object" === value["type"];
    },
  },
  parameterGroupName: {
    type: String,
    required: true,
  },
  modelValue: {
    type: Object,
    required: true,
  },
});
const title = computed<string>(() => props.parameterGroup["title"]);
const icon = computed<string>(() => props.parameterGroup["fa_icon"]);
const description = computed<string>(() => props.parameterGroup["description"]);
const groupHidden = computed<boolean>(() =>
  Object.keys(parameters.value).reduce(
    (acc: boolean, val: string) => acc && parameters.value[val]["hidden"],
    true
  )
);
const parameters = computed<Record<string, never>>(
  () => props.parameterGroup["properties"]
);

const formInput = computed(() => props.modelValue);
const emit = defineEmits<{
  (
    e: "update:modelValue",
    value: Record<string, number | string | boolean | undefined>
  ): void;
}>();

function parameterRequired(
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  parameterGroup: Record<string, any>,
  parameterName: string
): boolean {
  return (
    parameterGroup["required"]?.includes(parameterName) || // parameter is required
    parameterGroup["dependentRequired"]?.[parameterName] // parameter is required when another parameter is set
      ?.map((param: string) => formInput.value[param])
      ?.reduce((acc: boolean, val: string) => acc || val, false)
  );
}

watch(
  formInput,
  (newVal) => {
    //console.log("Group", props.parameterGroupName, newVal);
    emit("update:modelValue", newVal);
  },
  {
    deep: true,
  }
);
</script>

<template>
  <div class="card bg-dark mb-3" v-if="!groupHidden">
    <h2 class="card-header" :id="props.parameterGroupName">
      <font-awesome-icon :icon="icon" class="me-2" v-if="icon" />
      {{ title }}
    </h2>
    <div class="card-body">
      <h5 class="card-title" v-if="description">{{ description }}</h5>
      <template
        v-for="(parameter, parameterName) in parameters"
        :key="parameterName"
      >
        <template v-if="!parameter['hidden']">
          <div class="input-group">
            <span class="input-group-text" :id="parameterName + '-help'">
              <font-awesome-icon
                class="me-2 text-dark"
                :icon="parameter['fa_icon']"
                v-if="parameter['fa_icon']"
              />
              <code>--{{ parameterName }}</code>
            </span>
            <parameter-number-input
              v-if="
                parameter['type'] === 'number' ||
                parameter['type'] === 'integer'
              "
              :parameter-name="parameterName"
              :parameter="parameter"
              :help-id="parameterName + '-help'"
              :required="parameterRequired(parameterGroup, parameterName)"
              :model-value="formInput[parameterName]"
              @update:model-value="
                (newValue) => (formInput[parameterName] = newValue)
              "
            />
            <parameter-boolean-input
              v-else-if="parameter['type'] === 'boolean'"
              :parameter-name="parameterName"
              :parameter="parameter"
              :help-id="parameterName + '-help'"
              :model-value="formInput[parameterName]"
              @update:model-value="
                (newValue) => (formInput[parameterName] = newValue)
              "
            />
            <template v-else-if="parameter['type'] === 'string'">
              <parameter-enum-input
                v-if="parameter['enum']"
                :parameter-name="parameterName"
                :parameter="parameter"
                :model-value="formInput[parameterName]"
                :required="parameterRequired(parameterGroup, parameterName)"
                @update:model-value="
                  (newValue) => (formInput[parameterName] = newValue)
                "
              />
              <parameter-string-input
                v-else
                :parameter-name="parameterName"
                :parameter="parameter"
                :model-value="formInput[parameterName]"
                :required="parameterRequired(parameterGroup, parameterName)"
                @update:model-value="
                  (newValue) => (formInput[parameterName] = newValue)
                "
              />
            </template>
            <span
              class="input-group-text cursor-pointer px-2"
              v-if="parameter['help_text']"
              data-bs-toggle="collapse"
              :data-bs-target="'#helpCollapse' + parameterName"
              aria-expanded="false"
              aria-controls="collapseExample"
            >
              <font-awesome-icon
                class="cursor-pointer"
                icon="fa-solid fa-circle-question"
              />
            </span>
          </div>
          <label v-if="parameter['description']"
            ><markdown-renderer :markdown="parameter['description']"
          /></label>
          <div
            class="collapse p-2 pb-0 bg-dark mx-2 mt-1 flex-shrink-1"
            :id="'helpCollapse' + parameterName"
            v-if="parameter['help_text']"
          >
            <markdown-renderer
              class="helpTextCode"
              :markdown="parameter['help_text']"
            />
            <p v-if="parameter['pattern']">
              Pattern: <code>{{ parameter["pattern"] }}</code>
            </p>
          </div>
        </template>
      </template>
    </div>
  </div>
</template>

<style scoped>
div.card-body {
  backdrop-filter: brightness(1.2);
}
span.cursor-pointer:hover {
  color: var(--bs-info);
  background: var(--bs-light);
}
</style>