/* eslint-disable no-global-assign */
// eslint-disable-next-line no-unused-vars
/* global delegate_viewerReady, delegate_textureChanged, delegate_beforeChange, delegate_afterChange, delegate_optionsAllowed, delegate_endChanges */
/* global setIsLoaderActive, SetBlockTexturePath, beforeFilterAction, afterFilterAction */
/* global THREE, jQuery, scene, camera, controls, theModel */
/* global hideObject */

//Script version v1.0.0 [release]
//Created by Marevo (Oleksandr Trofymchuk (AlexTrofim88))
//UI changes by Marevo (Pavlo Voronin)

//Welcome to our custom script!

//REMEMBER:
//Theft is wrong not because some ancient text says, 'Thou shalt not steal.' It's always bad, robber :)

/*                                                                                                

          _____                    _____                    _____                    _____                    _____                   _______         
         /\    \                  /\    \                  /\    \                  /\    \                  /\    \                 /::\    \        
        /::\____\                /::\    \                /::\    \                /::\    \                /::\____\               /::::\    \       
       /::::|   |               /::::\    \              /::::\    \              /::::\    \              /:::/    /              /::::::\    \      
      /:::::|   |              /::::::\    \            /::::::\    \            /::::::\    \            /:::/    /              /::::::::\    \     
     /::::::|   |             /:::/\:::\    \          /:::/\:::\    \          /:::/\:::\    \          /:::/    /              /:::/~~\:::\    \    
    /:::/|::|   |            /:::/__\:::\    \        /:::/__\:::\    \        /:::/__\:::\    \        /:::/____/              /:::/    \:::\    \   
   /:::/ |::|   |           /::::\   \:::\    \      /::::\   \:::\    \      /::::\   \:::\    \       |::|    |              /:::/    / \:::\    \  
  /:::/  |::|___|______    /::::::\   \:::\    \    /::::::\   \:::\    \    /::::::\   \:::\    \      |::|    |     _____   /:::/____/   \:::\____\ 
 /:::/   |::::::::\    \  /:::/\:::\   \:::\    \  /:::/\:::\   \:::\____\  /:::/\:::\   \:::\    \     |::|    |    /\    \ |:::|    |     |:::|    |
/:::/    |:::::::::\____\/:::/  \:::\   \:::\____\/:::/  \:::\   \:::|    |/:::/__\:::\   \:::\____\    |::|    |   /::\____\|:::|____|     |:::|    |
\::/    / ~~~~~/:::/    /\::/    \:::\  /:::/    /\::/   |::::\  /:::|____|\:::\   \:::\   \::/    /    |::|    |  /:::/    / \:::\    \   /:::/    / 
 \/____/      /:::/    /  \/____/ \:::\/:::/    /  \/____|:::::\/:::/    /  \:::\   \:::\   \/____/     |::|    | /:::/    /   \:::\    \ /:::/    /  
             /:::/    /            \::::::/    /         |:::::::::/    /    \:::\   \:::\    \         |::|____|/:::/    /     \:::\    /:::/    /   
            /:::/    /              \::::/    /          |::|\::::/    /      \:::\   \:::\____\        |:::::::::::/    /       \:::\__/:::/    /    
           /:::/    /               /:::/    /           |::| \::/____/        \:::\   \::/    /        \::::::::::/____/         \::::::::/    /     
          /:::/    /               /:::/    /            |::|  ~|               \:::\   \/____/          ~~~~~~~~~~                \::::::/    /      
         /:::/    /               /:::/    /             |::|   |                \:::\    \                                         \::::/    /       
        /:::/    /               /:::/    /              \::|   |                 \:::\____\                                         \::/____/        
        \::/    /                \::/    /                \:|   |                  \::/    /                                          ~~              
         \/____/                  \/____/                  \|___|                   \/____/                                                           
                                                                                                                                                      


   ____  _      _                        _        _______         __                      _           _    
  / __ \| |    | |                      | |      |__   __|       / _|                    | |         | |   
 | |  | | | ___| | _____  __ _ _ __   __| |_ __     | |_ __ ___ | |_ _   _ _ __ ___   ___| |__  _   _| | __
 | |  | | |/ _ \ |/ / __|/ _` | '_ \ / _` | '__|    | | '__/ _ \|  _| | | | '_ ` _ \ / __| '_ \| | | | |/ /
 | |__| | |  __/   <\__ \ (_| | | | | (_| | |       | | | | (_) | | | |_| | | | | | | (__| | | | |_| |   < 
  \____/|_|\___|_|\_\___/\__,_|_| |_|\__,_|_|       |_|_|  \___/|_|  \__, |_| |_| |_|\___|_| |_|\__,_|_|\_\
  _____            _        __      __                   _            __/ |                                
 |  __ \          | |       \ \    / /                  (_)          |___/                                 
 | |__) |_ ___   _| | ___    \ \  / /__  _ __ ___  _ __  _ _ __                                            
 |  ___/ _` \ \ / / |/ _ \    \ \/ / _ \| '__/ _ \| '_ \| | '_ \                                           
 | |  | (_| |\ V /| | (_) |    \  / (_) | | | (_) | | | | | | | |                                          
 |_|   \__,_| \_/ |_|\___/      \/ \___/|_|  \___/|_| |_|_|_| |_|                                          
 
*/

//The script was created for additional management of admin panel resources for the byMain project.
//Each regio is designed to be divided into separate functions and is responsible for its actions separately.
//The PUBLIC VALUES region contains all the parameters-values that are used to interact with the admin panel, html, scripts, and user objects.
//In the CLASS's region, classes are created for convenient work with different types of groups that have their own characteristics.
//The INITIALIZATION region initializes all objects and parses data from the page.
//In the MAIN ACTIONS region, you prepare the actions that will be passed to objects from the page and change the properties that these objects are assigned.

//The basic structure of the script:
//- Calling the "viewerReady" event (all elements are prepared for interaction with the custom script)
//  - InitializationGroups (all groups and properties are initialized);
//  - Start (preparatory functions for interacting with objects are performed);
//      - SetActionForGroups (Setting up actions and interactions for objects);
//          - CheckChanges (Check and set new values for initialized objects. 
//                          The check occurs at every interaction with the initialized objects!)

// NOTE 
//Each region after the MAIN ACTIONS region has 2 main functions:
//- Prepare() - is executed when the script is initialized;
//- Change() - executed whenever the parameters in the script are changed. Execution occurs when using the CheckChanges function.

//------------------------------------------------------

// FAST FUNCTIONS (HELP FOR DEVELOPERS)

// jQuery(document).ready(function ($) { });
// document.addEventListener('click', function(){ });
// theModel.traverse((o) => { });

//------------------------------------------------------

//#region PUBLIC VALUES

var mainGroups = [];

// AR
var modelViewer;

// Pop-ups
let tblWindowArBtn;
let tblWindowShareBtn;

let tblInfo;
let tblInfoItemSharing;
let tblInfoItemQr;
let qrcode;
let tblInfoClose;
let tblInfoSharingIco;
let infoSharingInput;

// Canvas: top elements
let arPriceAmount;
let btnAddToCart;
let tblAcceptPrice;

var blockTexture = [];

var loaded = false;
var paramsLoaded = false;

var groupType = ["select", "select_no_photo", "range", "checkbox", "number", "text", "dropdown"];
let ar_filter = document.querySelector(".ar_filter");
var summary = document.querySelector("div.summary.entry-summary");

var formElement;

// SHADER
var isWorldposVertexShaderEnabled = true;

// MORPHS
let morphs = [];
let globalMorphs = [];

let needUpdateInsert = true;
let isAnimation = false;
let shouldAnimate = false;
let isPlankInserted = false;
let isPlankRoundInserted = false;
let insertedPlankRoundSize = 0;

// const railsNamesObj = {
//   120: 'rails_115-140',
//   125: 'rails_115-140',
//   130: 'rails_115-140',
//   135: 'rails_115-140',
//   140: 'rails_115-140',
//   145: 'rails_145-170',
//   150: 'rails_145-170',
//   155: 'rails_145-170',
//   160: 'rails_145-170',
// };

const railsNames = [
  'rails_90-110',
  'rails_115-140',
  'rails_145-170',
  'rails_175-200',
];

const insertPlanksNames90 = [
  'insert_1_90°_120',
  'insert_1_90°_125',
  'insert_1_90°_130',
  'insert_1_90°_135',
  'insert_1_90°_140',
  'insert_1_90°_145',
  'insert_1_90°_150',
  'insert_1_90°_150001',
  'insert_1_90°_160',

  'insert_2_90°_120',
  'insert_2_90°_125',
  'insert_2_90°_130',
  'insert_2_90°_135',
  'insert_2_90°_140',
  'insert_2_90°_145',
  'insert_2_90°_150',
  'insert_2_90°_150001',
  'insert_2_90°_160',

  'insert_3_90°_120',
  'insert_3_90°_125',
  'insert_3_90°_130',
  'insert_3_90°_135',
  'insert_3_90°_140',
  'insert_3_90°_145',
  'insert_3_90°_150',
  'insert_3_90°_150001',
  'insert_3_90°_160',

  'insert_4_90°_120',
  'insert_4_90°_125',
  'insert_4_90°_130',
  'insert_4_90°_135',
  'insert_4_90°_140',
  'insert_4_90°_145',
  'insert_4_90°_150',
  'insert_4_90°_150001',
  'insert_4_90°_160',
];

const insertPlanksNames20 = [
  'insert_1_20°_120',
  'insert_1_20°_125',
  'insert_1_20°_130',
  'insert_1_20°_135',
  'insert_1_20°_140',
  'insert_1_20°_145',
  'insert_1_20°_150',
  'insert_1_20°_150001',
  'insert_1_20°_160',

  'insert_2_20°_120',
  'insert_2_20°_125',
  'insert_2_20°_130',
  'insert_2_20°_135',
  'insert_2_20°_140',
  'insert_2_20°_145',
  'insert_2_20°_150',
  'insert_2_20°_150001',
  'insert_2_20°_160',

  'insert_3_20°_120',
  'insert_3_20°_125',
  'insert_3_20°_130',
  'insert_3_20°_135',
  'insert_3_20°_140',
  'insert_3_20°_145',
  'insert_3_20°_150',
  'insert_3_20°_150001',
  'insert_3_20°_160',

  'insert_4_20°_120',
  'insert_4_20°_125',
  'insert_4_20°_130',
  'insert_4_20°_135',
  'insert_4_20°_140',
  'insert_4_20°_145',
  'insert_4_20°_150',
  'insert_4_20°_150001',
  'insert_4_20°_160',
];

