class Group {

    static PATH = Environment.dataApi + "/api/v2/flaw/group/"

    static GROUP_SELECTED = "____selected_group";
    static GROUP_SELECTED_NAME = "____selected_name";
    static GROUP_SELECTED_ICON = "____selected_icon";
    static GROUP_PARAM = "id";

    static CURRENT_GROUP_SELECTED = "___current_group_selected"
    static CURRENT_GROUP_NAME = "___current_group_name"
    static CURRENT_GROUP_ICON = "___current_group_icon"

    static GROUP_FIELD = "group"
    static GROUP_ISSUE_FLOW_FIELD = "issueFlow";

    static CLEANED_FIELDS = ['parent', 'issueFlow', 'status', 'sprint', 'priority', 'parent', 'issueType', 'project', 'solutionType']
    static BOARD_LIST = 'board';
    static ISSUE_LIST = 'issue';
    static PROJECT_LIST = 'project';
    static EPIC_LIST = 'epic';
    static STORY_LIST = 'story';

    static GROUPS_PANEL_ID = "sub-groups-menu";

    static withMyGroups(doWithGroups, async = true, error = null) {
        Executor.runGet(this.PATH + "my?limit=25", doWithGroups, async, Executor.HEADERS, error)
    }

    static selectGroup(group, e) {
      if(group) {
        cache.add(Group.GROUP_SELECTED, group.id).add(Group.GROUP_SELECTED_NAME, group.name).add(Group.GROUP_SELECTED_ICON, group.icon);
        PersonalSettings.setSetting(Group.GROUP_SELECTED, group.id)

        if (e != null) {
            h.from(e).cl("active_group");
        }
      }
    }

    static initTempValue() {
        cache.copyFrom(Group.CURRENT_GROUP_SELECTED, Group.GROUP_SELECTED)
            .copyFrom(Group.CURRENT_GROUP_NAME, Group.GROUP_SELECTED_NAME)
            .copyFrom(Group.CURRENT_GROUP_ICON, Group.GROUP_SELECTED_ICON);
    }


    static selectTempGroupValue(id, name, icon) {
        if (_.isNull(name)) {
            name = ""
        }
        cache.add(Group.GROUP_SELECTED, id).add(Group.GROUP_SELECTED_NAME, name).add(Group.GROUP_SELECTED_ICON, icon);
        $.toast(MagicPage.translate("flaw.app.group.selected") + " " + name)
    }

    static getTempValue() {

        return cache.get(Group.GROUP_SELECTED);
    }

    static deSelectTempGroupValue() {
        cache.removeAll([Group.GROUP_SELECTED, Group.GROUP_SELECTED_NAME, Group.GROUP_SELECTED_ICON]);
    }


    static drawGroupSelection() {
      Group.withMyGroups((groups) => {
        var el = h.div("current_group");
          _.each(groups.content, (group) => {
              el.add(Group.drawGroup(group))
          })

        var isGroups = groups && groups.content && !_.isEmpty(groups.content);
        var wrapper = h.div("chooser-wrapper").appendToBody().zIndex(999);
        if(!isGroups) {
          var magicFormOptions = new MagicFormOptions("flaw/group"); 
          magicFormOptions.setParent(this);
          magicFormOptions.setFormListener((e) => {
            Group.addGroupFormListener(e, wrapper)
          });
          var form = MagicForm.Instance("flaw/group", magicFormOptions);
          form.load();
        
        } else {
          h.div("modal").appendTo(wrapper)
          .add(h.div("title").text("pages.global.select.group"))
          .add(h.div("selected_item_caption").text("pages.group.selected_group_title"))
          .add(h.div("selected").add(Group.currentGroup()))
          .add(h.div("available_item_caption").text("pages.group.available_group_title"))
          .add(h.div("available_groups").add(el))
          .add(h.div("footer").addIf(isGroups, Group.generateSelectGroupFooter()));
        }        
      })
    }

