var MochaTestSuite = Namespace.declare("org.mocha",
  class MochaTestSuite extends UcpComponent {
    static start() {
      console.log(this.name + " is ready");
      UcpComponentSupport.importLink(this.IOR.loader.basePath + "/src/css/mochaTestSuite.css", "stylesheet", "text/css");
    }

    static dependencies() {
      return [
        "/EAMD.ucp/Components/org/mocha/MochaTestSuite/1.0.0/MochaTestSuite.component.xml",
        "/EAMD.ucp/Components/org/mocha/MochaEngine/4.0.1/MochaEngine.component.xml",
        "/EAMD.ucp/Components/com/twitter/Bootstrap/3.3.7/Bootstrap.component.xml"

      ];
    }

    constructor() {
      super();
      this.components = {};
      this.initializedMochaSuite=false;
      this.classes='wrapper';
    }


    init() {
      if(this.isInitialized) {
        return;
      }
      super.init();

      return this;
    }


    async updateView(view) {
      if (!this.initializedMochaSuite && document.getElementById(view.viewId)) {
        this.initializedMochaSuite=true;
        await this.scan();
        if(location.search && location.search.length > 0) {
          const [variable, value] = location.search.split(/=/);
          if(variable === '?grep') {
            let [component, version] = decodeURI(value).split(/ /);
            version = version.replace(/\\/g,'');
            this.components = {
              [component]: {
                [version] : this.components[component][version]
              }
            };
          }
        }

        await this.checkComponents();
        this.engine = MochaEngine.getInstance().init();
        await this.loadClasses();
        await this.loadTests();
        this.engine.mocha.run();
        this.hideLoader();
      }
    }

    async scan(){
      this.showLoader('Scanning');
      const ucpComponents = await Structr.find("UcpComponentDescriptor");
      if (!ucpComponents || ucpComponents.length === 0) {
        console.log("no ucp components");
        return;
      }
      this.components = {};

      ucpComponents.forEach(comp => {
        if (!comp.model) {
          console.warn(comp);
          return;
        }
        const name = comp.name;
        const lVersion = (comp.model.version !== null) ? comp.model.version.name : null;
        if (!lVersion) {
          console.warn(`component ${name} has no version`);
          return;
        }
        if (
          comp.model.path.indexOf("org/demos") < 0 &&
          comp.model.path.indexOf("org/playground") < 0 &&
          comp.model.path.indexOf("org/playgound") < 0
        ) {
          const realName = name.replace(/\.component\.xml$/, '');
          this.components[realName] = this.components[realName] || {};

          const arr = comp.model.path.split(/\//);
          arr.pop();
          arr.push('test');
          arr.push('js');
          arr.push(`${realName}MochaTest.js`);

          this.components[realName][lVersion] = {
            href: comp.model.path,
            test: arr.join('/'),
            errors: [],
          };
        }
      });

    }

    checkComponents() {
      this.showLoader('Checking');
      const promises = [];
      for (const realName in this.components) {
        for (const version in this.components[realName]) {
          promises.push(this.checkComponent(realName, version));
        }
      }
      return Promise.all(promises);
    }

    checkComponent(realName, version){
      return Promise.all([
        this.linkExists(this.components[realName][version].href),
        this.linkExists(this.components[realName][version].test)
      ])
        .then(() => Promise.resolve())
        .catch(() => {
          delete this.components[realName][version];
          return Promise.resolve();
        });
    }

    loadClasses() {
      this.showLoader('Load classes');
      console.log('========');
      const promises = [];
      for (const realName in this.components) {
        const component = this.components[realName];
        for (const version in component) {
          if(component[version].errors.length === 0) {
            promises.push(this.engine.loadDescriptor(this.components[realName][version].href));
          }
        }
      }
      return Promise.all(promises);
    }

    loadTests() {
      this.showLoader('Load tests');
      const promises = [];
      for (const realName in this.components) {
        const component = this.components[realName];
        for (const version in component) {
          if(component[version].errors.length === 0) {
            promises.push(this.engine.loadTest(this.components[realName][version].test));
          }
        }
      }
      return Promise.all(promises);
    }




    showLoader(text) {
      const [info] = document.getElementsByClassName('loader-info');
      if(text) {
        info.innerHTML += `<p>${text}......</p>`;
      }
      info.classList.remove('hidden');
      document.getElementsByClassName('loader')[0].classList.remove('hidden');
    }

    hideLoader() {
      document.getElementsByClassName('loader-info')[0].classList.add('hidden');
      document.getElementsByClassName('loader')[0].classList.add('hidden');
    }



    linkExists(link) {
      const salt = new Date().getTime();
      link += link.indexOf('?') >=0 ? '&' : '?';
      link += `nocache=${salt}`;
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", link);

        xhr.onload = () => {
          if(xhr.status === 200) {
            return resolve();
          }
          return reject();
        };
        xhr.onerror = () => reject();
        xhr.send();
      });
    }


  }
);