//Custom Length Input
var inputCustomLength = null;

// Shared-URL PARAMETERS
var delayForWriteURL = false;

var parametersKey = "config";
var parametersValue = "";

var qrScaned = 0;

var SharedParameterList = [
  {
    id: "trasort", // [0]
    groupIds: ["group-0"],
    splitValue: 't',
    type: 'string',
    value: "0",
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "storerlse", // [1]
    groupIds: ["group-34"],
    splitValue: 's',
    type: 'int',
    value: 100,
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "kant", // [2]
    groupIds: ["group-20", "group-31", "group-30", "group-29", "group-28",
      "group-27", "group-26", "group-25", "group-24", "group-23", "group-22",
      "group-21", "group-19", "group-17", "group-16", "group-14", "group-13",
      "group-12", "group-11", "group-9", "group-8", "group-10", "group-18"],
    splitValue: 'k',
    type: 'string',
    value: "0",
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "behandling", // [3]
    groupIds: ["group-6", "group-32"],
    splitValue: 'b',
    type: 'string',
    value: "0",
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "overflade", // [4]
    groupIds: ["group-33", "group-5"],
    splitValue: 'o',
    type: 'string',
    value: "0",
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "bentype", // [5]
    groupIds: ["group-2"],
    splitValue: 'e',
    type: 'string',
    value: "0",
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "farvePaBen", // [6]
    groupIds: ["group-3"],
    splitValue: 'f',
    type: 'string',
    value: "0",
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "tilvalg", // [7]
    groupIds: ["group-4"],
    splitValue: 'i',
    type: 'array-string',
    value: [],
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "qr",
    groupIds: null,
    splitValue: 'q',
    type: 'int',
    value: 0,
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
  {
    id: "indsaetPlanke", // [9]
    groupIds: [
      "group-35", "group-40", "group-36",
      "group-41", "group-37", "group-42",
      "group-38", "group-43", "group-39",
    ],
    splitValue: 'a',
    type: 'string',
    value: "0",
    groupOptionAction: null,
    applyURLAction: null,
    applyURLActionReturn: false
  },
];

SharedParameterList[0].applyURLAction = function () {
  DebugLog(SharedParameterList[0].id + " - TEST - applyURLAction - ACTION");
}

SharedParameterList[0].groupOptionAction = function () {
  DebugLog(SharedParameterList[0].id + " - TEST - groupOptionAction - ACTION");
}

SharedParameterList[1].groupOptionAction = function () {
  // console.log("🚀🚀🚀 ~ groupOptionAction:", SharedParameterList[1].value);
  // DebugLog(SharedParameterList[1].id + " - TEST - groupOptionAction - ACTION");
  // if (inputCustomLength != null) { inputCustomLength.value = SharedParameterList[1].value; }
  //ChangeBentype();
}

SharedParameterList[5].groupOptionAction = function () {
  DebugLog(SharedParameterList[5].id + " - TEST - groupOptionAction - ACTION");
  //ChangeBentype();
  //promiseDelay(500, ChangeBentype);
}

SharedParameterList[9].groupOptionAction = function () { // indsaetPlanke
  CheckAssign(SharedParameterList[9]);
  insertPlank(this);
}

SharedParameterList[1].groupOptionAction = function () {
  DebugLog(SharedParameterList[1].id + " - TEST - groupOptionAction - ACTION");
  if (inputCustomLength != null) { inputCustomLength.value = SharedParameterList[1].value; }
  checkKantForInserts();
  ChangeStorrelseDiameter();
}

SharedParameterList[2].groupOptionAction = function () {
  DebugLog(SharedParameterList[2].id + " - TEST - groupOptionAction - ACTION");

  checkKantForInserts();
}

function EmptyURLParams() {
  ParseAllGroups();
  if (inputCustomLength != null) { inputCustomLength.value = SharedParameterList[1].value; }

  setIsLoaderActive(false);
}

//#endregion

//#region CLASS's

class Group {
  constructor() {
    this.element = null;
    this.group = null;
    this.id = "";
    this.type = "";
  }
}

class GroupSelect {
  constructor() {
    this.element = null;
    this.header = null;
    this.name = "";
    this.description = "";
    this.filter_option = null;
    this.options = [];
    this.activeOption = 0;
    this.optionsResult = null;
  }
}

class GroupRange {
  constructor() {
    this.element = null;
    this.header = null;
    this.name = "";
    this.description = "";
    this.filter_option = null;
    this.options = [];
    this.input = null;
    this.rangeList = [];
    this.optionsResult = null;
  }
}

class GroupInput {
  constructor() {
    this.element = null;
    this.header = null;
    this.name = "";
    this.description = "";
    this.filter_option = null;
    this.options = [];
    this.input = null;
    this.optionsResult = null;
  }
}

class GroupDropdown {
  constructor() {
    this.element = null;
    this.header = null;
    this.name = "";
    this.description = "";
    this.filter_option = null;
    this.options = [];
    this.select = null;
    this.optionsResult = null;
  }
}

class GroupCheckbox {
  constructor() {
    this.element = null;
    this.header = null;
    this.name = "";
    this.description = "";
    this.filter_option = null;
    this.options = [];
    this.activeOption = 0;
    this.optionsResult = null;
  }
}

class Option {
  constructor() {
    this.element = null;
    this.name = null;
    this.description = null;
    this.tooltip = null;
    this.dataValue = null;
    this.group_id = null;
    this.component_id = null;
    this.price = null;
    this.exclude_items = null;
    this.active = false;
    this.componentOptions = [];
  }
}

class ComponentOption {
  constructor() {
    this.element = null;
    this.name = null;
    this.color = null;
    this.map = null;
    this.normal_map = null;
    this.roughness = null;
    this.metalness = null;
    this.ao = null;
    this.targetObject = null;
  }
}

//#endregion

//#region DELEGATES

delegate_viewerReady = viewerReadyDelegate();
delegate_textureChanged = textureChangedDelegate();
delegate_beforeChange = beforeChangeDelegate;
delegate_afterChange = afterChangeDelegate;
delegate_optionsAllowed = optionsAllowedDelegate();
delegate_endChanges = endChangesDelegate();

function viewerReadyDelegate() {
  blockTexture = [];
  SetBlockTexturePath(blockTexture);

  if (camera != null) {
    camera.position.set(-1.2, 0.551, 0.71);
  }

  promiseDelayTheModel(100, function () { InitializationGroups(Start) });
}

function textureChangedDelegate() {
  //You can do something here...
}

function beforeChangeDelegate() {
  //You can do something here...
}

function afterChangeDelegate() {
  if (paramsLoaded) {
    ParseAllGroups();
  }
  ChangeStorrelse();
  ChangeBentype();
}

function optionsAllowedDelegate() {
  //You can do something here...
}

function endChangesDelegate() {
  //You can do something here...
}

//#endregion

//#region INITIALIZATION

function InitializationGroups(callback) {

  mainGroups = [];

  let groups = ar_filter.querySelectorAll(":scope > div.ar_filter_group");

  console.log(groups);

  for (let i = 0; i < groups.length; i++) {
    const element = groups[i];

    let typeValue = "";

    let name = element.querySelector("div.ar_filter_caption");
    let description = element.querySelector("div.ar_filter_description");

    let ar_filter_option = null;
    var ar_filter_inputs = null;

    for (let t = 0; t < groupType.length; t++) {

      ar_filter_option = element.querySelector("div.ar_filter_options.type_" + groupType[t]);
      ar_filter_inputs = element.querySelector("div.ar_filter_inputs.type_" + groupType[t]);

      if (ar_filter_option != null) {
        typeValue = groupType[t];
        break;
      }
    }

    if (ar_filter_option == null) { continue; }

    var ar_filter_options_result = element.querySelector("div.ar_filter_options_result");
    var ar_filter_header = element.querySelector("div.ar_filter_header");
    let options = ar_filter_option.querySelectorAll(":scope > div.option");

    //if(options == null) {continue;}
    //if(options.length == 0) {continue;}
    const newGroup = new Group();
    newGroup.element = element;
    newGroup.type = typeValue;
    newGroup.id = element.getAttribute("id");

    var newSomeGroup = null;
    switch (typeValue) {
      case "select":
      case "select_no_photo":
        newSomeGroup = new GroupSelect();
        break;
      case "range":
        newSomeGroup = new GroupRange();
        break;
      case "checkbox":
        newSomeGroup = new GroupCheckbox();
        break;
      case "number":
        newSomeGroup = new GroupInput();
        break;
      case "text":
        newSomeGroup = new GroupInput();
        break;
      case "dropdown":
        newSomeGroup = new GroupDropdown();
        break;
    }

    newSomeGroup.element = element;
    newSomeGroup.name = name != null ? name.textContent.trim() : null;
    newSomeGroup.description = description != null ? description.textContent.trim() : null;
    newSomeGroup.filter_option = ar_filter_option;
    newSomeGroup.optionsResult = ar_filter_options_result != null ? ar_filter_options_result : null;
    newSomeGroup.header = ar_filter_header != null ? ar_filter_header : null;
    //newSomeGroup.options = options != null ? options : null;

    let inputRange, input, select_dropdown;

    switch (typeValue) {
      case "range":
        inputRange = ar_filter_inputs.querySelector("input");
        // console.log(inputRange);

        if (inputRange != null) {
          newSomeGroup.input = inputRange;

          newSomeGroup.rangeList = [];
          if (options != null) {
            options.forEach(opt => {
              newSomeGroup.rangeList.push(opt.textContent.trim());
            });
            newSomeGroup.rangeList.sort();
            console.log(newSomeGroup.rangeList);
          }
        }
        break;
      case "number":
      case "text":
        input = ar_filter_inputs.querySelector("input");
        // console.log(input);

        if (input != null) {
          newSomeGroup.input = input;
        }
        break;
      case "dropdown":
        select_dropdown = ar_filter_inputs.querySelector("select");
        // console.log(select_dropdown);

        if (select_dropdown != null) {
          newSomeGroup.select = select_dropdown;
        }
        break;
      default:
        break;
    }

    if (options != null) {
      if (options.length > 0) {
        for (let o = 0; o < options.length; o++) {
          const opt = options[o];

          const newOption = new Option();
          newOption.element = opt;
          //newOption.name = opt.textContent.trim();
          var nameElement = opt.querySelector("div.component_title");
          var descriptionElement = opt.querySelector("div.ar_option_description");
          var tooltipElement = opt.querySelector("div.ar_option_description_tooltip");

          newOption.name = nameElement ? nameElement.textContent.trim() : "";
          newOption.description = descriptionElement ? descriptionElement.textContent.trim() : "";
          newOption.tooltip = tooltipElement ? tooltipElement.textContent.trim() : "";
          newOption.active = opt.classList.contains("active") ? true : false;

          if (newOption.active) {
            newSomeGroup.activeOption = o;
          }

          newOption.group_id = opt.getAttribute("data-group_id");
          newOption.component_id = opt.getAttribute("data-component_id");
          newOption.price = opt.getAttribute("data-price");
          newOption.dataValue = opt.getAttribute("data-value");
          newOption.exclude_items = opt.getAttribute("data-exclude_items");

          newOption.componentOptions = [];

          let divComponentOptions = opt.querySelector("div.component_options");

          if (divComponentOptions != null) {
            let componentOptions = divComponentOptions.querySelectorAll(":scope > div.option_settings");

            if (componentOptions != null) {
              if (componentOptions.length > 0) {
                componentOptions.forEach(copt => {
                  const newComponentOption = new ComponentOption();
                  newComponentOption.element = copt;
                  newComponentOption.name = copt.getAttribute("data-name");
                  newComponentOption.color = copt.getAttribute("data-color");
                  newComponentOption.map = copt.getAttribute("data-map");
                  newComponentOption.normal_map = copt.getAttribute("data-normal_map");
                  newComponentOption.roughness = copt.getAttribute("data-roughness");
                  newComponentOption.metalness = copt.getAttribute("data-metalness");
                  newComponentOption.ao = copt.getAttribute("data-ao");
                  newComponentOption.targetObject = GetObject(copt.getAttribute("data-name"));
                  if (newComponentOption.targetObject == null) {
                    newComponentOption.targetObject = GetGroup(copt.getAttribute("data-name"));
                    if (newComponentOption.targetObject == null) {
                      newComponentOption.targetObject = GetMaterial(copt.getAttribute("data-name"));
                    }
                  }
                  newOption.componentOptions.push(newComponentOption);
                });
              }
            }
          }

          newSomeGroup.options.push(newOption);
        }
      }
    }

    newGroup.group = newSomeGroup;

    mainGroups.push(newGroup)
  }

  console.log(mainGroups);
  if (callback != null) callback();
}

function Start() {
  if (loaded == true) {
    return;
  }
  loaded = true;
  theModel.visible = false;
  InitMorphModel(theModel); // Init Morph System
  ReadURLParameters(StartSettings);
}

function StartSettings() {
  PrepareStorrelse();
  PrepareBentype();
  ChangeBentype();

  Settings3d();

  PrepareExcludes();
  PrepareUI();
  PrepareAR();

  SetActionForGroups();

  CheckChanges();

  ChangeUI();

  promiseDelay(1000, () => {
    ApplyURLParameters(roundDefaultCheck);
  });

  promiseDelay(2000, ChangeBentype);
  promiseDelay(2000, ChangeStorrelse);
  

  promiseDelay(2000, () => {
    checkInsertedPlanks(SharedParameterList[9]);
    insertPlank(SharedParameterList[9]);
    toggleOptionDisplayForLegs();
    // CheckChanges();
  });

  ChangeStorrelse();

  promiseDelay(3500, () => {
    theModel.scale.set(0, 0, 0);
    theModel.visible = true;
    animateScale(theModel);
  });
}

function Settings3d() {
  // controls.minDistance = 1.25;
  // controls.maxDistance = 4;
  // controls.maxPolarAngle = Math.PI / 2.35;

  // camera.position.y = 0.5;
  // camera.position.x = -1.5;
  // camera.position.z = 2.1;

  // theModel.position.x = 0;
  // theModel.position.y = 0;
  // theModel.position.z = 0;
}

//#endregion

//#region MAIN ACTIONS

// group id - 9999999 - is example!
function SetActionForGroups() {
  mainGroups.forEach(target => {
    switch (target.type) {
      case "select":
      case "select_no_photo":
        for (let i = 0; i < target.group.options.length; i++) {
          const opt = target.group.options[i];
          opt.element.addEventListener('click', function () {
            target.group.activeOption = i;

            SetGroupActionForSharedParameters(target.id, opt.component_id, () => {
              CheckChanges();
              WriteURLParameters();
            });
          });
        }
        break;
      case "range":
        if (target.id == "group-9999999") {
          //You can do something here...
        }

        target.group.input.addEventListener('input', function () {
          if (!loaded) { return; }
          //You can do something here...
          //SetGroupActionForSharedParameters(target.id, target.group.input.value, () => {
          //    CheckChanges();
          //    WriteURLParameters();
          //});
        });
        target.group.input.addEventListener('change', function () {
          if (!loaded) { return; }
          
          needUpdateInsert = true; //! only for this project
          
          SetGroupActionForSharedParameters(target.id, target.group.input.value, () => {
            CheckChanges();
            WriteURLParameters();
          });
          console.log('%c' + target.group.input.value, 'color: blue; font-size: larger');
          //You can do something here...
        });
        break;
      case "checkbox":
        for (let i = 0; i < target.group.options.length; i++) {
          const opt = target.group.options[i];
          opt.element.addEventListener('click', function () {
            target.group.activeOption = i;
            opt.active = !opt.active;

            SetGroupActionForSharedParametersCheckboxArray(target.id, target.group.options, () => {
              CheckChanges();
              WriteURLParameters();
            });

            //You can do something here...
          });
        }
        break;
      case "number":
        target.group.input.addEventListener('input', function () {
          SetGroupActionForSharedParameters(target.id, target.group.input.value);
          CheckChanges();
          //You can do something here...
        });

        target.group.input.addEventListener('change', function () {
          console.log('%c' + target.group.input.value, 'color: blue; font-size: larger');
          WriteURLParameters();
          //You can do something here...
        });
        break;
      case "dropdown":
        target.group.select.addEventListener('change', function () {
          const activeOption = parseInt(this.value);
          target.group.activeOption = activeOption;

          for (let o = 0; o < target.group.options.length; o++) {
            const opt = target.group.options[o];
            opt.element.classList.remove("active");
            opt.active = false;
          }
          const opt = target.group.options[activeOption];
          opt.element.classList.add("active");
          opt.active = true;

          shouldAnimate = true; //! only for this project

          SetGroupActionForSharedParameters(target.id, target.group.select.value);
          console.log('%c' + target.group.select.value, 'color: blue; font-size: larger');
          //You can do something here...
          CheckChanges();
          WriteURLParameters();
        });
        break;
      case "text":
        //You can do something here...
        break;
    }
  });
}

function SetGroupActionForSharedParameters(targetID, value, callback, parse = false) {
  for (let i = 0; i < SharedParameterList.length; i++) {
    const element = SharedParameterList[i];

    if (element.groupIds == undefined || element.groupIds == null) { continue; }
    if (!element.groupIds.includes(targetID)) { continue; }

    if (element.value == value) { continue; }

    element.value = value;

    if (element.groupOptionAction != null && parse == false) {
      element.groupOptionAction();
    }
  }

  if (callback != null) {
    callback();
  }
}

function SetGroupActionForSharedParametersCheckboxArray(targetID, array, callback, parse = false) {
  if (array == undefined || array == null) { return; }

  for (let i = 0; i < SharedParameterList.length; i++) {
    const element = SharedParameterList[i];

    if (element.groupIds == undefined || element.groupIds == null) { continue; }
    if (!element.groupIds.includes(targetID)) { continue; }

    var newValue = [];

    for (var o = 0; o < array.length; o++) {
      if (array[o].active) {
        newValue.push("1");
      } else {
        newValue.push("0");
      }
    }

    if (element.value == newValue) { continue; }

    element.value = newValue;

    if (element.groupOptionAction != null && parse == false) {
      element.groupOptionAction();
    }
  }

  if (callback != null) {
    callback();
  }
}

function CheckChanges() {
  promiseDelay(100, () => {
    (needUpdateInsert) && checkDiameterForInsertedPlanks(SharedParameterList[1].value);
    CheckAssign(SharedParameterList[9]);
    checkInsertedPlanks(SharedParameterList[9]);
    checkInsertedPlanksSummary(SharedParameterList[9]);
    insertPlank(SharedParameterList[9]);
    
    checkKantForInserts();
    toggleOptionDisplayForLegs();
  });

  //You can do something here...
  //ChangeBentype();
  //promiseDelay(500, ChangeBentype);

  checkKantForInserts();

  if (inputCustomLength != null) { inputCustomLength.value = SharedParameterList[1].value; }
  ChangeUI();
}

//#endregion

//#region EXCLUDES

function PrepareExcludes() {
  //CreateExclude("3-6", 24, null);
}

//selectValue = string "0-1" == 0 - selected group; 1 - selected value;
//targetGroup = int 0 - 0 == target group;
//targetOption = int 0 - 0 == target value;
// eslint-disable-next-line no-unused-vars
function CreateExclude(selectValue, targetGroup, targetOption) {
  var element = document.createElement("div");
  element.className = 'exclude_item exclude_' + selectValue;
  element.setAttribute('data-target_group', targetGroup);

  if (targetOption != null) {
    element.setAttribute('data-target_option', targetOption);
  }

  summary.appendChild(element);
}

//#endregion

//#region DEBUG

// eslint-disable-next-line
function DebugLog(value, color = 'blue', fontSize = 'larger') {
  // console.log('%c' + value, 'color: ' + color + '; font-size: ' + fontSize);
}

// eslint-disable-next-line no-unused-vars
function DebugAlert(value) {
  alert(value);
}

//#endregion

//#region ADDITIONAL FUNCTIONS

function ParseAllGroups() {
  mainGroups.forEach(target => {
    if (!target.group.element.classList.contains("disabled")) {
      switch (target.type) {
        case "select":
        case "select_no_photo":
          for (let i = 0; i < target.group.options.length; i++) {
            const opt = target.group.options[i];

            if (opt.element.classList.contains("active")) {
              SetGroupActionForSharedParameters(target.id, opt.component_id, null, true);
              break;
            }
          }
          break;
        case "range":
          SetGroupActionForSharedParameters(target.id, target.group.input.value, null, true);
          break;
        case "checkbox":
          SetGroupActionForSharedParametersCheckboxArray(target.id, target.group.options, null, true);
          break;
        case "number":
          SetGroupActionForSharedParameters(target.id, target.group.input.value, null, true);
          break;
        case "dropdown":
          SetGroupActionForSharedParameters(target.id, target.group.select.value, null, true);
          break;
        case "text":
          //You can do something here...
          break;
      }
    }
  });
}

function ChangeRangeOptions(groupID) {
  jQuery(document).ready(function ($) {
    let group = $('#' + groupID);
    let range_option = [];
    let range = group.find('input');
    // console.log(range);
    group.find('.option').removeClass('active');
    beforeFilterAction();
    group.find('.option:not(.disable_filter)').each(function () {

      // Get divided values from the input data.
      const values = $(this).data('value').toString().split('-');

      // Create minimum and maximum variables.
      let min = 0.0;
      let max = 0.0;

      // Check the resulting array of values for the number of elements.
      if (values.length == 1) {
        // If we have 1 element, the minimum and maximum values will be the same.
        max = parseFloat(values[0]);
        min = max;
      } else {
        // Assign a minimum and maximum value.
        min = parseFloat(values[0]);
        max = parseFloat(values[1]);

        // Check the minimum and maximum values and whether one is larger than the other or vice versa.
        if (max < min || min > max) {
          // If the maximum value is less than the minimum value or the minimum value is greater than the maximum value, assign the maximum value to the minimum value.
          max = min;
        }
      }

      // Check if the input value is within the range of the required values.
      if (range.val() >= min && range.val() <= max) {
        range_option.push($(this));
      }
    });

    // If the value array is empty, there is no point in continuing. Calling a callback.
    if (range_option.length == 0) {
      return;
    }

    range_option.forEach(element => {
      $('.selected_components-' + element.data('group_id')).attr('checked', false);
    });

    $('#group-' + range_option[0].data('group_id')).find('.option .component_options .option_settings').each(function () {
      if ($("#ar_filter .option.active .option_settings.option-" + $(this).data('name')).length == 0) {
        hideObject($(this).data('name'));
      }
    });

    range_option.forEach(element => {
      $('.selected_components-' + element.data('group_id') + '-' + element.data('component_id')).attr('checked', true);
      element.addClass('active');
    });

    afterFilterAction(group);
  });
}

function promiseDelay(time, callback) {
  if (time == null) {
    time = 2000;
  }

  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('resolved');
      if (callback != null) {
        callback();
      }
    }, time);
  });
}