    static addGroupFormListener(event, wrapper) {
      if(_e(event.type, MagicFormEvent.FORM_SHOW)) {
        var wrapp = event.form.getWrapper();
        wrapp.firstChildByClass(".close_inner_form")?.remove();
        wrapp.firstChildByClass(".close_auto_form")?.remove();
        wrapp.firstChildByClass(".close_and_save_auto_form")?.remove();

        _.each(event.form.getFields(), (field) => {
          if (_.e (field.getField(), 'defaultIssueFlow')){
            h.from(field.getFieldObject()).hide();
  
            return;
          }
        })
        return;
      }

      if(_e(event.type, MagicFormEvent.FORM_SAVED)) {
        wrapper.remove();

        event.form.getWrapper().parent().remove();

        Group.selectGroup(event.additional)

        try {
          drawMyGroups(Group.GROUPS_PANEL_ID, "menu-item");
        } catch (e) {       
        }
      }
    }

    static generateSelectGroupFooter() {
        return h.div("current_group").add(h.input("button").text("global.pages.group.close_group_selection")
            .cl("close_group_selection").click((e) => {
                h.from(e).parent().parent().parent().parent().remove()
            }));
    }


    static currentGroup() {
        let group = cache.get(Group.GROUP_SELECTED);

        if (_.isNull(group)) {
            group = PersonalSettings.getSetting(Group.GROUP_SELECTED + "")
            if (_.notNull(group)) {
                let groupFromServer = Group.getById(group);
                Group.selectGroup(groupFromServer);
                return;
            }
        }

        let groups;
        if (_.isNull(group)) {
            Executor.runGet(this.PATH + "my", (data) => {
                groups = data
            }, false)

            if (groups == null) {
                throw new Error("Cannot get groups of user")
            }

            Group.selectGroup(groups.content[0])

        }
        return h.div("current_group").add(Group.drawGroup());
    }

    static GroupListener(event) {
        if (utils.e(event.type, MagicRemoteChooser.EVENT_ITEM_SELECTED)) {
            if (utils.e(event.field, Group.GROUP_FIELD)) {
                Group.selectGroup({"id": event.additional.id})
            }
        }
    }

    static tableListener(event) {

    }

    static makeTitle(where, listType, id){

        Executor.runGet(Environment.dataApi + "/api/v2/flaw/"+ listType +"/root/fetch/details/"+ parseInt(id),(data)=>{
            h.from(where).text('', false).add(h.div(listType + 'title').text(data.data.name, false))

            Executor.runGet(Environment.dataApi + "/api/v2/flaw/issue/path/"+ parseInt(id) + "/" + listType, (newdata)=>{
                 h.from(where).add(new ConnectionView(newdata, true).getContainer())
            })
        })  
    }

