fcf.module({
  name: "fcfControls:templates/menu.wrapper.js",
  dependencies: ["fcf:NClient/Wrapper.js"],
  module: function(Wrapper){
    return class WrapperEx extends Wrapper{

      constructor(a_options){
        super(a_options);
      }

      async onOpenMenu(a_event, a_uri, a_open){
        a_event.preventDefault();
        a_event.stopPropagation();
        if (!this.getArg("dynamic"))
          return;
        this.setArg("innerOpen", true, true, true);
        this.setArg("innerOpenItem", true, true, true);
        await this.expandMenuItem(a_uri, !a_open);

      }

      async onClick(a_event, a_uri){
        if (!this.getArg("dynamic"))
          return;
        this.setArg("innerOpen", true, true, true);
        await this.expandMenuItem(a_uri, true, true, false);
      }

      async expandMenuItem(a_uri, a_opening, a_noredraw, a_async){
        a_async = a_async === undefined ? true : a_async;

        let self = this;
        let items = this.getArg("items");

        let result = undefined;

        let reqItems = [];
        let foundOpenLevel = undefined;

        fcf.each(items, (a_key, a_item)=>{
          if (a_uri == a_item.uri){
            a_item.animation = a_item.open != a_opening;
            a_item.open = a_opening;
            foundOpenLevel = a_item.level;
          } else if (
            foundOpenLevel !== undefined &&
            ((a_opening && foundOpenLevel && foundOpenLevel == (a_item.level - 1)) || (foundOpenLevel && !a_opening && foundOpenLevel <= (a_item.level - 1)))
          ) {
            a_item.visible = a_opening;
            if (!a_opening)
              a_item.open = false;
            if (a_opening && a_item.end){
              reqItems.push(a_item.uri);
              a_item.end = false;
            }
          } else if (foundOpenLevel !== undefined && a_item.level <= foundOpenLevel) {
            return false;
          }
        });

        let insertItems = {};
        if (!fcf.empty(reqItems)){
          if (!a_async){
            this.send({command: "extend", items: reqItems}, false).then((a_res)=>{ insertItems = a_res; });
          } else {
            insertItems = await this.send({command: "extend", items: reqItems});
          }
        }

        let newItems = [];
        fcf.each(items, (a_key, a_item)=>{
          newItems.push(a_item);
          if (fcf.empty(insertItems[a_item.uri]))
            return;
          a_item.noempty = true;
          fcf.each(insertItems[a_item.uri], (a_key, a_subitem)=>{
            newItems.push({
              uri:        a_subitem.uri,
              title:      a_subitem.title,
              current:    false,
              level:      a_item.level + 1,
              visible:    false,
              open:       false,
              noempty:    false,
              end:        true,
              animation:  false,
            });
          });
        })

        this.setArg("items", newItems, false, false, !!a_noredraw);
      }
    };
  }
});