function promiseDelayTheModel(time, callback) {
  if (time == null) {
    time = 2000;
  }

  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('resolved');
      if (theModel == null) {
        promiseDelayTheModel(time, callback);
      } else {
        if (callback != null) {
          callback();
        }
      }
    }, time);
  });
}

// eslint-disable-next-line no-unused-vars
function udid() {
  return Date.now().toString(36) + Math.random().toString(36).substr(2);
}

function GetObject(name) {
  var object = null;
  theModel.traverse((o) => {
    if (o.isMesh) {
      if (name == o.name) {
        object = o;
      }
    }
  });

  return object;
}

function GetGroup(name) {
  var group = null;
  theModel.traverse((o) => {
    if (o.isGroup) {
      if (name == o.name) {
        group = o;
      }
    }
  });

  return group;
}

function GetMaterial(name) {
  var material = null;
  theModel.traverse((o) => {
    if (o.isMaterial) {
      if (name == o.material.name) {
        material = o.material;
      }
    }
  });

  return material;
}

function SetObjectVisibility(name, value) {
  let objMesh = GetObject(name);

  if (!objMesh) {
    objMesh = GetGroup(name);
  }

  if (!objMesh) {
    console.log(`ERROR !!! Mesh named "${name}" is not found !!!`);
    return;
  }

  if (objMesh.isMesh) {
    objMesh.visible = value;
  } else {
    objMesh.traverse((o) => {
      if (o.isMesh) {
        o.visible = value;
      }
    });
  }
}