    static drawCustomField(header, what, data, cellRender, listName) {

        if (utils.e(header.field, "status") && _.e(listName, Group.ISSUE_LIST)) {

            let path = Environment.dataApi + '/api/v2/flaw/issue/adjacent_status/' + data.id

            let imgPromote = h.img("promote.png").wh(20).pointer().click(() => {
                Issue.promote(data.id, function (data) {
                    cellRender.getParent().drawValues();
                })
            });
            let imgDemote = h.img("demote.png").wh(20).pointer().click((x) => {
                Issue.demote(data.id, function () {
                    cellRender.getParent().drawValues();
                });
            });

            Executor.runGet(path, function (data) {
                if (_.isFalse(data.hasBack)) {
                    imgDemote.click(() => {
                    }).cl('no-demote');
                }
                if (_.isFalse(data.hasForward)) {
                    imgPromote.click(() => {
                    }).cl('no-promote');
                }
                if (_.isNull(data.issueForm.issueFlow)) {
                    imgDemote.click(() => {
                    }).cl('no-flow-demote');
                    imgPromote.click(() => {
                    }).cl('no-flow-promote');
                    ;
                }
            })

            let val = h.div("value_status_span");
            let res = "";

            if (what != null && !utils.isEmpty(what.value)) {
                h.a("#")
                    .cl("object_link")
                    .text(what.value, false)
                    .click(() => {
                        h.magicView(what.key, header.remoteType, false, header.searchName).setParent(cellRender);
                        return false;
                    })
                    .appendTo(val);
            } else {
                val.text(what == null ? what : what.value, false);
            }

            //we add icon here if object contains an Icon (or download file link)
            if (
                what != null &&
                what.additional.icon != null &&
                what.additional.icon.length > 0
            ) {
                res = h
                    .img(what.additional.icon, Environment.defaultIconSize)
                    .cl("image_in_details")
                    .click(function (e) {

                      

                        utils.showFullImage(e.src);
                    })
                    .wh(16);
                val.get().prepend(res.get());
            }
            if (what == null) {
                val.text(null);
            }

            let r = h.div("status_field").add(imgDemote).add(val).add(imgPromote);

            val.get().style.background = what.additional.color;

            return r;
        }

        if(utils.e(header.field, "statuses") && utils.e(listName, Group.BOARD_LIST)){
            let div = h.div('statuses_field');

            new StatusesModal(div, data).init();

            return div
        }


        if (utils.e(header.field, "name")){

            if(utils.e(listName, Group.BOARD_LIST)){
                
                let div = h.div("name_content");
                div.addIf(_.notNull(data.icon), () => getDefaultIconPath(data.icon).wh(32).click((e) => {
                
                let path = Group.buildImgPath(e);
                    
                    utils.showFullImage2(path, e.icons)
                }))
                h.a(
                    Environment.self + "/pages/board/view?id=" + data.id,
                    data.name,
                    false
                )
                    .attr("target", "_blank")
                    .appendTo(div);
                return div;
                }

            if( utils.e(listName, Group.PROJECT_LIST)){

                let div = h.div("name_content");
                div.addIf(_.notNull(data.icon), () => getDefaultIconPath(data.icon).wh(32).click((e) => {
                
                let path = Group.buildImgPath(e);
                    
                    utils.showFullImage2(path, e.icons)
                }))
                h.a(
                    Environment.self + "/pages/project/view?id=" + data.id,
                    data.name,
                    false
                )
                    .attr("target", "_blank")
                    .appendTo(div);
                return div;
                }
            
            if(utils.e(listName, Const.EPIC_LIST)){

                let div = h.div("name_content");
                div.addIf(_.notNull(data.icon), () => getDefaultIconPath(data.icon).wh(32).click((e) => {
                  
                  let path = Group.buildImgPath(e);
                    
                    utils.showFullImage2(path, e.icons)
                }))
                h.a(
                    Environment.self + "/pages/epic/view?id=" + data.id,
                    data.name,
                    false
                )
                    .attr("target", "_blank")
                    .appendTo(div);
                return div;

            }

            if(utils.e(listName, Group.STORY_LIST)){

                let div = h.div("name_content");
                div.addIf(_.notNull(data.icon), () => getDefaultIconPath(data.icon).wh(32).click((e) => {
              
                let path = Group.buildImgPath(e);
                
                utils.showFullImage2(path, e.icons)
                 }))
                h.a(
                    Environment.self + "/pages/story/view?id=" + data.id,
                    data.name,
                    false
                )
                .attr("target", "_blank")
                .appendTo(div);
                return div;
            }

            if(utils.e(listName,  Group.ISSUE_LIST)){

                let div = h.div("name_content");
                div.addIf(_.notNull(data.icon), () => getDefaultIconPath(data.icon).wh(32).click((e) => {
                  
                  let path = Group.buildImgPath(e);
                    
                    utils.showFullImage2(path, e.icons)
                }))
                h.a(
                    Environment.self + "/pages/issue/view?id=" + data.id,
                    data.name,
                    false
                )
                    .attr("target", "_blank")
                    .appendTo(div);
                    
                Issue.showDescription(data, header).appendTo(div);
                return div;
            }

        }  

        if(utils.e(header.field, "description")){
      
          return h.div('desc-wrapper').text(data.description, false).eachOf((el) => {
            new TextWithNotice(el.textContent).buildTextDivH(h.from(el))
          })
        }


        function getDefaultIconPath(iconPath){

            if(!_.isEmpty(iconPath)){
              return h.img(iconPath, Environment.defaultIconSize)
            } else return h.img("null.svg")
          }
    }

