class ConnectionView{
  static GROUP_CLASS = "group-node-icon";
  static PROJECT_CLASS = "project-node-icon";
  static STORY_CLASS = "story-node-icon";
  static EPIC_CLASS = "epic-node-icon";
  static PARENT_CLASS = "parent-node-icon";
  static SPRINT_CLASS = "sprint-node-icon";
  static FLOW_CLASS = "flow-node-icon";
  static ISSUE_CLASS = "issue-node-icon";

  static TREE_CLASS = "connection-tree";

  static CONNECTION_TYPES = {
    group: ConnectionView.GROUP_CLASS,
    project: ConnectionView.PROJECT_CLASS,
    story: ConnectionView.STORY_CLASS,
    epic: ConnectionView.EPIC_CLASS,
    sprint: ConnectionView.SPRINT_CLASS,
    flow: ConnectionView.FLOW_CLASS,
    parent: ConnectionView.PARENT_CLASS,
    issue: ConnectionView.ISSUE_CLASS,
  }

  #path = [];
  #state = [];
  #canRedirect
  #containerH = h.div("connection-with");
  #header = h.div("connection-with_header");
  #tree = h.div("connection-tree");

  #treeWrapper = h.div("connection-tree-nodes");

  constructor(data, canRedirect = false) {

    this.#path = data.path;

    this.#canRedirect = canRedirect;
    this.buildState();

    this.buildHeader();

    this.builTree();
  }

  buildHeader(){
    this.#header.add(h.div("select-connection-icon"))
    .add(h.div("select-connection-title").text("issuecontroller.issueform.connection"))
  }

  builTree(){

    this.#tree.add(h.div("connection-line-angle-icon")).add(this.#treeWrapper)

    this.transformState();

    this.putSplitter();
  }

  transformState() {
    this.#state = this.#state.map((item) => {
      

      let node = h.div("connection-tree-node");

      node.add(h.div("connection-tree-node_icon").cl(item.className));

      let type = item.className.split("-")[0];

      let text = item.value.name
        ? item.value.name
        : type + " #" + item.value.id;

      node.add(h.div("connection-tree-node_text").text(text, false));

      if( _.isTrue(this.#canRedirect)){
        node.click(()=>{
          this.redirect(item)
        })
      }

      return node;
    });
  }

  redirect(item){
    let path = "/pages/" + item.type + "/view?id=" + item.value.id
    dom.redirect(path);
  }


  putSplitter() {
    let arr = [];

    utils.each(this.#state, (el, i) => {
      let splitter = h.div("connection-line-icon");

      if (this.#state[i - 1]) {
        arr.push(splitter);
      }

      arr.push(el);
    });

    this.#state = arr;
  }

  buildState(){
    if(this.#path && this.#path.length){
      this.#state = this.#path.map(el => {



        return {
          type:el.type,
          className: ConnectionView.CONNECTION_TYPES[el.type],
          value: el.value
        }
      })
    }
  }

  getContainer(){

    if(this.#state && this.#state.length){
      utils.each(this.#state, (el) => {
        this.#treeWrapper.add(el)
      })
    } else return this.#containerH;

    return this.#containerH.add(this.#header).add(this.#tree);
  }

}

class ConnectionChooser extends FieldResolver{

  static tabs = ["project", "story", "epic", "issue"];

  static CL = 'connection__';

  static CONNECTION_TRANSLATE = "pages.flaw.issue.field.connect_with";
  #tabs;
  #list;
  #textDivH;
  #listState = {};
  #header;

  #prevFieldsState = [];

  constructor(field) {
    super(field);
  }

  create() {

    this.row =  h.div("row").cl(ConnectionChooser.CL + "row");
    this.showDescription(this.row)
    this.#textDivH = h.div(ConnectionChooser.CL + 'field').pointer().text(ConnectionChooser.CONNECTION_TRANSLATE).appendTo(this.row).click(() => this.init())
    this.showLabel(this.row);

    return this.row;
  }

  init(){
    let options = new MagicTabOptions().setPinable(true, 'conntection_pined_tab');

    this.#tabs = new MagicTab(options);
    this.draw();
    
    this.drawTabs();

    this.drawFooter();
  }

  setValue(val){

    if(_.isNull(val)){

      if(cache.get(Group.GROUP_SELECTED)){
        Executor.runGet(Environment.dataApi + "/api/v2/flaw/group/root/fetch/details/" + cache.get(Group.GROUP_SELECTED), (group) => {
          
          let conectedGroup = {
            path: [{
              type: "group",
              value: group.data
            }]
          }

          let view = new ConnectionView(conectedGroup);

          this.drawConnectionTree(view.getContainer());

        })
      } else {
        this.#textDivH.text(ConnectionChooser.CONNECTION_TRANSLATE)
      }

    } else {

      let dataType = this.getParent().getOptions().getParent()?.getOptions().getDataType();

      if(utils.isNull(dataType)) dataType = "issue";

      this.getConnections(dataType, val.id, (data) => {

        if(data && data.path && data.path.length){
          let arrOfTypes = data.path.map((el) => el.type);

          utils.each(this.getParent().getFields(), field => {

            utils.each(arrOfTypes, (type) => {
              if(_e(field.getField(), type)){
                this.#prevFieldsState.push(field)
              }
            })
          });

          let view = new ConnectionView(data);

          this.drawConnectionTree(view.getContainer());
        }
      })
    }
  }