function GetMobileOperatingSystem() {
  var userAgent = navigator.userAgent || navigator.vendor || window.opera;

  if (/Macintosh/i.test(userAgent)) {
    return "Macintosh";
  }

  if (/Windows/i.test(userAgent) || /Win/i.test(userAgent)) {
    return "Windows";
  }

  if (/windows phone/i.test(userAgent)) {
    return "Windows Phone";
  }

  if (/android/i.test(userAgent)) {
    return "Android";
  }

  if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
    return "iOS";
  }

  return "unknown";
}

function waitFor(conditionFunction) {

  const poll = resolve => {
    if (conditionFunction()) resolve();
    // eslint-disable-next-line no-unused-vars
    else setTimeout(_ => poll(resolve), 400);
  }

  return new Promise(poll);
}

// eslint-disable-next-line no-unused-vars
function UpdateActiveOption(groupId) {
  const parentGroup = mainGroups.find(element => element.id == groupId);
  if (!parentGroup) { return; }
  const group = parentGroup.group;

  if (!group.element.classList.contains("disabled")) {
    promiseDelay(100, () => {
      for (let i = 0; i < group.options.length; i++) {
        if (!group.options[i].element.classList.contains("disabled") &&
          group.options[i].element.classList.contains("active")) {
          group.options[i].element.classList.remove("active");
          group.options[i].element.click();
          break;
        }
      }
    });
  }
}

function CheckAssign(SharedParameterListItem) {
  for (let i = 0; i < SharedParameterListItem.groupIds.length; i++) {
    const groupId = SharedParameterListItem.groupIds[i];
    const parentGroup = mainGroups.find(element => element.id == groupId);
    if (parentGroup == null) { continue; }
    const group = parentGroup.group;

    if (!group.element.classList.contains("disabled")) { continue; }
    let hasValue = false;

    for (let o = 0; o < group.options.length; o++) {
      const opt = group.options[o];

      if (opt.component_id != SharedParameterListItem.value) {
        if (opt.element.classList.contains("active")) {
          opt.element.classList.remove("active");
        }
        continue;
      }

      if (!opt.element.classList.contains("active")) {
        opt.element.classList.add("active");
        group.activeOption = o;
      }

      hasValue = true;
    }

    if (!hasValue) {
      const opt = group.options[0];

      if (!opt.element.classList.contains("active")) {
        opt.element.classList.add("active");
        group.activeOption = 0;
      }
    }

    const selectElement = jQuery(`#${groupId}`).find('select');

    if (selectElement.find(`option[value="${SharedParameterListItem.value}"]`).length > 0) {
      selectElement.val(SharedParameterListItem.value);
    } else {
      selectElement.val('0');
    }
  }
}

//#endregion

//#region UI FUNCTIONS