    static buildImgPath(e){

      if(!_.isEmpty(h.from(e).getA("have-full-path"))) {
        return _.getFullImgPath(e.src);
      } return e.src;
      
    }

    static drawGroup(group = null) {

        if (group == null) {
            group = {
                'name': cache.get(this.GROUP_SELECTED_NAME),
                'id': cache.get(this.GROUP_SELECTED),
                'icon': cache.get(this.GROUP_SELECTED_ICON),
            }
        }
        return h.div("group_layout").attr("data-id", group.id)
            .addIf(_.notNull(group.icon), () => {
                return h.divImg(group.icon, Environment.defaultIconSize).wh(16)
            })
            .add(h.span("group_name").text(group.name, false).click(() => {
                Group.selectGroup(group);
                dom.toast(MagicPage.translate("pages.group.selected") + group.name)
            }));
            //maby it's necessary 
            // .add(h.divImg("select.svg").wh(16).click((e) => {
            //     document.location.href = Environment.self + "/pages/group/view/?id=" + group.id;
            // }))
    }

    static selectGroupListener(event) {

        if (_.e(event.type, MagicRemoteChooser.EVENT_SELECTOR_OPENED)) {
            if (_.e(event.field, Group.GROUP_FIELD)) {

                let itemsHasValue = _.find(event.form.getFields(), (field) => {
                    if (_.notNull(field.read()) && !_.e(field.read(), 0) && Group.CLEANED_FIELDS.includes(field.getField())) {
                        return field;
                    }
                });
                if (itemsHasValue == null) {
                    return
                }

                let searchForm = event.additional;
                searchForm.hide();
                let opts = new MagicPromptOptions("global.prompt.change_group_title", "global.prompt.change_group_text");
                opts.applyClick(MagicPromptButton.OK_LABEL, () => {
                    opts.closeSelf();
                    searchForm.show();
                    opts.markNoRepeat()
                }).setIsAction(MagicPromptButton.OK_LABEL, true)
                    .applyClick(MagicPromptButton.CANCEL_LABEL, () => opts.closeSelf()).setIsAction(MagicPromptButton.CANCEL_LABEL, false)
                    .allowNoRepeat("global.prompt_no_repeat").newPrompt();
            }


        }

        if (_.e(event.type, MagicRemoteChooser.EVENT_ITEM_SELECTED) && _.e(event.field, Group.GROUP_FIELD)) {
            let group = event.additional;
            Group.selectTempGroupValue(group.id, group.name, group.icon);
        }

        if (_.e(event.type, MagicRemoteChooser.EVENT_ITEM_CHANGED) && _.e(event.field, Group.GROUP_FIELD)) {
            Group.selectTempGroupValue(event.additional.id, event.additional.name, event.additional.icon)

            let eventForm = event.form;

            _.each(eventForm.getFields(), (field) => {
                if (Group.CLEANED_FIELDS.includes(field.getField())) {
                    field.setValue(null)
                }
            })
        }

    }

    static getSelectedGroup () {
      return cache.get(Group.GROUP_SELECTED)
    }

