<template>
  <div class="form-input flex flex-col">
    <div :class="`label-${labelPosition}`">
      <slot name="label" />
      <div class="w-full">
        <div
          class="relative flex items-center group-input"
          :class="{ 'wrap-slot': slotLeft || slotRight }"
        >
          <base-icon
            v-if="iconLeft"
            :iconName="iconLeft"
            color="#59636E"
            class="absolute ml-3"
            width="20"
            height="20"
          />
          <div
            v-if="slotLeft"
            class="slot-left"
            :class="{ 'disabled-slot': disabled }"
          >
            {{ slotLeft }}
          </div>
          <div v-if="tag" class="tag-code">
            {{ tag }}
          </div>
          <input 
            v-if="currency || dataDecimal"
            :id="`${name}inputCurrency`"
            name="inputCurrency"
            type="text" 
            v-model="maskCurrency"
            @input="maskInput($event.target.value)"
            :placeholder="`${prefix ? prefix + ' ' : ''}` + placeholder"
            :readonly="readonly"
            :disabled="disabled"
            class="w-full"
            :class="{
              error: error,
              'text-right': textAlign == 'right',
              'text-left': textAlign == 'left',
              'border-slot-left': slotLeft,
              'border-slot-right': slotRight || btnOnInput,
              'padding-icon-right': iconRight,
              'padding-icon-left': iconLeft,
            }"
            @click="handleCursorLast()"
            :maxlength="maxDecimal"
          >
          <input 
            v-else-if="mask"
            name="inputCurrency"
            type="text" 
            v-model="maskCurrency"
            @input="maskInput($event.target.value)"
            @keypress="isNumber"
            :placeholder="`${prefix ? prefix + ' ' : ''}` + placeholder"
            :readonly="readonly"
            :disabled="disabled"
            :maxlength="mask.length"
            class="w-full"
            :class="{
              error: error,
              'text-right': textAlign == 'right',
              'text-left': textAlign == 'left',
              'border-slot-left': slotLeft,
              'border-slot-right': slotRight || btnOnInput,
              'padding-icon-right': iconRight,
              'padding-icon-left': iconLeft,
            }"
          >
          <input
            v-else
            class="w-full"
            data-test="base-form-input"
            :maxlength="maxLength"
            :minlength="minLength"
            :class="{
              error: error,
              'text-right': textAlign == 'right',
              'text-left': textAlign == 'left',
              'border-slot-left': slotLeft,
              'border-slot-right': slotRight || btnOnInput,
              'padding-icon-right': iconRight,
              'padding-icon-left': iconLeft,
              'padding-tag-code': tag
            }"
            :placeholder="placeholder"
            :disabled="disabled"
            v-model="dataValue"
            :readonly="readonly"
            @keypress="isNumber"
            :type="type == 'number' ? 'text' : type"
            @blur="$emit('blur')"
          >
          <div
            v-if="slotRight"
            class="slot-right"
            :class="{ 'disabled-slot': disabled }"
          >
            {{ slotRight }}
          </div>
          <div
            v-if="btnOnInput"
            class="btn-on-input"
            @click="actionBtnOnInput"
          >
            {{ btnOnInput }}
          </div>
          <base-icon
            v-if="iconRight"
            :iconName="iconRight"
            color="#59636E"
            class="absolute mr-3 icon-right"
            width="20"
            height="20"
            :class="iconRight"
            @click="$emit('clickIcon')"
          />
        </div>
        <div
          v-if="message"
          class="helper-text flex items-center"
          :class="{ 'error-helper': error }"
        >
          <base-icon
            v-if="errorIcon"
            :iconName="errorIcon"
            width="14"
            height="14"
            class="mr-1"
            color="#e03021"
          /> 
          <span v-html="message" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import BaseIcon from "@/components/Base/BaseIcon";