function PrepareUI() {
  var GLTFExporter_script = document.createElement('script');
  GLTFExporter_script.setAttribute('src', 'https://cdn.jsdelivr.net/npm/three@0.146/examples/js/exporters/GLTFExporter.js');
  document.body.appendChild(GLTFExporter_script);

  formElement = document.querySelector('.ar_result_container .cart');

  for (let i = 0; i < mainGroups.length; i++) {
    let toggle = jQuery(mainGroups[i].element).find("div.ar_filter_header");
    let optPart1 = jQuery(mainGroups[i].element).find("div.ar_filter_description");
    let optPart2 = jQuery(mainGroups[i].element).find("div.ar_group_config");
    let optPart3 = jQuery(mainGroups[i].element).find("div.ar_filter_inputs");
    let optPart4 = jQuery(mainGroups[i].element).find("div.ar_filter_options");
    let optPart5 = jQuery(mainGroups[i].element).find("div.custom-input-container");
    let optPart6 = jQuery(mainGroups[i].element).find("div.ar_filter_options_result");
    const speed = 300;

    toggle.on('click', function () {
      toggle.toggleClass('invisible');
      optPart1?.slideToggle(speed);
      optPart2?.slideToggle(speed);
      optPart3?.slideToggle(speed);
      optPart4?.slideToggle(speed);
      optPart5?.slideToggle(speed);
      if (!optPart4.hasClass('type_checkbox')) {
        optPart6?.slideToggle(speed);
      }
    });
  }

  jQuery(document).ready(function ($) {
    $("#group-4 .customer_value_container input").change(function () {
      var value = jQuery(this).val();

      setTimeout(function () {
        $(".ar_result_container .cart .hidden_option.selected_components-4-1").val(`${value} cm`);
      }, 100);

    });
  });

  // Custom Length input
  const parentGroupLength = mainGroups.find(element => element.id == "group-34");
  var groupLength = parentGroupLength.group;

  if (groupLength != null) {
    inputCustomLength = document.createElement("INPUT");
    inputCustomLength.setAttribute("type", "number");
    inputCustomLength.setAttribute("step", 5);
    inputCustomLength.setAttribute("min", 90);
    inputCustomLength.setAttribute("max", 200);
    inputCustomLength.setAttribute("value", SharedParameterList[1].value);

    var div = document.createElement("div");
    div.classList.add("custom-input-container");

    const span = document.createElement("span");
    span.classList.add("custom-input-label");

    span.textContent = "ANGIV ØNSKET STØRRELSE:";

    div.appendChild(span);
    div.appendChild(inputCustomLength);

    groupLength.element.insertBefore(div, groupLength.element.lastElementChild);

    inputCustomLength.addEventListener('change', function () {
      const min = parseInt(this.min);
      const max = parseInt(this.max);
      let value = parseInt(this.value);

      if (isNaN(value)) {
        value = min;
      } else {
        value = Math.min(Math.max(value, min), max);
      }

      this.value = value;

      SetGroupActionForSharedParameters("group-34", inputCustomLength.value, () => {
        groupLength.input.value = inputCustomLength.value;
        groupLength.input.dispatchEvent(new Event('input'));
        ChangeRangeOptions("group-34");
        CheckChanges();
        WriteURLParameters();
      });
    });
  }

  // *****   Container for AR_CONF  *****
  jQuery(document).ready(function ($) {
    const arConfContainer = $('<div class="ar_conf_container"></div>');
    const arModelViewer = $('.ar_model_viewer');
    const summary = $('.summary.entry-summary');
    arConfContainer.insertBefore(arModelViewer);
    arConfContainer.append(arModelViewer);
    arConfContainer.append(summary);
  });

  // ***********************************************
  let scrollY = window.scrollY;
  let windowWidth = window.innerWidth;
  let headerHeight = 70;
  const canvasBlock = document.querySelector('.ar_model_viewer');
  const menuBlock = document.querySelector('.summary.entry-summary');

  let canvasHeight = canvasBlock.offsetHeight;
  let menuHeight = menuBlock.offsetHeight;
  let topPos = scrollY + canvasBlock.getBoundingClientRect().top;

  function handleScroll() {
    windowWidth = window.innerWidth;
    canvasHeight = canvasBlock.offsetHeight;
    menuHeight = menuBlock.offsetHeight;
    scrollY = window.scrollY;

    if ((menuHeight <= canvasHeight) && (windowWidth >= 779)) {
      menuHeight = canvasHeight;
      canvasBlock.style.position = 'relative';
      canvasBlock.style.top = '0px';
      menuBlock.style.margin = '';
    }

    if (windowWidth < 779) {
      if (scrollY <= topPos) {
        canvasBlock.style.top = 'auto';
        canvasBlock.style.position = 'static';
        menuBlock.style.margin = '0';
      }

      if (scrollY > (topPos - headerHeight)) {
        canvasBlock.style.top = `${headerHeight}px`;
        canvasBlock.style.position = 'fixed';
        menuBlock.style.margin = `${canvasHeight}px 0 0 0`;
      }

      if (scrollY > menuHeight) {
        canvasBlock.style.top = `${headerHeight - scrollY + menuHeight}px`;
      }
    }

    if (windowWidth >= 779) {
      menuBlock.style.margin = '';

      if (menuHeight > canvasHeight) {
        if (scrollY > (topPos - headerHeight)) {
          canvasBlock.style.top = `${headerHeight}px`;
          canvasBlock.style.position = 'fixed';
        } else {
          canvasBlock.style.position = 'relative';
          canvasBlock.style.top = '0px';
        }

        if (scrollY >= (menuHeight - canvasHeight + topPos - headerHeight)) {
          canvasBlock.style.position = 'relative';
          canvasBlock.style.top = `${menuHeight - canvasHeight}px`;
        }
      }
    }
  }

  function handleWindowResize() {
    windowWidth = window.innerWidth;
    canvasHeight = canvasBlock.offsetHeight;
    menuHeight = menuBlock.offsetHeight;

    if (windowWidth >= 779) {
      menuBlock.style.margin = '';
    }
  }

  window.addEventListener('scroll', handleScroll);
  window.addEventListener('resize', handleWindowResize);
  // ***********************************************

  // *****   Scale for the input range  *****
  jQuery(document).ready(function ($) {
    const scaleContainer = $(".ar_filter_inputs.type_range");
    const optionContainer = $(".ar_filter_options.type_range");
    const input = $("input[type='range']");
    const minValue = parseInt(input.attr("min"));
    const maxValue = parseInt(input.attr("max"));

    scaleContainer.append('<div class="progress_line"></div>');
    const progressLine = $(".progress_line", scaleContainer);

    const startValue = parseInt(input.val());
    const startPercentage = ((startValue - minValue) / (maxValue - minValue)) * 100;
    progressLine.width(startPercentage + "%");

    $(".option", optionContainer).each(function () {
      const value = parseInt($(this).data("value"));
      const percentage = ((value - minValue) / (maxValue - minValue)) * 100;

      if (!$(this).hasClass("hidden")) {
        const label = $(`<div class="label">${value}</div>`);
        const line = $(`<div class="line"></div>`);

        $(scaleContainer).append(label).append(line);
        $(label).css("left", percentage + "%");
        $(line).css("left", percentage + "%");
      }
    });

    input.on("input", function () {
      const currentValue = parseInt($(this).val());
      const currentPercentage = ((currentValue - minValue) / (maxValue - minValue)) * 100;
      progressLine.width(currentPercentage + "%");

      const labels = $(".label", scaleContainer);

      const activeLabel = labels.filter(function () {
        return parseInt($(this).text()) === currentValue;
      });

      const leftLabels = labels.filter(function () {
        return parseInt($(this).text()) <= currentValue;
      });

      labels.removeClass("active");

      if (activeLabel.length > 0) {
        activeLabel.addClass("active");
      } else {
        leftLabels.last().addClass("active");
      }
    });
  });

  // *****   Buttons on the AR-canvas: Hide, AR and SHARE  *****
  jQuery(document).ready(function ($) {
    const modelViewerElement = $(".ar_model_viewer");

    const tblHiderContainer = $('<div class="tbl-window-btn tbl-hider-container"></div>');
    const tblHiderIcon = $('<div class="tbl-hider-icon"></div>');
    const hideIcon = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/arrow-right.png" alt="Hide">');

    tblHiderIcon.append(hideIcon);
    tblHiderContainer.append(tblHiderIcon);

    const tblInstrContainer = $('<div class="tbl-window-btn tbl-instr-container"></div>');
    const tblInstrIcons = $('<div class="tbl-instr-icons"></div>');
    const leftClickIcon = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/left-click.svg" alt="click">');
    const plusIcon = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/plus.svg" alt="plus">');
    const scrollIcon = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/scroll.svg" alt="scroll">');
    const tblInstrText = $('<span class="tbl-window-btn-text">CONTROLS</span>');

    tblInstrIcons.append(leftClickIcon).append(plusIcon).append(scrollIcon);
    tblInstrContainer.append(tblInstrIcons).append(tblInstrText);

    tblWindowArBtn = $('<div class="tbl-window-btn tbl-window-btn-ar"></div>');
    const buttonArQr = $('<div id="button_ar_qr" class="tbl-window-btn-item js-tbl-info" data-info="qr"></div>');
    const tblWindowArIcon = $('<div class="tbl-window-btn-icon tbl-window-btn-icon-ar"></div>');
    const arIcon = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/cube.svg" alt="AR">');
    const arText = $('<span class="tbl-window-btn-text">PLACER I RUMMET</span>');

    tblWindowArIcon.append(arIcon);
    buttonArQr.append(tblWindowArIcon).append(arText);
    tblWindowArBtn.append(buttonArQr);

    tblWindowArBtn.on('click', function () {
      OpenARorQR();
    });

    tblWindowShareBtn = $('<div class="tbl-window-btn tbl-window-btn-share"></div>');
    const tblInvisibleBlock = $('<div class="tbl-window-btn tbl-window-invible-block"></div>');
    const buttonShareUrl = $('<div id="button_share_url" class="tbl-window-btn-item js-tbl-info" data-info="sharing"></div>');
    const tblWindowShareIcon = $('<div class="tbl-window-btn-icon"></div>');
    const shareIcon = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/share.svg" alt="S">');
    const shareText = $('<span class="tbl-window-btn-text">DEL</span>');

    tblWindowShareIcon.append(shareIcon);
    buttonShareUrl.append(tblWindowShareIcon).append(shareText);
    tblWindowShareBtn.append(buttonShareUrl);

    tblWindowShareBtn.on('click', function () {
      tblInfo.toggleClass('active');
      tblInfoItemSharing.toggleClass('active');
      tblInfoItemQr.removeClass('active');
      infoSharingInput[0].value = GetURLWithParameters();
    });

    modelViewerElement.append(
      tblHiderContainer,
      tblInstrContainer,
      tblWindowArBtn,
      tblWindowShareBtn,
      tblInvisibleBlock,
    );

    arPriceAmount = $('.ar_price_amount');
    btnAddToCart = $('.single_add_to_cart_button');

    // Canvas: top elements
    const tblAcceptContainer = $('<div class="tbl-accept-container"></div>');

    const tblAcceptPriceBlock = $('<div class="tbl-accept-price-block"></div>');
    const tblAcceptCurrency = $('<span class="tbl-accept-currency">Kr.</span>');
    tblAcceptPrice = $('<span class="tbl-accept-price" id="duplicate_ar_price_amount"></span>');
    tblAcceptPriceBlock.append(tblAcceptCurrency, tblAcceptPrice);

    const tblAcceptBtn = $('<button class="tbl-accept-btn">Tilføj til kurv</button>');

    tblAcceptBtn.addClass("disabled");
    const activationCheckbox = $('#ar_order_agreement');

    function scrollToCheckbox() {
      const checkboxRect = activationCheckbox[0].getBoundingClientRect();

      window.scrollTo({
        top: window.scrollY + checkboxRect.bottom - window.innerHeight + 100,
        behavior: 'smooth'
      });

      activationCheckbox.addClass('highlight-checkbox');
    }

    activationCheckbox.on('change', function () {
      if (activationCheckbox.prop('checked')) {
        activationCheckbox.removeClass('highlight-checkbox');
        tblAcceptBtn.removeClass("disabled");
      } else {
        tblAcceptBtn.addClass("disabled");
      }
    });

    tblAcceptBtn.on('click', function () {
      if (activationCheckbox.prop('checked')) {
        // alert('Product added to cart!');
        btnAddToCart[0].click();
      } else {
        scrollToCheckbox();
      }
    });

    window.addEventListener('load', function () {
      tblAcceptPrice[0].innerHTML = arPriceAmount[0].innerHTML + ",-";
    });

    window.addEventListener('click', function () {
      tblAcceptPrice[0].innerHTML = arPriceAmount[0].innerHTML + ",-";
    });

    const shippingNoteElement = document.querySelector('.shipping-note');
    const shippingNoteElementText = shippingNoteElement.textContent;
    const tblAcceptTextBlock = $('<div class="tbl-accept-text-block"></div>');
    const tblAcceptText = $('<span class="tbl-accept-text"></span>');
    $('.tbl-accept-text').text(shippingNoteElementText);
    tblAcceptTextBlock.append(tblAcceptText);

    tblAcceptContainer.append(tblAcceptPriceBlock, tblAcceptBtn, tblAcceptTextBlock);
    modelViewerElement.append(tblAcceptContainer);

    const summaryElement = $(".summary.entry-summary");

    tblHiderContainer.on('click', function () {
      tblHiderContainer.toggleClass('invisible');
      tblHiderIcon.toggleClass('invisible');
      hideIcon.toggleClass('invisible');
      modelViewerElement.toggleClass('wide');
      summaryElement.animate({
        width: 'toggle'
      }, 300);
      if (modelViewerElement.hasClass('wide')) {
        window.scrollTo(0, topPos - headerHeight);
        canvasBlock.style.position = 'relative';
        canvasBlock.style.top = '0px';
      }
    });
  });

  // *****   ACCEPT-BLOCK  *****
  jQuery(document).ready(function ($) {
    const $agreementText = $('.ar_order_agreement_text');
    const content = $agreementText.html();
    const parts = content.split('</b>');
    const titlePart = parts[0].replace('<b>', '').trim();
    const contentPart = parts[1].trim();
    const newContent = `
      <div class="ar_order_agreement_text-title">${titlePart.slice(0, -1)}</div>
      <span>*</span>
      <div class="ar_order_agreement_text-content">${contentPart}</div>
    `;
    $agreementText.html(newContent);
    $('.ar_order_agreement_text-content').css('text-align', 'justify');
  });

  // *****   POP-UPs   *****
  jQuery(document).ready(function ($) {
    tblInfo = $('<div class="tbl-info">');
    const tblInfoBox = $('<div class="tbl-info-box">');

    tblInfoItemSharing = $('<div class="tbl-info-item" data-info-window="sharing">');
    const tblInfoSharing = $('<div class="tbl-info-sharing">');
    const tblInfoSharingTitle = $('<div class="tbl-info-sharing-title">Del konfiguration</div>');
    const tblInfoSharingWindow = $('<div class="tbl-info-sharing-window">');
    infoSharingInput = $('<input id="info-sharing-input" type="text" value="">');
    tblInfoSharingIco = $('<div class="tbl-info-sharing-ico">');
    const icoImage = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/share2.svg" alt="S">');

    tblInfoSharingIco.on('click', function () {
      copyToClipboard();
    });

    tblInfoSharingIco.append(icoImage);
    tblInfoSharingWindow.append(infoSharingInput, tblInfoSharingIco);
    tblInfoSharing.append(tblInfoSharingTitle, tblInfoSharingWindow);
    tblInfoItemSharing.append(tblInfoSharing);

    tblInfoItemQr = $('<div class="tbl-info-item" data-info-window="qr">');
    const tblQr = $('<div class="tbl-qr">');
    const tblQrTitle = $('<div class="tbl-qr-title">Placer dit bord direkte i dit hjem med vores AR-funktion. Scan QR-koden med din telefon. AR-funktionen åbner på din telefon inden for 1-3 sekunder.</div>');
    const tblQrImg = $('<div class="tbl-qr-img">');
    qrcode = $('<div id="qrcode"></div>');

    tblQrImg.append(qrcode);
    tblQr.append(tblQrTitle, tblQrImg);
    tblInfoItemQr.append(tblQr);

    tblInfoClose = $('<div class="tbl-info-close">');
    const closeImage = $('<img src="/wp-content/themes/dt-the7/images/ar-ui-icons/cross.svg" alt="X">');
    tblInfoClose.append(closeImage);

    tblInfoClose.on('click', function () {
      tblInfo.removeClass('active');
      tblInfoItemQr.removeClass('active');
      tblInfoItemSharing.removeClass('active');
    });

    const tblInfoOverlay = $('<div class="tbl-info-overlay"></div>');

    tblInfoOverlay.on('click', function () {
      tblInfo.removeClass('active');
      tblInfoItemQr.removeClass('active');
      tblInfoItemSharing.removeClass('active');
    });

    tblInfoBox.append(tblInfoItemSharing, tblInfoItemQr, tblInfoClose);
    tblInfo.append(tblInfoBox, tblInfoOverlay);

    const productType3DModel = $('.product-type-3dmodel');
    productType3DModel.append(tblInfo);
  });

  // Bottom text with a delivery info
  jQuery(document).ready(function ($) {
    const shippingNoteElement = document.querySelector('.shipping-note');
    const shippingNoteElementText = shippingNoteElement.textContent;
    const acceptTextBlock = $('<div class="tbl-accept-text-block-menu"></div>');
    const acceptText = $('<span class="tbl-accept-text"></span>');
    $('.tbl-accept-text').text(shippingNoteElementText);
    acceptTextBlock.append(acceptText);
    const productContainer = $(".product-type-3dmodel");
    const addToCartButton = productContainer.find("button.single_add_to_cart_button");

    if (addToCartButton.length > 0) {
      acceptTextBlock.insertAfter(addToCartButton);
    }
  });
}