    static preselectingGroupListener(event) {

        if (_.e(event.type, MagicFormEvent.FIELD_GENERATED) && _.e(event.field, Group.GROUP_FIELD)) {
            let data = event.additional.val;

            if (_.notNull(data)) {
                return;
            }

            let val = cache.toObject("group").set("id", Group.GROUP_SELECTED).set("key", Group.GROUP_SELECTED)
                .set("value", Group.GROUP_SELECTED_NAME).set("additional", this.GROUP_SELECTED_ICON).get();

            event.additional.field.setValue(val);
            event.additional.field.setPreselected();
        }
        if (_.e(event.type, MagicFormEvent.FIELD_GENERATED) && _.e(event.field, Group.GROUP_ISSUE_FLOW_FIELD)) {
          
            let data = event.additional.val;

            if (_.notNull(data)) {
                return;
            }
  
            Executor.runGet(Environment.dataApi + "/api/v2/flaw/group/flaw/" + cache.get(Group.GROUP_SELECTED), (data) => {
                if(_.isNull(data)){
                    return;
                }
                if (data.name) {
                    data.value = data.name;
                    data.key = data.id;
                }

                event.additional.field.setValue( {"issueFlow" : data});
                event.additional.field.setPreselected();


                event.form.findField("issueType").setValue({"issueType" : data.issueType});
            });

        }
    }

    static toGroup(data) {
        if (_.isNull(data.id)) {

            return {"id": data.key, "icon": data.additional, "name": data.value}
        }

        return data;
    }

    static getById(group, onSuccess) {
        let toReturn;
        Executor.runGet(this.PATH + "id/" + group, (data) => {
        
            _.isNull(onSuccess) ? toReturn = data : onSuccess()
        }, _.notNull(onSuccess));

        return toReturn;
    }
}

function customVerifyPage() {
    Group.withMyGroups((data) => {
        if (_.isEmpty(data.content)) {
            if (Environment.isNotRegisterLoginOrReset()) {
                if (!_.endsWith(document.location.href, Environment.self)) {
                    document.location.href = Environment.self;
                }
            }
        }
    }, false, (e) => {
        if (Environment.isNotRegisterLoginOrReset()) {
            if (!_.endsWith(document.location.href, Environment.self)) {
                document.location.href = Environment.self;
            }
        } else {

        }
    })
}


class StatusesModal{

  static EDIT_PATH =  Environment.dataApi + "/api/v2/flaw/board/edit";

  static STATUSES_TITILE = "global.pages.group.tabs.statuses";

  static CLASS_NAME = "board-tab__";

  #dropToDiv;
  #startElement;
  #data;
  #trigger;
  #board;
  #chooser;

  #wrapper = h.div(ConnectionChooser.CL + 'wrapp').cl('chooser-wrapper');
  #modal = h.div(ConnectionChooser.CL + "modal").cl("remote-chooser").appendTo(this.#wrapper);
  
  #closeBtn =  h.div(ConnectionChooser.CL + "close-btn").pointer().click(() => this.close()).appendTo(this.#modal);
  #title = h.div(ConnectionChooser.CL + 'title').text(StatusesModal.STATUSES_TITILE).appendTo(this.#modal);
  #addBtn = h.div(StatusesModal.CLASS_NAME + "add-btn").text("global.app.list.search.add").appendTo(this.#modal).click(() => this.openChooser());
  #statusesWrapper = h.div(ConnectionChooser.CL + "wrapper").appendTo(this.#modal);

  constructor(trigger ,data){
    
    this.#board = structuredClone(data);
    
    this.#board.flow = data.flow.key;

    this.#board.group = data.group.key;

    this.#data = this.#board.statuses;

    this.#trigger = trigger;

    this.buildChooser();
  }

