var Poi3dModuleLoader = function (modules)
{
  this.moduleArray = modules;
  this.maxRetries = 3;
  this.loadedModules = 0;
  this.errorModules = 0;
  this.loadParallel = false;
  this.afterLoadFunction = null;
  this.versionString = "";

  this.checkForAfterLoad = function()
  {
    if(this.loadedModules + this.errorModules == this.moduleArray.length)
    {
      if(this.afterLoadFunction != null)
        this.afterLoadFunction();
    }
  };

  this.loadModules = function ()
  {
    let topModule = null;
    let module = null;

    for (let i = 0; i < this.moduleArray.length; i++)
    {
      if(this.versionString.length > 0)
        this.moduleArray[i].mLoc =  this.moduleArray[i].mLoc+"?v="+this.versionString;
      
      if(i==0)
      {
        topModule = this.addModule(null,this.moduleArray[i]);
        module = topModule;
      }
      else
        module = this.addModule(module,this.moduleArray[i]);
    }

    if((topModule != null)&&(this.loadParallel == false))
      this.loadModule(topModule,0);
    else
    {
      for (let i = 0; i < this.moduleArray.length; i++)
      {
        this.loadModule(this.moduleArray[i],0);
      }
    }
  };//Poi3dModuleLoader.loadModules

  this.addModule = function(upperModule,moduleDef)
  {
    let module = {mLoc:moduleDef.mLoc,subModule:null,loadFct:moduleDef.loadFct};
      
    if((upperModule != null)&&(this.loadParallel == false))
      upperModule.subModule = module;
    return module;
  };//Poi3dModuleLoader.addModule

  this.loadModule = function(moduleObj,errCount)
  {
    let elementToAdd = null;
    if(moduleObj.mLoc.includes(".js"))
    {
      elementToAdd = document.createElement('script');
    }
    else if(moduleObj.mLoc.includes(".mjs"))
    {
      elementToAdd = document.createElement('script');
      elementToAdd.type="module";
    }
    else if(moduleObj.mLoc.includes(".css"))
    {
      elementToAdd = document.createElement('link');
      elementToAdd.type="text/css";
      elementToAdd.rel="stylesheet";
    }
    else
    {
      elementToAdd=new Image();
    }

    elementToAdd.loaderObject = this;

    elementToAdd.onerror = function (loaderObject)
    {
      //console.log (moduleObj.mLoc + " error");

      errCount++;
      if(errCount < this.loaderObject.maxRetries)
      {
        let oldObj = moduleObj;
        moduleObj = {mLoc:oldObj.mLoc,subModule:oldObj.subModule,loadFct:oldObj.loadFct};
        this.loaderObject.loadModule(moduleObj,errCount);//rekursion
      }
      else //continue
      {
        this.loaderObject.errorModules++;
        this.loaderObject.checkForAfterLoad();

        if((moduleObj.subModule != undefined)&&(moduleObj.subModule != null))
          this.loaderObject.loadModule(moduleObj.subModule,0);//rekursion
        if(moduleObj.loadFct != null)
          moduleObj.loadFct();
      }
    };

    elementToAdd.onload = function (loaderObject)
    {
      //console.log (moduleObj.mLoc + " loaded");
      this.loaderObject.loadedModules++;

      if((moduleObj.subModule != undefined)&&(moduleObj.subModule != null))
        this.loaderObject.loadModule(moduleObj.subModule,0);//rekursion
      if(moduleObj.loadFct != null)
        moduleObj.loadFct();

      this.loaderObject.checkForAfterLoad();
    };

    if(moduleObj.mLoc.includes(".css"))
      elementToAdd.href = moduleObj.mLoc;
    else
      elementToAdd.src = moduleObj.mLoc;

    document.head.appendChild(elementToAdd);
  };//Poi3dModuleLoader.loadModule
};