function ChangeUI() {
}

//#endregion

//#region URL PARAMETERS

// eslint-disable-next-line no-unused-vars
function PrepareURLParameters() {
}

function GetParameterSplitString(array) {
  if (array.length == 0) { return; }

  var params = [];
  for (let index = 0; index < array.length; index++) {
    params.push(array[index].splitValue);
  }
  return new RegExp(`${params.join("|")}`)
}

function ReadURLParameters(callback) {
  const queryString = window.location.search;
  console.log(queryString);
  const urlParams = new URLSearchParams(queryString);
  // const keys = urlParams.keys();
  // const values = urlParams.values();
  const entries = urlParams.entries();

  var parseParams = "";

  for (const entry of entries) {
    if (entry[0] == parametersKey) {
      parseParams = entry[1];
      break;
    }
  }

  console.log(parseParams);

  if (!parseParams?.trim()) {
    paramsLoaded = true;
    EmptyURLParams();
    if (callback != null) { callback(); }
    return;
  }

  const paramArray = parseParams.split(GetParameterSplitString(SharedParameterList));

  if (paramArray.length == 0) {
    paramsLoaded = true;
    EmptyURLParams();
    if (callback != null) { callback(); }
    return;
  }

  console.log(paramArray);

  for (let index = 0; index < SharedParameterList.length; index++) {
    const element = SharedParameterList[index];
    let arrayValue;

    switch (element.type) {
      case 'string':
        element.value = paramArray[index + 1]?.toString();
        break;
      case 'int':
        element.value = parseInt(paramArray[index + 1]);
        break;
      case 'float':
        element.value = parseFloat(paramArray[index + 1]);
        break;
      case 'array-string':
        arrayValue = paramArray[index + 1]?.toString();
        element.value = GetSharedArrayValues(arrayValue, 'string');
        break;
      case 'array-int':
        arrayValue = paramArray[index + 1]?.toString();
        element.value = GetSharedArrayValues(arrayValue, 'int');
        break;
      case 'array-float':
        arrayValue = paramArray[index + 1]?.toString();
        element.value = GetSharedArrayValues(arrayValue, 'float');
        break;
    }

    if (element.id == "qr") {
      qrScaned = element.value;
    }
  }

  if (callback != null) callback();

  CheckQRMobile();
}

function GetSharedArrayValues(arrayValue, type) {
  var output = [];

  if (arrayValue == undefined || arrayValue == null) { return output; }
  if (arrayValue == "") { return output; }

  var options = arrayValue.split('-');
  for (let i = 0; i < options.length; i++) {
    switch (type) {
      case 'string':
        output.push(options[i]);
        break;
      case 'int':
        output.push(parseInt(options[i]));
        break;
      case 'float':
        output.push(parseFloat(options[i]));
        break;
    }
  }

  return output;
}

function delay(time) {
  return new Promise(resolve => setTimeout(resolve, time));
}

async function ApplyURLParameters(callback = () => { }) {
  let ar_order_link;

  if (paramsLoaded) {
    ar_order_link = jQuery("input[name='ar_order_link']");
    if (ar_order_link != null) {
      ar_order_link[0].value = GetURLWithParameters();
    }
    return;
  }

  for (const target of mainGroups) {
    const group = target.group;

    for (let i = 0; i < SharedParameterList.length; i++) {
      const SharedParameterListItem = SharedParameterList[i];

      if (SharedParameterListItem.groupIds == undefined || SharedParameterListItem.groupIds == null) { continue; }
      if (!SharedParameterListItem.groupIds.includes(target.id)) { continue; }

      if (SharedParameterListItem.applyURLActionReturn) {

        if (SharedParameterListItem.applyURLAction != null) {
          SharedParameterListItem.applyURLAction();
        }

        await delay(50);
        continue;
      }

      let option;
      switch (target.type) {
        case "select":
        case "select_no_photo":
          if (SharedParameterListItem.value == "") { break; }

          option = group.options.find(o => o.component_id == SharedParameterListItem.value);
          if (option == null) { break; }
          if (option.element.classList.contains("active")) { break; }

          for (let i = 0; i < group.options.length; i++) {
            const element = group.options[i];
            if (element.element.classList.contains("active")) {
              element.element.classList.remove("active");
            }
          }

          if (group.element.classList.contains("disabled")) {
            option.element.classList.add("active");
            break;
          }

          option.element.click();
          break;
        case "range":
          group.input.value = SharedParameterListItem.value;
          group.input.dispatchEvent(new Event('input'));
          ChangeRangeOptions(target.id);
          break;
        case "checkbox":
          for (let i = 0; i < SharedParameterListItem.value.length; i++) {
            const value = SharedParameterListItem.value[i];
            if (value == "1") {
              group.options[i].active = true;
              group.options[i].element.classList.add("active");
              //group.options[i].element.click();
            }
          }
          break;
        case "number":
          group.input.value = SharedParameterListItem.value;
          group.input.dispatchEvent(new Event('input'));
          break;
        case "dropdown":
          if (SharedParameterListItem.value == "") { break; }

          group.select.value = SharedParameterListItem.value;

          for (let index = 0; index < group.options.length; index++) {
            const element = group.options[index];
            if (element.component_id == SharedParameterListItem.value) {
              if (!element.element.classList.contains("active")) {
                element.element.classList.add("active");
              }
            } else {
              if (element.element.classList.contains("active")) {
                element.element.classList.remove("active");
              }
            }
          }
          if (!group.element.classList.contains("disabled")) {
            let additionalGroup = jQuery('#' + target.id);
            afterFilterAction(additionalGroup);
          }
          break;
        case "text":
          break;
      }

      if (SharedParameterListItem.applyURLAction != null) {
        SharedParameterListItem.applyURLAction();
      }
    }

    await delay(50);
  }

  ar_order_link = jQuery("input[name='ar_order_link']");
  if (ar_order_link != null) {
    ar_order_link[0].value = GetURLWithParameters();
  }

  paramsLoaded = true;

  setIsLoaderActive(false);

  callback();
}

function WriteURLParameters() {
  if (!paramsLoaded) { return; }
  qrScaned = 0;

  if (!delayForWriteURL) {
    delayForWriteURL = true;
    promiseDelay(500, function () {
      history.pushState(null, 'byMAIN', GetURLWithParameters());

      var ar_order_link = jQuery("input[name='ar_order_link']");
      if (ar_order_link != null) {
        ar_order_link[0].value = GetURLWithParameters();
      }

      if (formElement != null) {
        formElement.action = GetURLWithParameters();
      }

      delayForWriteURL = false;
    });
  }
}

function GetParametersString() {
  parametersValue = "";

  for (let index = 0; index < SharedParameterList.length; index++) {
    const element = SharedParameterList[index];

    if (element.value == undefined || element.value == null) { continue; }

    switch (element.type) {
      case 'array-string':
      case 'array-int':
      case 'array-float':
        parametersValue += element.splitValue;

        for (var i = 0; i < element.value.length; i++) {
          if (i == element.value.length - 1) {
            parametersValue += element.value[i];
          } else {
            parametersValue += element.value[i] + '-';
          }
        }
        break;
      default:
        parametersValue += element.splitValue + element.value;
        break;
    }
  }

  //You can do something here...
  return parametersValue;
}

