/**
 * Flaw sdk is a small framework to work with flaw
 * You might need:
 * http://dennis.systems/js/magic.*.js
 * http://dennis.systems/js/html.js
 * http://dennis.systems/js/userdata.js
 *
 *    * means all files like this in directory.
 *    directory is safe to explore
 *
 */

class Flow {}

class FlowElement {
  #current;
  #next;
  #prev;
}

class EditFlow {
  #data;
  #editWindow;
  #infoIssueType = h.input("hidden");
  #wrapperEditWindow;
  #list;

  static ISSUE_TYPE = "issue_type";
  static NAME = "name";
  static OBJECT_CHOOSER = "object_chooser";

  constructor(data, action) {
    this.#data = data;
    this.#list = action.parent.parent().getParent();
    this.#infoIssueType.text(this.#data.issueType.key, false);
  }

  getWrapper() {
    return this.#wrapperEditWindow;
  }

  getFormFieldListener() {
    return null
  }

  build() {
    let _this = this;
    this.#wrapperEditWindow = dom.createModal(dom.REMOVE_TYPE_REMOVE).cl("wrapper_edit_flow_window").appendToBody();

    this.#editWindow = 
      h.div("edit_flow_window")
      .appendTo(this.#wrapperEditWindow);

    let divForInput = 
      h.div("change_input_div")
      .add(h.tag("label").text("global.flow.name"))
      .appendTo(this.#editWindow);

    let inpit = 
      h.input("text")
      .text(this.#data.name, false)
      .focus()
      .appendTo(divForInput); 

      this.createChooser(
        this.#data.issueType,
        this.#editWindow
      );

    let cancelBtn = h
      .inputBtn("global.edit.cancel")
      .cl("close_auto_form")
      .click(function () {
        _this.closeWindow();
      })
      .appendTo(this.#editWindow);

    this.saveBtn = h
      .inputBtn("global.edit.save")
      .cl("save_auto_form")
      .click(function () {
        _this.#data.name = inpit.val();
        _this.#data.issueType = utils.toInt(_this.#infoIssueType.val());
        _this.#data.group = utils.toInt(_this.#data.group.key);

        Executor.runPutWithPayload(
          Environment.dataApi + "/api/v2/flaw/issue_flow/edit",
          function () {
            _this.closeWindow();
            _this.#list.drawValues();
          },
          _this.#data
        );
      })
      .appendTo(this.#editWindow);

    let closeEditFlowWindow = dom.createCloseImage()
      .click(function () {
        _this.closeWindow();
      })
      .appendTo(this.#editWindow);
  }

  closeWindow() {
    this.#wrapperEditWindow.hideModal();
  }

  createChooser(data, window) {
    let divForChooser = h.div("choser_wrapper")
      .add(h.tag("label").text("global." + EditFlow.ISSUE_TYPE))
      .appendTo(window);
    let where = h.div("chooser").appendTo(divForChooser);
    let hiddenElement = this.#infoIssueType.appendTo(divForChooser);

    new MagicRemoteChooser(where, data, hiddenElement, "dataType", this.createHeaderForChooser(), this);
  }

  createHeaderForChooser(){
    let header = {
      getData() {
        return {
          searchName: EditFlow.ISSUE_TYPE,
          searchField: EditFlow.NAME,
        };
      },
      getField() {
        return EditFlow.ISSUE_TYPE;
      },
      getType() {
        return EditFlow.OBJECT_CHOOSER;
      },
    };
    return header
  }
}

class StatusRoad {
  static ISSUE_STATUS = "issue_status";
  static NAME = "name";
  static STATUS = "status";
  static OBJECT_CHOOSER = "object_chooser";
  static PREVIUS_STATUS = "prevStatus";
  static CURRENT_STATUS = "currentStatus";
  static NEXT_STATUS = "nexStatus";
  static EVENT_ITEM_SELECTED = "EVENT_ITEM_SELECTED";
  static EVENT_ITEM_DESELECTED = "EVENT_ITEM_DESELECTED";


  #data;
  #stages;
  #statusRoad;
  #statusRoadWindow;
  #divWithStages;
  #wrapperRoadWindow = dom.createModal(dom.REMOVE_TYPE_REMOVE).cl("wrapper_road_status_window").appendToBody();
  #newDataId = 0;
  #list;
  #event;
  #whereError = []

  constructor(data, action) {
    this.#data = data;
    this.#stages = data.stages;
    this.#list = action.parent.parent().getParent();
  }

  getWrapper() {
    return this.#wrapperRoadWindow;
  }

  getFormFieldListener() {
    return this.chooserEvent;
  }


  build() {
    let _this = this;


    this.#divWithStages = h
      .div("div_with_stages") ;

    var wrap = this.#divWithStages;

    this.#statusRoadWindow = h
      .div("road_status_window")
      .add(h.div("title_div").text("global.stages.stage.form.title"))
      .add(
        dom.createCloseImage()
        .click(function () {
        _this.closeWindow();
      }))
      .add(wrap)
      .add(h.a("#", "global.status.add +").cl("add_stage_btn")
          .click(() => {

            var isFirst = false;

            if(!wrap.childNodes().length) {
              isFirst = true;
            }

            _this.createFields(false, isFirst);
          }))
      
      .add( 
        h.div('buttons_box')
        .add( h.inputBtn("global.status.cancel")
        .click(function () {
          _this.closeWindow();
        }))
        .add(
      h.inputBtn("global.status.save")
        .click(() => {
          this.saveStages();
        }))
      )
      .appendTo(this.#wrapperRoadWindow);

    utils.each(this.#data.stages, (stage, i) =>{
      var isFirst = false;

      if(_e(i, 0)) {
        isFirst = true;
      }
      _this.createFields(stage, isFirst);
      }
    );
  }


  chooserEvent(event) {
    let _this = event.form;
    if (_.e(event.type, StatusRoad.EVENT_ITEM_SELECTED)) {
      _this.editStage(event);
    }
    if (_.e(event.type, StatusRoad.EVENT_ITEM_DESELECTED)) {
      _this.#event = event
    }
  }

  editStage(event) {
    let _this = this;
    if (_.notNull(_this.stageId) && _.notNull( _this.fieldInStage)) {
      _this.#stages.filter((element, index) => {
        if (_.e(element.id, _this.stageId)) {
          _this.#stages[index][_this.fieldInStage] = event.additional;
          if(_.e(event.type, StatusRoad.EVENT_ITEM_SELECTED)){
            _this.#stages[index][_this.fieldInStage].group =
            _this.#stages[index][_this.fieldInStage].group.key;
          }
          
        }
      });
    } else {
      log.debug("not choose element");
    }
    _this.stageId = null;
    _this.fieldInStage = null;
  }

  closeWindow() {
    this.#wrapperRoadWindow.hideModal();
    this.#list.drawValues()
  }

  saveStages() { 
    let _this = this;
    
    this.checkNearblyStatus()

    if (_.e(this.#whereError.length, 0)) {
      _this.#stages.map((e) => {
        if (isNaN(e.id)) {
          e.id = 0;
        }
      });
      Executor.runPutWithPayload(
        Environment.dataApi +
          "/api/v2/flaw/issue_flow/update_stages/" +
          _this.#data.id,
        function () {
          _this.closeWindow();
          _this.#list.drawValues();
        },
        _this.#stages
      );
    } else {
      _.each(this.#divWithStages.childNodes(), (e)=>{
        if(this.#whereError.includes(parseInt(h.from(e).getData('stage')))){
          h.from(e).cl('red_bgc')
        }
        if(this.#whereError.includes(h.from(e).getData('stage'))){
          h.from(e).cl('red_bgc')
        }    
      })
    }
  }

  hideError(){
    _.each(this.#divWithStages.childNodes(), (e)=>{
        h.from(e).rcl('red_bgc');
    })
    this.#whereError = [];
  }

  checkNearblyStatus(){
    let _this = this;
    this.#stages.forEach(stage => {
      if(_.isNull(stage.currentStatus)){
        _this.#whereError.push(stage.id);
      }
    })