export default {
  components: {
    BaseIcon,
  },
  props: {
    name: {
      type: [String],
      default: "",
    },
    placeholder: {
      type: [String, Number],
      default: "Your text input here",
    },
    disabled: {
      type: [Boolean],
      default: false,
    },
    error: {
      type: [Boolean],
      default: false,
    },
    message: {
      type: [String],
      default: "",
    },
    maxLength: {
      type: [String, Number],
      default: ""
    },
    minLength: {
      type: [String, Number],
      default: ""
    },
    textAlign: {
      type: [String],
      default: "left",
      validator: function (value) {
        return ["left", "right"].indexOf(value) !== -1;
      },
    },
    type: {
      type: [String],
      default: "text",
      validator: function (value) {
        return ["text", "number", "password", "alphanumeric", "alphanumericspace"].indexOf(value) !== -1;
      },
    },
    slotLeft: {
      type: [String],
      default: "",
    },
    slotRight: {
      type: [String],
      default: "",
    },
    btnOnInput: {
      type: [String],
      default: "",
    },
    iconLeft: {
      type: [String],
      default: "",
    },
    iconRight: {
      type: [String],
      default: "",
    },
    modelValue: {
      type: [String, Number, Array, Object],
    },
    labelPosition: {
      type: [String],
      validator: function (value) {
        return ["left", "top"].indexOf(value) !== -1;
      },
    },
    readonly: {
      type: [Boolean],
      default: false,
    },
    prefix: {
      type: [String],
      default: "",
    },
    currency: {
      type: [Boolean],
      default: false
    },
    decimal: {
      type: [Number, Boolean],
      default: 0
    },
    mask: {
      type: String,
      default: "",
    },
    errorIcon: {
      type: String,
      default: ""
    },
    tag: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      maskCurrency: "",
      dataValue: "",
      dataDecimal: 0,
      maxDecimal: null
    }
  },
  watch: {
    maskCurrency(newVal) {
      if (this.currency || this.dataDecimal) {
        newVal = newVal
          .replace(/-/g, "")
          .replace(/\./g, "")
          .replace(`${this.prefix} `, "")
          .replace(`${this.prefix}`, "")
          .replace(",", ".") //for decimal
        if (newVal.search(/\(/) != -1) {
          newVal = newVal
            .replace(/\(/, "-")
            .replace(/\)/, "")
        }
        if (newVal.length >= this.dataDecimal) {
          if (newVal.indexOf(0) == 0) {
            newVal = newVal.replace("0", "")
          }
        }
        this.$emit("update:modelValue", Number(newVal));
      }
    },
    modelValue(newVal) {
      if (!newVal) {
        this.maskCurrency = ""
        this.dataValue = ""
      } else if (newVal) {
        if (this.currency || this.dataDecimal) {
          newVal = String(newVal).replace(".", ",")
          this.maskInput(newVal)
        } else if (this.mask) {
          this.maskInput(this.modelValue)
        } else {
          this.dataValue = newVal
        }
      }
    },
    dataValue(newVal) {
      this.dataValue = this.processFilter(newVal)
      this.$emit("update:modelValue", newVal);
    }
  },
  mounted() {
    if (this.currency || this.decimal) {
      this.dataDecimal = this.decimal == true ? 2 : this.decimal
      this.maskInput(String(this.modelValue))
    } else if(this.mask) {
      this.maskInput(this.modelValue)
    } else {
      this.dataValue = this.modelValue
    }
  },
  methods: {
    actionBtnOnInput(){
      this.$emit("actionBtnOnInput")
    },
    processFilter: function (val) {
      if (this.type == "email") val = val.toLowerCase();
      if (this.type == "number") return val ? String(val).replace(/[^0-9]/g, "") : val;
      if (this.type == "alphanumeric") return String(val).replace(/[^0-9a-zA-Z]/g, "");
      if (this.type == "alphanumericspace") return String(val).replace(/[^0-9 a-zA-Z]/g, "");
      else return val;
    },
    formatCurrency(value) {
      return String(value).replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ".")
    },
    maskInput(value) {
      this.maxDecimal = null
      if (this.mask) {
        if (value) {
          value = value.replace(/\D/g, ""); // Remove non-numeric characters
          let maskedValue = "";
          let setSeparatorMask = {}
          let minIndex = 0
          this.mask.split("").forEach((element, index) => {
            if (element != "#") {
              setSeparatorMask = {
                ...setSeparatorMask, [index-minIndex]: element
              }
              minIndex++
            }
          });
  
          for (let index = 0; index < value.length; index++) {
            if (setSeparatorMask[index]) {
              maskedValue += `${setSeparatorMask[index]}${value[index]}`;
            } else {
              maskedValue += value[index];
            }
          }
          this.maskCurrency = maskedValue;
          this.$emit("update:modelValue", value);
        } else {
          this.$emit("update:modelValue", value);
        }
      } else if (this.dataDecimal && this.currency) {
        let inputVal = String(value);
        if (inputVal.indexOf(this.prefix) == -1) {
          inputVal = inputVal.replace(".", ",")
        }
        if (inputVal === "") { return; }
        let checkNegative = false
        if (inputVal.search("-") != -1) {
          checkNegative = true
        } else if (inputVal.search(/\(/) != -1) {
          checkNegative = true
        }

        // check for decimal
        if (inputVal.indexOf(",") >= 0) {
          let decimalPos = inputVal.indexOf(",");
          let leftSide = inputVal.substring(0, decimalPos);
          let rightSide = inputVal.substring(decimalPos);
          leftSide = this.formatCurrency(leftSide);
          rightSide = this.formatCurrency(rightSide).replace(/\./g, "").replace(",", "");
          rightSide = rightSide.substring(0, this.dataDecimal);
          inputVal = `${checkNegative ? "(" : ""}${this.prefix ? this.prefix + " " : ""}` + leftSide + "," + rightSide + (checkNegative ? ")" : "");
          if (rightSide.length == this.dataDecimal) {
            this.maxDecimal = String(inputVal).length
          }
        } else {
          inputVal = this.formatCurrency(inputVal);
          inputVal = `${checkNegative ? "(" : ""}${this.prefix ? this.prefix + " " : ""}` + inputVal + (checkNegative ? ")" : "");
        }
        this.maskCurrency = inputVal
      } else if (!this.dataDecimal && this.currency) {
        let checkNegative = false
        if (String(value).search("-") != -1) {
          checkNegative = true
        } else if (String(value).search(/\(/) != -1) {
          checkNegative = true
        }

        let getValue = value
        getValue = getValue.replace(this.prefix, "").replace(" ", "").replace(/\./g, "")
        if (value) {
          if (Number(getValue) != 0) {
            this.maskCurrency = `${checkNegative ? "(" : ""}${this.prefix ? this.prefix + " " : ""}` + this.formatCurrency(getValue) + (checkNegative ? ")" : "");
          } else {
            this.maskCurrency = `${this.prefix ? this.prefix + " " : ""}0`
          }
        } else {
          this.maskCurrency = String(value).replace(`${this.prefix} `, "").replace(`${this.prefix}`, "")
        }
      } else if (this.dataDecimal && !this.currency) {
        let inputVal = String(value);
        if (inputVal === "") { return; }
        // check for decimal
        if (inputVal.indexOf(",") >= 0) {
          let decimalPos = inputVal.indexOf(",");
          let leftSide = inputVal.substring(0, decimalPos);
          let rightSide = inputVal.substring(decimalPos);
          leftSide = leftSide.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, "");
          rightSide = rightSide.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, "");
          rightSide = rightSide.substring(0, this.dataDecimal);
          inputVal = leftSide + "," + rightSide;
          if (rightSide.length == this.dataDecimal) {
            this.maxDecimal = String(inputVal).length
          }
        } else {
          inputVal = inputVal.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, "");
        }
        this.maskCurrency = inputVal
      }
    },
    isNumber(evt) {
      if (this.type.toLowerCase() == "number" || this.mask) {
        evt = evt ? evt : window.event;
        var charCode = evt.which ? evt.which : evt.keyCode;
        if (charCode > 47 && charCode <= 57) {
          return true;
        } else {
          evt.preventDefault();
        }
      }
    },
    handleCursorLast() {
      const input = document.getElementById(`${this.name}inputCurrency`);
      let getValue = input.value
      getValue = getValue.replace(this.prefix, "").replace(" ", "").replace(/\./g, "")
      if (Number(getValue) == 0) {
        const length = input.value.length;
        // Focus on the input
        input.focus();
        // Set the cursor to the end
        input.setSelectionRange(length, length);
      }      
    }
  },
};
</script>