function GetURLWithParameters() {
  const queryString = window.location.search;
  const urlParams = new URLSearchParams(queryString);

  // const keys = urlParams.keys();
  // const values = urlParams.values();
  const entries = urlParams.entries();

  var url = location.protocol + '//' + location.host + location.pathname + "?";

  var configEmpty = true;

  for (const entry of entries) {
    if (entry[0] == parametersKey) {
      url += parametersKey + "=" + GetParametersString() + "&";
      configEmpty = false;
    } else {
      url += entry[0] + "=" + entry[1] + "&";
    }
  }

  if (configEmpty) {
    url += parametersKey + "=" + GetParametersString();
  }

  if (url.endsWith("&")) {
    url = url.substring(0, url.length - 1);
  }

  return url;
}

//#endregion

//#region CLIPBOARD

const copyToClipboard = function () {
  var aux = document.createElement("input");
  aux.setAttribute("value", infoSharingInput[0].value);
  document.body.appendChild(aux);
  aux.select();
  document.execCommand("copy");
  document.body.removeChild(aux);
}

//#endregion

//#region QR

// eslint-disable-next-line no-unused-vars
function PrepareQR() {
}

function CreateQR() {
  var qr = qrcode[0];
  if (qr == null) { return; }

  while (qr.hasChildNodes()) {
    qr.removeChild(qr.lastChild);
  }

  qrScaned = 1;

  var uri = GetURLWithParameters();
  var encoded = encodeURIComponent(uri);
  var qrImg = new Image();
  //qrImg.src = 'https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=' + encoded;
  qrImg.src = 'https://quickchart.io/qr?text=' + encoded + "&size=200";
  qrImg.addEventListener("load", () => {
    qr.appendChild(qrImg);
  });
}

async function CheckQRMobile() {
  // eslint-disable-next-line no-unused-vars
  await waitFor(_ => loaded === true);

  if (qrScaned == 1) {
    if (GetMobileOperatingSystem() == "Android" || GetMobileOperatingSystem() == "iOS") {
      OpenAR();
    }
    qrScaned = 0;
  }
}

//#endregion

//#region AR

function PrepareAR() {
  jQuery(document).ready(function ($) {

    const body = $("body");

    modelViewer = $('<model-viewer id="marevo_model" ar ar-modes="webxr scene-viewer quick-look" src="https://s3.eu-central-1.amazonaws.com/marevo.vision/RelevantProjects/webAR/model-viewer-important/scenes/empty_scene.glb" poster="" ar-scale="fixed" loading="eager" alt="by MAIN" shadow-intensity="1" shadow-softness="1" environment-image="neutral" stage-light-intensity="1" camera-orbit="-30deg auto auto" max-camera-orbit="auto 100deg auto" camera-controls exposure="0.9" auto-rotate>');
    const arPromt = $('<div id="ar-prompt">');
    const icoImage = $('<img src="https://modelviewer.dev/shared-assets/icons/hand.png" alt="ar-prompt">');

    arPromt.append(icoImage);
    modelViewer.append(arPromt);

    body.append(modelViewer);

    modelViewer[0].addEventListener('ar-status', (event) => {
      if (event.detail.status == 'session-started') {
        arPromt[0].style.display = "block";
      } else if (event.detail.status == 'not-presenting') {
        arPromt[0].style.display = "none";
        modelViewer[0].resetScene();
      }
      else {
        arPromt[0].style.display = "none";
      }
    });
  });
}

async function OpenAR() {
  ComputeMorphedAttributes();
  ImportScene(scene);
}

function OpenARorQR() {

  if (GetMobileOperatingSystem() == "Android" || GetMobileOperatingSystem() == "iOS") {
    OpenAR();
    return;
  }

  CreateQR();

  tblInfo.toggleClass('active');
  tblInfoItemQr.toggleClass('active');
  tblInfoItemSharing.removeClass('active');
}

//IMPORT
async function ImportScene(newScene) {
  // eslint-disable-next-line no-unused-vars
  const value = await modelViewer[0].importScene(newScene);
  modelViewer[0].activateAR();
}

//#endregion

//Create your regions with the functions you need. Past projects can be used as an example.

//#region STØRRELSE

function PrepareStorrelse() {
}

function ChangeStorrelse() {
  var componentTitleG2 = document.querySelector("#group-34 > div.ar_filter_options_result > div.ar_filter_options_result_list > div > div.ar_filter_options_result_name");
  if (componentTitleG2 != null) componentTitleG2.textContent = (componentTitleG2.textContent.replace(' cm', '') + " cm");

  jQuery(".ar_summary .ar_summary_list .ar_summary_list_item .ar_summary_list_group").each(function () {
    if (jQuery(this).text() == "Størrelse") {
      var componentTitle = jQuery(this).parent().find(".ar_summary_list_components .ar_summary_list_components_component_title");

      if (componentTitle.text() == "100" || componentTitle.text() == "100 cm") {
        componentTitle.text("100 cm (min. 98 cm)");
      } else {
        componentTitle.text(componentTitle.text().replace(' cm', '') + " cm");
      }
    }
  });
}

function ChangeStorrelseDiameter() {
  var value = parseFloat(SharedParameterList[1].value);

  //Camara min-max distance position
  controls.minDistance = value / 100 / 2.2 * 2 + 0.15;
  controls.maxDistance = (value / 100 / 2.2 * 2 + 0.15) * 2;
}

//#endregion

//#region BENTYPE

function PrepareBentype() {
}

function ChangeBentype() {

  var groupBentype = mainGroups.find(g => g.id == "group-2");
  var groupRange = mainGroups.find(g => g.id == "group-34");

  if (groupBentype == null) { return; }
  if (groupRange == null) { return; }

  for (let index = 0; index < groupBentype.group.options.length; index++) {
    const opt = groupBentype.group.options[index];

    if (opt.component_id != SharedParameterList[5].value) { continue; }

    for (let i = 0; i < opt.componentOptions.length; i++) {
      const component = opt.componentOptions[i];

      if (component.targetObject == null) { continue; }

      if (groupRange.group.input.value >= 161) {
        if (component.targetObject.name.includes("3-pin_A-ben_8x4cm_small") || component.targetObject.name.includes("3-pin_A-ben_12x6cm_small")) {
          component.targetObject.visible = false;
        }
      } else {
        if (component.targetObject.name.includes("3-pin_A-ben_8x4cm_big") || component.targetObject.name.includes("3-pin_A-ben_12x6cm_big")) {
          component.targetObject.visible = false;
        }
      }
    }
  }
}

//#endregion

//#region SHADER

function Shader_ChangeVertexToWorldpos(object) {
  promiseDelayShaderSettings(500, object, () => {
    if (object.isMesh) {
      if (isWorldposVertexShaderEnabled) {
        if (object.material) {
          if (object.material.name.includes("_Z")) {
            object.material.onBeforeCompile = (shader) => {
              shader.vertexShader = shader.vertexShader.replace('#include <uv_vertex>\n', '').replace('#include <worldpos_vertex>', 'vec4 worldPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\nworldPosition = instanceMatrix * worldPosition;\n#endif\nworldPosition = modelMatrix * worldPosition;\nvUv = (uvTransform * vec3(worldPosition.xz, 1)).xy;');
            };
          }
          else if (object.material.name.includes("_Y")) {
            object.material.onBeforeCompile = (shader) => {
              shader.vertexShader = shader.vertexShader.replace('#include <uv_vertex>\n', '').replace('#include <worldpos_vertex>', 'vec4 worldPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\nworldPosition = instanceMatrix * worldPosition;\n#endif\nworldPosition = modelMatrix * worldPosition;\nvUv = (uvTransform * vec3(worldPosition.xy, 1)).xy;');
            };
          }
          else if (object.material.name.includes("_X")) {
            object.material.onBeforeCompile = (shader) => {
              shader.vertexShader = shader.vertexShader.replace('#include <uv_vertex>\n', '').replace('#include <worldpos_vertex>', 'vec4 worldPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\nworldPosition = instanceMatrix * worldPosition;\n#endif\nworldPosition = modelMatrix * worldPosition;\nvUv = (uvTransform * vec3(worldPosition.yz, 1)).xy;');
            };
          }
          object.material.needsUpdate = true;
        }
      }
    }
  });
}

function promiseDelayShaderSettings(time, object, callback) {
  if (time == null) {
    time = 2000;
  }

  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('resolved');
      if (object.material.map == null) {
        promiseDelayShaderSettings(time, object, callback);
      } else {
        if (callback != null) {
          callback();
        }
      }
    }, time);
  });
}

//#endregion

//#region MORPHS

function InitMorphModel(model) {
  var BufferGeometryUtils_script = document.createElement('script');
  BufferGeometryUtils_script.setAttribute('src', 'https://cdn.jsdelivr.net/npm/three@0.147/examples/js/utils/BufferGeometryUtils.js');
  document.body.appendChild(BufferGeometryUtils_script);

  model.traverse((object) => {
    if (object.isMesh) {

      Shader_ChangeVertexToWorldpos(object);

      if (object.morphTargetDictionary != null) {

        for (const [key, value] of Object.entries(object.morphTargetDictionary)) {

          var morph = {
            name: key,
            object: object,
            key: value,
            value: value
          };

          if (!morphs.includes(morph)) {
            morphs.push(morph);
          }
        }
      }
    }
  });

  PrepareGlobalMorphs();
}

function PrepareGlobalMorphs() {
  globalMorphs = [];

  for (let index = 0; index < morphs.length; index++) {
    const morph = morphs[index];

    var hasMorph = false;

    for (let m = 0; m < globalMorphs.length; m++) {
      const globalMorph = globalMorphs[m];
      if (globalMorph.name != morph.name) { continue; }
      hasMorph = true;
      break;
    }

    if (!hasMorph) {
      globalMorphs.push(morph);
    }
  }

  promiseDelay(1000, () => {
    CheckAssign(SharedParameterList[9]);
  });
}

// eslint-disable-next-line no-unused-vars
function ChangeObjectMorph(morph, inputvalue) {
  if (morph.object == null) { return; }

  if (morph.object.isMesh) {
    if (morph.object.morphTargetInfluences != null) {
      morph.object.morphTargetInfluences[morph.key] = inputvalue;
    }
  }
}

function ChangeGlobalMorph(morphName, inputvalue) {
  for (let index = 0; index < morphs.length; index++) {
    const morph = morphs[index];

    if (morph.name != morphName) { continue; }
    if (morph.object == null) { continue; }
    if (!morph.object.isMesh) { continue; }
    if (morph.object.morphTargetInfluences == null) { continue; }

    morph.object.morphTargetInfluences[morph.key] = inputvalue;
  }
}

function ComputeMorphedAttributes() {
  for (let index = 0; index < morphs.length; index++) {
    const morph = morphs[index];
    var computeMorphedAttributes = THREE.BufferGeometryUtils.computeMorphedAttributes(morph.object);
    morph.object.geometry.computeMorphedAttributes = computeMorphedAttributes;
  }
}