  buildTrigger(){
    this.#trigger.text(null).add(h.span(StatusesModal.CLASS_NAME + "statuses-span").text(StatusesModal.STATUSES_TITILE))
    .add(h.span(StatusesModal.CLASS_NAME + "status-count").text(" - " +  this.#data.length, false));
  }

  init(){
    
    this.buildTrigger();
  
    this.drawStatuses();

    this.#trigger.pointer().click(() => this.#wrapper.appendToBody().zIndex(5500))
    
  }

  dragEndEvent = (e, el) => {

    e.preventDefault()

    let indexTo = dom.getElementIndex(this.#dropToDiv);

    let indexFrom = dom.getElementIndex(this.#startElement)
  

    this.#board.statuses = _.arrayMove(this.#data, indexFrom, indexTo);

    this.changeOrder(this.#board.statuses);

    Executor.runPutWithPayload(StatusesModal.EDIT_PATH, (() => {
  
      if (_.e(indexTo, indexFrom)){
        return;
      }
  
      if (indexTo > indexFrom){
        el.setData('direction', 'forward');
      }  else {
        el.setData('direction', 'back')
      }

      if (_.e(h.from(el).getData('direction'), 'back')) {

        el.parent().addBefore(el, this.#dropToDiv)
      } else {
        if(this.#dropToDiv.next()){

          el.parent().addBefore(el, this.#dropToDiv.get().nextSibling)
        } else {
          this.#statusesWrapper.add(el)
        }
      }
      
    }), this.#board, (e) =>{});
  }

  changeOrder = (array) => {
    array = array.map((el, i) => {
      el.order = i;

      return el;
    })
  }

  dragOverEvent = (e, el) => {
    e.preventDefault()
    
    this.#dropToDiv = el;
  } 

  close(){
    this.#wrapper.remove()
  }

  drawStatuses () {
    _.each(this.#data, (item, i) => {

      this.getStatusDiv(item.model).appendTo(this.#statusesWrapper);

    });
  }

  removeItem(el){
    let index = dom.getElementIndex(el);

    this.#board.statuses.splice(index, 1);

    this.changeOrder(this.#board.statuses);

    Executor.runPutWithPayload(StatusesModal.EDIT_PATH, (() => {
      el.remove();

      this.buildTrigger();
    }), this.#board, (e) => {
    })
  }


  getStatusDiv = (status) => {
    let statusDiv = h.div(StatusesModal.CLASS_NAME + "_status_span").pointer();

    statusDiv.addIf(status.icon, h.img(status.icon, Environment.defaultIconSize).cl("image_in_details")
    .click((e) => utils.showFullImage(e.src)).wh(16));

    statusDiv.addIf(status.description, h.a("#").cl("object_link").text(status.description, false).appendTo(statusDiv));

    statusDiv.style().background(status.color);
  
    statusDiv.add(h.img('rm.png', Environment.defaultIconSize).click(() => this.removeItem(statusDiv)));

    statusDiv.draggable((e, startElement) => { 

      this.#startElement = startElement;

     }, this.dragEndEvent);

    statusDiv.dragOver(this.dragOverEvent)

    return statusDiv;
  }

  openChooser = () => {
    this.#chooser.showForm();
  }

  getFormFieldListener(){
    return (event) =>{
      if(_e(event.type, MagicRemoteChooser.EVENT_ITEM_SELECTED)){
        this.#board.statuses.push({
          id: null,
          model:  {
            id: event.additional.id,
            name: event.additional.name,
            group: event.additional.group.key,
            description: event.additional.description,
          },
          order: this.#board.statuses.length
        });

        Executor.runPutWithPayload(StatusesModal.EDIT_PATH, (() => {

          this.getStatusDiv(event.additional).appendTo(this.#statusesWrapper);

          this.buildTrigger();

        }),this.#board, (e) => {});
      }
    }
  }

  buildChooser = () => {
    let remoteChooserDiv = h.div('remote_selection');

    let remoteChooserInput = h.input(dom.HIDDEN);

    this.#chooser = new MagicRemoteChooser(remoteChooserDiv, {}, remoteChooserInput, 'dataType', Issue.createHeaderForStatusChooser(), this );
  }
}