<style lang="scss">
@use "@/assets/style/_color.scss" as *;

.form-input {
  .label-top {
    display: flex;
    flex-flow: column;

    .typo-text {
      margin-bottom: 8px;
    }
  }

  .label-left {
    display: flex;

    .typo-text {
      margin-right: 12px;
      height: 37px;
      align-self: flex-start;
      display: flex;
      align-items: center;
      min-width: fit-content;
    }
  }

  .group-input {
    .icon-right {
      right: 0px;
    }
  }

  .group-input:focus-within {
    .keyboard_arrow_down {
      transform: rotate(180deg);
    }
  }

  .wrap-slot {
    display: flex;
    position: relative;
  }

  .slot-left {
    align-self: center;
    display: flex;
    align-items: center;
    color: $neutral-4;
    background: $neutral-2;
    border-radius: 6px 0px 0px 6px;
    padding: 0 12px;
    border: 1px solid $neutral-2;
    font-weight: 700;
    font-size: 14px;
    height: 35px;
  }

  .slot-right {
    align-self: center;
    display: flex;
    align-items: center;
    color: $neutral-4;
    background: $neutral-2;
    border-radius: 0px 6px 6px 0px;
    padding: 0 12px;
    border: 1px solid $neutral-2;
    font-weight: 700;
    font-size: 14px;
    height: 35px;
  }

  .btn-on-input {
    align-self: center;
    display: flex;
    align-items: center;
    color: $neutral-0;
    background: $dark-blue-4;
    border-radius: 0px 6px 6px 0px;
    padding: 0 12px;
    border: 1px solid $neutral-2;
    font-weight: 700;
    font-size: 14px;
    height: 35px;
    white-space: nowrap;
    cursor: pointer;
  }

  input {
    border: 1px solid $neutral-2;
    background: $neutral-0;
    border-radius: 6px;
    padding: 8px 16px;
    outline: none;
    font-size: 14px;
    color: $neutral-6;
    max-width: -webkit-fill-available;

    &:hover,
    &:focus {
      border-color: $dark-blue-4;
    }

    &::placeholder {
      color: $neutral-3;
    }

    &:disabled {
      background: $neutral-1;
      border-color: $neutral-2;
    }
  }

  .error {
    border-color: $critical-4;
    &:hover,
    &:focus {
      border-color: $critical-4;
    }
  }

  input[type="number"]::-webkit-inner-spin-button,
  input[type="number"]::-webkit-outer-spin-button {
    display: none;
  }

  .helper-text {
    font-size: 10px;
    margin-top: 4px;
    color: $neutral-6;
  }

  .error-helper {
    color: $critical-4;
  }

  .disabled-slot {
    color: $neutral-3;
  }

  .padding-icon-left {
    padding-left: 40px;
  }

  .padding-icon-right {
    padding-right: 40px;
  }

  .border-slot-left {
    border-radius: 0 6px 6px 0;
  }

  .border-slot-right {
    border-radius: 6px 0 0 6px;
  }

  .tag-code {
    padding: 4px 6.5px;
    background: #F9F9F9;
    font-size: 14px;
    font-weight: 900;
    position: absolute;
    margin-left: 16px;
  }

  .padding-tag-code {
    padding-left: 62px;
  }
}
</style>