function animateMorph(
  morphName,
  valueStart,
  valueEnd,
  timeInterval = 200,
  steps = 25,
  callback = () => { }
) {
  const stepDuration = timeInterval / steps;
  const stepValue = (valueEnd - valueStart) / steps;
  let currentValue = valueStart;
  let completedSteps = 0;

  for (let i = 1; i <= steps; i++) {
    setTimeout(() => {
      ChangeGlobalMorph(morphName, currentValue);
      currentValue += stepValue;
      completedSteps++;
      if (completedSteps === steps) {
        ChangeGlobalMorph(morphName, valueEnd);
        callback();
      }
    }, i * stepDuration);
  }
}

//#endregion

//#region ANIMATION

// ANIMATION OF MODEL - "SCALING"
function animateScale(
  model,
  duration = 500,
  startScale = 0,
  endScale = 1,
  timingKeyword = 'ease-in',
  callback = () => { }
) {
  function timingFunction(progress) {
    switch (timingKeyword) {
      case 'ease-in':
        return progress * progress;
      case 'ease-out':
        return 1 - Math.pow(1 - progress, 2);
      case 'ease-in-out':
        return progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
      default:
        return progress;
    }
  }

  let startTime = null;

  function animate(currentTime) {
    if (!startTime) {
      startTime = currentTime;
    }

    const elapsedTime = currentTime - startTime;
    const progress = Math.min(elapsedTime / duration, 1);
    const easedProgress = timingFunction(progress);
    const interpolatedScale = startScale + (endScale - startScale) * easedProgress;
    model.scale.set(interpolatedScale, interpolatedScale, interpolatedScale);

    if (progress < 1) {
      requestAnimationFrame(animate);
    } else {
      model.scale.set(endScale, endScale, endScale);
      callback();
    }
  }

  requestAnimationFrame(animate);
}

//#endregion

//#region ADDITIONAL PLANK (INSERTING)

function insertPlank(SharedParameterListItem) {
  const groupIds = SharedParameterListItem.groupIds;

  if (!isPlankInserted) {
    ChangeGlobalMorph('falling', 0);
    ChangeGlobalMorph('insert', 0);
  } else {
    for (let i = 0; i < groupIds.length; i++) {
      const groupId = groupIds[i];
      const parentGroup = mainGroups.find(element => element.id == groupId);
      if (!parentGroup) { return; }
      const group = parentGroup.group;
      if (!group.element.classList.contains("disabled")) {
        switch (groupId) {
          case 'group-35': //* Round
          case 'group-40':
          case 'group-36':
          case 'group-41':
          case 'group-37':
          case 'group-42':
          case 'group-38':
          case 'group-43':
          case 'group-39':
            console.log("🚀 ~ insertPlank ~ insertedPlankRoundSize:", insertedPlankRoundSize);
            console.log("🚀 ~ insertPlank ~ SharedParameterList[9].value:", SharedParameterListItem.value);
            if (SharedParameterListItem.value == '0') {
              animateRoundOff(groupId);
            } else {
              animateRoundOn(SharedParameterListItem.value, groupId);
            }
            break;
          default:
            break;
        }
      }
    }
    shouldAnimate = false;
  }
}

function animateRoundOn(plankSize, groupId) {
  checkRails();
  const selectElement = jQuery(`#${groupId}`).find('select');
  const summaryBlock = jQuery('.summary.entry-summary');

  let startValue = 0;

  if (isPlankRoundInserted) {
    // startValue = (plankSize == '2') ? 0.5 : 1;

    switch (insertedPlankRoundSize) {
      case '1':
        startValue = 0.25;
        break;
      case '2':
        startValue = 0.5;
        break;
      case '3':
        startValue = 0.75;
        break;
      case '4':
        startValue = 1;
        break;
      default:
        break;
    }
  }

  // const targetValue = (plankSize == '1') ? 0.5 : 1;
  let targetValue = 0;

  switch (plankSize) {
    case '1':
      targetValue = 0.25;
      break;
    case '2':
      targetValue = 0.5;
      break;
    case '3':
      targetValue = 0.75;
      break;
    case '4':
      targetValue = 1;
      break;
    default:
      break;
  }

  if (shouldAnimate) {
    selectElement.prop('disabled', true);
    summaryBlock.css('pointer-events', 'none');

    isAnimation = true;
    checkRails();
    ChangeGlobalMorph('falling', 0);
    promiseDelay(100, () => {
      animateMorph('insert', startValue, targetValue + 0.1 * targetValue, 700, 50); // top, rails, legs
    });
    promiseDelay(1500, () => {
      animateMorph('falling', 0, 1, 500, 30);
    });
    promiseDelay(2000, () => {
      animateMorph('insert', targetValue + 0.1 * targetValue, targetValue, 300, 20); // top, rails, legs
      isAnimation = false;

      selectElement.prop('disabled', false);
      summaryBlock.css('pointer-events', 'auto');
    });
  }

  if (!isAnimation && isPlankInserted) {
    checkRails();
    ChangeGlobalMorph('falling', 1); // additional plank
    ChangeGlobalMorph('insert', targetValue); // top, rails, legs
  }

  isPlankRoundInserted = true;
  insertedPlankRoundSize = plankSize;
  isPlankInserted = true;
}

function animateRoundOff(groupId) {
  isPlankInserted = false;
  isPlankRoundInserted = false;
  const selectElement = jQuery(`#${groupId}`).find('select');
  const summaryBlock = jQuery('.summary.entry-summary');

  const targetValue = 0
  
  // const startValue = (insertedPlankRoundSize == '1') ? 0.5 : 1;
  let startValue = 0;

  switch (insertedPlankRoundSize) {
    case '1':
      startValue = 0.25;
      break;
    case '2':
      startValue = 0.5;
      break;
    case '3':
      startValue = 0.75;
      break;
    case '4':
      startValue = 1;
      break;
    default:
      break;
  }

  insertedPlankRoundSize = 0;

  if (shouldAnimate) {
    selectElement.prop('disabled', true);
    summaryBlock.css('pointer-events', 'none');
    isAnimation = true;

    ChangeGlobalMorph('falling', 0);
    animateMorph('insert', startValue, targetValue, 300, 20, checkRails()); // top, rails, legs

    promiseDelay(600, () => {
      isAnimation = false;
      selectElement.prop('disabled', false);
      summaryBlock.css('pointer-events', 'auto');
    });
  } else {
    ChangeGlobalMorph('falling', 0); // additional plank
    ChangeGlobalMorph('insert', targetValue); // top, rails, legs
    checkRails();
  }
}

function checkInsertedPlanks(SharedParameterListItem) {
  const groupIds = SharedParameterListItem.groupIds;

  for (let i = 0; i < groupIds.length; i++) {
    const groupId = groupIds[i];
    const parentGroup = mainGroups.find(element => element.id == groupId);
    if (!parentGroup) { return; }
    const group = parentGroup.group;

    if (!group.element.classList.contains("disabled")
      && group.activeOption !== 0
      && !group.options[group.activeOption].element.classList.contains("disabled")
    ) {
      isPlankInserted = true;
      return;
    }
  }

  isPlankInserted = false;
  CheckAssign(SharedParameterList[9]);
}

function checkInsertedPlanksSummary(SharedParameterListItem) {
  const groupIds = SharedParameterListItem.groupIds;

  for (let i = 0; i < groupIds.length; i++) {
    const group = jQuery(`#${groupIds[i]}`);
    if (!group.hasClass('disabled')) {
      const selectElement = jQuery(`#${groupIds[i]}`).find('select');
      const componentTitle = jQuery(`#${groupIds[i]}`).find('.ar_filter_options_result_name');
      const selectedOptionText = selectElement.find('option:selected').text();
      componentTitle.text(selectedOptionText);
      break;
    }
  }
}

function checkDiameterForInsertedPlanks(diameter) {
  if (diameter < 120 || diameter > 160) {
    const groupIds = SharedParameterList[9].groupIds;

    for (let i = 0; i < groupIds.length; i++) {
      const groupId = groupIds[i];
      const parentGroup = mainGroups.find(element => element.id == groupId);
      if (!parentGroup) { return; }
      const group = parentGroup.group;
      const selectElement = group.element.querySelector('select');
      selectElement.value = "0";
      group.activeOption = 0;
      let event = new Event('change');
      selectElement.dispatchEvent(event);

      isPlankInserted = false;
      isPlankRoundInserted = false;

      ChangeGlobalMorph('insert', 0); // top, rails, legs
      ChangeGlobalMorph('falling', 0); // additional plank

      needUpdateInsert = false;
    }
  }
}

function checkRails() {
  // const diameter = SharedParameterList[1].value;
  // if (diameter > 115 && diameter < 165 && isPlankInserted) {
    for (let i = 0; i < railsNames.length; i++) {
      const meshName = railsNames[i];
      SetObjectVisibility(meshName, false);
    }
  // }
}

function checkKantForInserts() {
  const diameter = SharedParameterList[1].value;
  
  if (diameter > 115 && diameter < 165 && isPlankInserted) {
    console.log("🚀 ~ checkKantForInserts ~ diameter, kant:", diameter, SharedParameterList[2].value);
    if (SharedParameterList[2].value == '0') {
      insertPlanksNames20.forEach(name => SetObjectVisibility(name, false));
    } else if (SharedParameterList[2].value == '1') {
      insertPlanksNames90.forEach(name => SetObjectVisibility(name, false));
    }
  }
}

function roundDefaultCheck() {
  if (SharedParameterList[9].value == '1' || SharedParameterList[9].value == '2') {
    const parentGroup = mainGroups.find(element => element.id == 'group-39');
    if (parentGroup == null) { return; }
    const group = parentGroup.group;
    for (let o = 0; o < group.options.length; o++) {
      const opt = group.options[o];
      if (opt.element.classList.contains("active")) {
        group.activeOption = o;
      }
    }
  }

  checkInsertedPlanks(SharedParameterList[9]);
  insertPlank(SharedParameterList[9]);
}

function toggleOptionDisplayForLegs() {
  if (SharedParameterList[9].value == '1' || SharedParameterList[9].value == '2') {
    const group = jQuery('#group-2');
    const options = group.find('.option.disabled');
    
    options.css('display', 'none');
  } else {
    const group = jQuery('#group-2');
    const options = group.find('.option');

    options.each(function() {
      if (jQuery(this).attr('style') && jQuery(this).css('display') === 'none') {
        jQuery(this).removeAttr('style');
      }
    });
  }
}

//#endregion