    this.#stages.forEach(stage => {
      if(!_.isNull(stage.currentStatus) && !_.isNull(stage.nexStatus)){
        if( _.e(stage.currentStatus.id, stage.nexStatus.id)){
              _this.#whereError.push(stage.id);
          }
      }
      if(!_.isNull(stage.currentStatus) && !_.isNull(stage.prevStatus)){
        if( _.e(stage.currentStatus.id, stage.prevStatus.id)){
              _this.#whereError.push(stage.id);
          }
      }
    })
  }

  deleteStage(target) {
    let _this = this
    let delElem = h.from(target).parent().getData('stage');
    this.#stages.forEach((element, index) => {
      _.e(element.id, delElem) && _this.#stages.splice(index, 1);
    });
    h.from(target).parent().remove();
  }

  createStage(currentStatus = null) {
    let obj = {
      id: "my" + this.#newDataId,
      action: null,
      [StatusRoad.CURRENT_STATUS]: currentStatus,
      [StatusRoad.NEXT_STATUS]: null,
      position: null,
      [StatusRoad.PREVIUS_STATUS]: null,
    };
    this.#stages.push(obj);
    this.#newDataId++;
  }

  createFields(savedElement = false, isFirst = false) {
    let mainDiv = h
      .div("main_road_status_fields")
      .appendTo(this.#divWithStages);

    if (savedElement) {
      mainDiv.setData("stage", savedElement.id);
    } else {
 
      mainDiv.setData("stage", "my" + this.#newDataId);
 
    }

    let prevStatus = h.div("road_status_field").setData(StatusRoad.STATUS, StatusRoad.PREVIUS_STATUS).appendTo(mainDiv);
    let currentStatus = h.div("road_status_field").setData(StatusRoad.STATUS, StatusRoad.CURRENT_STATUS).appendTo(mainDiv);
    let nextStatus = h.div("road_status_field").setData(StatusRoad.STATUS, StatusRoad.NEXT_STATUS).appendTo(mainDiv);
    
    h.img("rm.png")
      .cl('close_img')
      .click((e, event) => {
        this.deleteStage(event.target);
        this.hideError()
      })
      .appendTo(mainDiv);

    if (savedElement) {
       if(!isFirst) {
        this.buildChooser(prevStatus, savedElement.prevStatus);
      } else {
        prevStatus.cl("chooser")
      }
      this.buildChooser(currentStatus, savedElement.currentStatus);
      this.buildChooser(nextStatus, savedElement.nexStatus);
    } else {
      if(!isFirst) {
        this.buildNewChoosers(prevStatus, currentStatus, nextStatus);  
      } else {
        this.buildNewChoosers(null, currentStatus, nextStatus);
        prevStatus.cl("chooser")
      }
    }
  }


  buildNewChoosers(prevStatus, currentStatus, nextStatus){
    let previosStatus = this.getPreviousStatus()
    
    if(prevStatus) this.buildChooser(prevStatus);
    this.buildChooser(currentStatus, previosStatus);
    this.buildChooser(nextStatus);
    this.createStage(previosStatus);
  }

  getPreviousStatus(){
    if( _.e(this.#stages.length, 0)){
      return null
    }
      return this.#stages[this.#stages.length - 1].nexStatus
  }

  buildChooser(divForChooser, data = false) {
    let _this = this;
    let hiddenElement = h.input("hidden").get();
    divForChooser.click((e, ev) => {
      this.stageId = h.from(e.parentElement).getData("stage");
      this.fieldInStage = h.from(e).getData(StatusRoad.STATUS);
      this.hideError()
      if(_.notNull(_this.#event)){
        _this.editStage(_this.#event);
        _this.#event = null
      }
    });
    let where = h.div("chooser").appendTo(divForChooser);
    if (!_.isFalse(data)) {
      where.data_id(data.id);
    }

    let dataForChooser = this.changeObjForChooser(data);
    new MagicRemoteChooser(
      where,
      dataForChooser,
      hiddenElement,
      "dataType",
      this.buildHeaderforChooser(),
      this
    );
  }

  buildHeaderforChooser() {
    let header = {
      getData() {
        return {
          searchName: StatusRoad.ISSUE_STATUS,
          searchField: StatusRoad.NAME,
        };
      },
      getField() {
        return StatusRoad.STATUS;
      },
      getType() {
        return StatusRoad.OBJECT_CHOOSER;
      },
    };
    return header;
  }



  changeObjForChooser(data) {
    //make object for chooser
    let newData = {
      key: 0,
      value: null,
      additional: {
        icon: null,
        color: null,
      },
    };
    if (_.notNull(data)) {
      newData.key = data.id;
      newData.value = data.name;
      newData.additional.icon = data.icon;
      newData.additional.color = data.color;
    } else {
      newData.additional = null;
    }

    return newData;
  }
}