  close(){
    this.wrapper.text(null);
    this.tabs = null;
    this.wrapper.remove();
  }

  drawTabs(){
    this.#tabs.addTab('pages.project.title', this.tabInner('project'))
    .addTab('pages.story.title', this.tabInner('story'))
    .addTab('pages.epic.title', this.tabInner('epic'))
    .addTab('pages.issue.title', this.tabInner('issue'))
    .deployTo(this.modal);
  }


  tabInner(type){
    let content = h.div(ConnectionChooser.CL + 'tabs-inner');
    this.drawTable(type, content)

    return content;
  }

  drawTable(type, content){
    let payload = new MagicRequest();

    Executor.runPostWithPayload(Environment.dataApi + "/api/v2/flaw/" + type + "/root/fetch/data", (data) => {

      if(data && data.content && data.content.length){
        let options = new MagicListOptions("flaw/" + type, null, null).setTableListener(this.tableListener);
        options.setAvailableFields(["id", "name", "icon" , "status"])

        options.setMultiSelect(false)
        
        this.#list = new MagicList2("flaw/" + type, options);
  
        this.#list.load(content);
  
        this.#listState[type] = {
          list: this.#list,
          type: type,
          data: data
        }
      } else{

        content.text("global.no_data")
      }

    }, payload);
  }

  tableListener = (event) =>{
    if(_e(event.eventType, MagicTable.SELECTED_ROW_CLASS)) {
     
      let selectedTab = this.#tabs.getSelectedTab();

      let type = ConnectionChooser.tabs[selectedTab.index]

      this.getConnections(type, event.data, (data) => {
        this.connectionView.text(null).add(new ConnectionView(data).getContainer())
      })
    }
  }

  draw(){
    this.wrapper = h.div(ConnectionChooser.CL + 'wrapp').cl('chooser-wrapper').appendToBody();
    this.modal = h.div(ConnectionChooser.CL + "modal").cl("remote-chooser").appendTo(this.wrapper);

    this.#header = h.div(ConnectionChooser.CL + "header").appendTo(this.modal);

    h.div(ConnectionChooser.CL + "close-btn").pointer().click(() => this.close()).appendTo(this.modal);

    this.connectionView = h.div(ConnectionChooser.CL + "modal-view").appendTo(this.#header);
  }

  drawFooter(){
    h.div(ConnectionChooser.CL + 'btn-row').appendTo(this.modal)
    .add(h.div(ConnectionChooser.CL + 'btn').cl('close_auto_form').text('global.messages.cancel').click(() => this.close()))
    .add(h.div(ConnectionChooser.CL + 'btn').cl('save_auto_form').text('subscriptionpage.submit').click(() => this.apply()))
  }

  drawConnectionTree(divH){
    this.getField().getFieldObject().eachOfClass("connection__field", (el) => {
      h.from(el).text(null).add(divH)
    })
  }

  setConnectionsInForm(data){

    let fields = this.getParent().getFields();

    this.#prevFieldsState = [];

    utils.each(data.path,(el) => {
    
      let field = fields.filter((field) => {
        return _e(field.getField(), el.type)
      })[0];

      let dataForChooser = el.value;

      dataForChooser.value = el.value.name ? el.value.name : el.value.id;

      field.setValue({
        [field.getField()]: dataForChooser
      })

      this.#prevFieldsState.push(field);
    })
  }

  clearPrevFields(){
    if(this.#prevFieldsState.length){
      utils.each(this.#prevFieldsState, (field) => {
        field.setValue(null);
      })
    }
  }

  apply(){

    let selectedTab = this.#tabs.getSelectedTab();

    let type = ConnectionChooser.tabs[selectedTab.index]

    let currentList = this.#listState[type].list;

    let selected = currentList.getTableObject().getSelectedIds()[0];

    if(selected){

      this.getConnections(type, selected, (data) => {

        Executor.runGet(Environment.dataApi + "/api/v2/flaw/" + type + "/root/fetch/details/" + selected, (val) => {

          let dataWidthParent = data;

          dataWidthParent.path.push({
            type: _e(type, "issue") ? "parent" : type,
            value: val.data
          })

          let view = new ConnectionView(dataWidthParent);
        
          this.clearPrevFields();
    
          this.setConnectionsInForm(dataWidthParent);
    
          this.drawConnectionTree(view.getContainer());
    
          this.close();
        })
      
      })
    } else {
      this.close();
    }
  }

  getConnections(type, id, callback){
    let fullType = "/" + type;

    if(_e(type, "issue") || _e(type, "flaw/issue")){
      fullType = "";
    }

    Executor.runGet(Environment.dataApi + "/api/v2/flaw/issue/path/" + id + fullType, (data) => {

      if(utils.notNull(callback)){
        callback(data)
      } 
    })
  }
}