<script>
import { setDataColumns, setDataRows, setParsedDataFormatFunction, setSaveFunction, setPending, setCompleted, setProcessing, setFailed, getPending, getProcessing, getFailed, getCompleted, getRequestLimit, getResponses, setResponses } from "@/components/forms/other/MassDataInserter.vue";
import { generateNewColumn} from "@/components/forms/other/functions/manageDataColumns.vue";
import { columnTypes } from "@/components/forms/other/types/dataColumnsType.vue";
import { applyColumnProperties } from "@/components/forms/other/types/dataColumn.vue";
import { SessionUser } from "@/components/session/token/SessionUser.vue";
import {getCustomerName} from "@/components/shop/POSDepartmentProcess.vue";
import {watch} from "vue";

export const exampleRows = [
  {
    customer_id: 1,
    reg: "AB123CD",
    wash_subscription: true,
    type: 1,
  },
  {
    customer_id: 2,
    reg: "EF456GH",
    wash_subscription: false,
    type: 2,
  },
  {
    customer_id: 3,
    reg: "IJ789KL",
    wash_subscription: true,
    type: 3,
  },
];

export const init = () => {
  /**
   * Set the data columns for the vehicle data structure
   * @type {function}
   */
  setDataColumns([
    generateNewColumn("customer_id", columnTypes.number, applyColumnProperties({required: true, label: SessionUser.objects.global.language.customer})),
    generateNewColumn("reg", columnTypes.registration_number, applyColumnProperties({required: true, label: SessionUser.objects.vehicles.columns.reg.label})),
    generateNewColumn("wash_subscription", columnTypes.boolean, applyColumnProperties({required: true, label: SessionUser.objects.vehicles.columns.wash_subscription.label})),
    generateNewColumn("type", columnTypes.product, applyColumnProperties({required: true, label: SessionUser.objects.vehicles.columns.type.label, default: 0})),
    generateNewColumn("reference", columnTypes.string, applyColumnProperties({required: false, label: SessionUser.objects.vehicles.columns.reference.label})),
  ]);

  /**
   * Set the data format parser function
   * @type {function}
   */
  setParsedDataFormatFunction((objects) => {
    console.log('parsing format vehicles', objects);
    // Define the objects
    let parsedObjects = [];
    // Define the default object
    let defaultObject = {
      customer_id: null,
      reg: null,
      wash_subscription: false,
      type: 0,
      reference: null,
    };
    // Loop through the objects and parse them to the correct format
    objects.forEach((object) => {
      let parsedObject = {
        ...defaultObject,
      };
      // Loop through the object, and see if any of the inputs could be a match
      for (const key in object) {
        let tmp_value = object[key];
        // Check if the value could be a customer id
        if (isCustomerNumber(tmp_value)) {
          console.log('Verified customer id', tmp_value, 'Current customer id', parsedObject.customer_id);
          // If there's currently a customer id, set the reference to the current customer id
          if (parsedObject.customer_id) {
            parsedObject.reference = '' + parsedObject.customer_id;
          }
          // If the value is a customer id, set it to the customer id key
          parsedObject.customer_id = parseInt(tmp_value);
        }
        // Check if the value could be a wash subscription
        else if (tmp_value === "true" || tmp_value === "false") {
          // If the value is a wash subscription, set it to the wash subscription key
          parsedObject.wash_subscription = tmp_value === "true";
        }
        // Check if the value could be a registration number
        else if (isRegistrationNumber(tmp_value)) {
          // If the value is a registration number, set it to the reg key
          console.log('Checking reg', tmp_value, 'Current reg', parsedObject.reg);
          if (parsedObject.reg) {
            // If there's currently a reg, set the reference to the current reg
            parsedObject.reference = parsedObject.reg;
          }
          parsedObject.reg = tmp_value;
        }
        // Check if the value could be a type
        else if (isType(tmp_value)) {
          // If the value is a type, set it to the type key
          console.log('Checking type', tmp_value, 'Current type', parsedObject.type);
          if (parsedObject.type) {
            // Apply the current value to reference
            parsedObject.reference = '' + parsedObject.type;
          }
          parsedObject.type = tmp_value;
        }
        else {
          // Set the reference to the value
          console.log('Checking reference', tmp_value, 'Current reference', parsedObject.reference);
          parsedObject.reference = tmp_value;
        }

        console.log('key', key, 'value', object[key]);
      }
      // Add the parsed object to the parsed objects array
      parsedObjects.push(parsedObject);
    });
    // Parse the object to the correct format
    console.log('parsed objects', parsedObjects);
    // Loop through the parsed objects and set the default values
    // Store the parsed objects in the data rows
    setDataRows(parsedObjects);
    return parsedObjects;
  });

  /**
   * Set the save function for the vehicle data structure
   * @type {function}
   */
  setSaveFunction((objects) => {
    // Add all the objects to the pending objects
    setPending(objects);
    // Start the processing
    processPendingVehicles();
  });
}

const isCustomerNumber = (value) => {
  // Check if the string only contains numbers
  console.log('Checking customer #1', value);
  if (typeof value !== 'number' && typeof value !== 'string') {
    console.log('not a number or string');
    return false;
  }
  // Check if the string only contains numbers
  if (!/^[0-9]+$/.test(value)) {
    console.log('not a number');
    return false;
  }
  // If the value is not 3, 6 or 8 digits long return false
  if (value.length !== 3 && value.length !== 8 && value.length !== 9 && value.length !== 6) {
    console.log('not 3, 6, 8 or 9 digits');
    return false;
  }
  // Check if we can get the customer name from the customer id
  //  if (!getCustomerName(parseInt(value))) {
  //  console.log('not a valid customer id');
  //  return false;
  // }
  // If the value is a valid customer number return true
  return true;
}

const isRegistrationNumber = (value) => {
  console.log('Checking reg #1', value);
  // Check if the value is a registration number (Contains both letters and numbers, and is between 1 and 12 characters long)
  // If the value is not between 1 and 12 characters long return false
  if (value.length < 3 || value.length > 12) {
    console.log('not between 3 and 12 characters');
    return false;
  }
  // If the value contains any spaces return false
  if (/\s/.test(value)) {
    console.log('contains spaces');
    return false;
  }
  // If the value is a valid registration number return true
  return true;
}

const isType = (value) => {
  // Check if the value is a type (Contains only numbers, and is between 1 and 3 digits long)
  // If the value is not between 1 and 3 digits long return false
  if (value.length < 1 || value.length > 3) {
    console.log('not between 1 and 3 digits');
    return false;
  }
  // If the value contains any spaces return false
  if (/\s/.test(value)) {
    console.log('contains spaces');
    return false;
  }
  // Check if the value only contains numbers
  if (!/^[0-9]+$/.test(value)) {
    console.log('not a number');
    return false;
  }
  // If the value is a valid type return true
  return true;
}

const processPendingVehicles = () => {
  // While there's unprocessed objects, process them
  while (getPending().length > 0 && getProcessing().length < getRequestLimit()) {
      // Get the first object from the pending objects
      let object = getPending()[0];
      // Remove the object from the pending objects
      setPending(getPending().slice(1));
      // Add the object to the processing objects
      setProcessing([...getProcessing(), object]);
      // Process the object
      processVehicle(object);
  }
}

const processVehicle = (object) => {
  // Send a request to the server to process the object
  SessionUser.objects.vehicles.add(
      object.type,
      object.reg,
      object.wash_subscription,
      object.customer_id,
      object.reference
  ).then((response) => {
    // If the request was successful, check if the object is valid
    if (response.status === 200) {
      // Add the response to the responses
      setResponses([...getResponses(), {
        object: object,
        success: true,
        response: response,
      }]);
      // If the object is valid, add it to the completed objects
      setCompleted([...getCompleted(), object]);
      // Remove the object from the processing objects
      setProcessing(getProcessing().filter((o) => o !== object));
    }
  }).catch((error) => {
    // If the request failed, add the object to the failed objects
    console.log('Failed to process vehicle', error);
    // Add the response to the responses
    setResponses([...getResponses(), {
      object: object,
      success: false,
      error: error,
    }]);
    setFailed([...getFailed(), object]);
    // Remove the object from the processing objects
    setProcessing(getProcessing().filter((o) => o !== object));
  }).finally(() => {
    // Process the next object
    processPendingVehicles();
  });
}


</script>