/**
 * 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 Issue {
    static ISSUE_PARAM = "id";

    static getFromPage(callBack) {
        let issueNumber = MagicPage.getPageParam(Issue.ISSUE_PARAM);
        let path = Environment.dataApi + "/api/v2/flaw/issue/byId/" + issueNumber;
        Executor.runGet(path, callBack);
    }

    static getLinkedIssues(callBack) {
        let issueNumber = MagicPage.getPageParam(Issue.ISSUE_PARAM);
        let path =
            Environment.dataApi +
            "/api/v2/flaw/issue_to_issue_link/by_parent/" +
            issueNumber;
        Executor.runGet(path, callBack);
    }

    static getLinkedIssuesWithId(callBack, id) {
        let path =
            Environment.dataApi + "/api/v2/flaw/issue_to_issue_link/by_parent/" + id;
        Executor.runGet(path, callBack);
    }

    static getStatus(callBack, id) {
        let path =
            Environment.dataApi + "/api/v1/search/type/toString/issue_status/" + id;
        Executor.runGet(path, callBack, true, Executor.HEADERS_PLAIN);
    }

    static deleteLinkedIssues(id, callBack) {
        let path =
            Environment.dataApi +
            "/api/v2/flaw/issue_to_issue_link" +
            "/delete/" +
            id;
        let method = "DELETE";
        Executor.run(path, method, callBack);
    }

    static showDescription(data, header) {

        return h.divImg("description_issue.png").wh(24).click(() => {
            h.magicView(data.id, 'flaw/issue', false, "IssueForm")
        });
    }

    static showCloseWindow(ids, currentStatus, list){
        let remoteChooserDiv = h.div('remote_selection')
        let remoteChooserInput = h.input(dom.HIDDEN).text(currentStatus,false)
        let textArea  = h.textArea(null)
        let modal = h.div("modal")
        .add(h.div('title').text("global.page.issue.menu_close.form.title"))
        .add(h.div('status').add(h.span('status_label', 'global.page.issue.menu_close.form.status_text', true)).add(remoteChooserDiv))
        .add(h.div('comment').add(h.span('status_comment', 'global.page.issue.menu_close.form.comment', true )).add(textArea))
        .add(h.div('actions').add(h.input('button').text('global.page.issue.menu_close.form.close.issue').cl('apply').click(()=>{

            _.each(ids, id =>{
                Issue.sendCloseIssueRequest(id, remoteChooserInput.val(), textArea.val(), list);
            })

        })))
        let form = h.div("modal_prompt").add(modal).appendToBody();


        modal.add(dom.createCloseImage().click(()=>{form.remove()}))


        let chooser = new MagicRemoteChooser(remoteChooserDiv, {}, remoteChooserInput, 'dataType', Issue.createHeaderForStatusChooser() );
        if (currentStatus != null){
            chooser.getDataById(currentStatus, 'issue_status' )
        }
    }

    static  createHeaderForStatusChooser(){
        let header = {
            getData() {
                return {
                    searchName: 'issue_status',
                    searchField: 'name',
                };
            },
            getField() {
                return 'status';
            },
            getType() {
                return EditFlow.OBJECT_CHOOSER;
            },
        };
        return header
    }

    static saveIssueToast(event) {
      var isEdit = !!event.form.getId();
      var issueTextClass = "issue-toast__text";
      var path = Environment.self + "pages/issue/view/?id=";
      var className = "issue-created__toast";
      var created = MagicPage.translate("issuecontroller.issueform.created").toLowerCase();

      if(isEdit) created = MagicPage.translate("issuecontroller.issueform.changed").toLowerCase();

      if(_e(event.additional.type, ToastType.SUCCESS)) {
        var data= event.additional.data;
  
        if(data){
          var toast = h.div(className + "-content");
          toast.add(h.span(issueTextClass).text("pages.issue.title"));
          toast.add(h.a(path + data.id," " + data.id + " ", false, true));
          toast.add(h.span(issueTextClass).text(created, false));

          dom.customToast(3, toast, className + " " + ToastType.SUCCESS)
        }
      }
    }

    static deleteIssueToast(event){
      var issueTextClass = "issue-toast__text";
      var className = "issue-deleted__toast";
      var deleted = MagicPage.translate("issuehistorycontroller.action.deleted").toLowerCase();
      
      var toast = h.div(className + "-content");
      toast.add(h.span(issueTextClass).text("pages.issue.title"));
      toast.add(h.span("removed__issue").text(" " + event.data + " ", false).setA("href", null));
      toast.add(h.span(issueTextClass).text(deleted, false));
      dom.customToast(3, toast, className + " " + ToastType.SUCCESS)
      
    }

    static contextMenuToGroupTransformer = (action) => {
      return action.name.split("_")[0];
    }


    static sendCloseIssueRequest(id, status, comment, list){
        let path =
            Environment.dataApi + "/api/v2/flaw/issue/close/";

        let payLoad = {
            'id' : id,
            'status':  status,
            'comment' : comment,
            'removePerformer' : false
        }
        Executor.runPostWithPayload(path, ()=> {
          dom.successMessage();
          list.drawValues();
        
        },payLoad  )
    }

    static promote(id = null, callBack) {
        let issueNumber = id == null ? MagicPage.getPageParam(Issue.ISSUE_PARAM) : id;
        let path = Environment.dataApi + "/api/v2/flaw/issue/promote/" + issueNumber;
        Executor.runPost(path, callBack);
    }

    static demote(id = null, callBack) {
        let issueNumber = id == null ? MagicPage.getPageParam(Issue.ISSUE_PARAM) : id;
        let path = Environment.dataApi + "/api/v2/flaw/issue/demote/" + issueNumber;
        Executor.runPost(path, callBack);
    }

    static showNotification(callBack) {
        let path = Environment.dataApi + "/api/v2/flaw/user_notification/my";
        Executor.runGet(path, callBack);
    }

    static deleteNotification(callBack, id) {
        let path =
            Environment.dataApi +
            `/api/v2/flaw/user_notification/${id}/read?isRead=true`;
        Executor.runPost(path, callBack);
    }

    static changeStatus(callBack, elementId, payload) {
        let path =
            Environment.dataApi + `/api/v2/flaw/issue/edit_field/id/${elementId}`;
        Executor.runPutWithPayload(path, callBack, payload);
    }

    static changeFormField(event){
     
        Group.preselectingGroupListener(event);

        if (_.e(event.type, SearchEvent.SEARCH_CREATED)) {
            let div = h.div('closed_items_container').appendTo(event.additional[1]);


            let options = new MagicTrueFalseSelectorOptions(MagicPage.translate("global.pages.issue.issue_closed"),
                false, true, true, true,
                MagicTrueFalseSelectorOptions.SELECTED_SWITCH_BOX_IMAGE,
                MagicTrueFalseSelectorOptions.DESELECTED_SWITCH_IMAGE )
            let selector = new MagicTrueFalseSelector(options).draw(div);

            //
            // dom.chk('issue_closed_add', MagicPage.translate("global.pages.issue.issue_closed"), true, div).change(() => {
            //     event.form?.drawValues()
            // }).cl('checkbox_closed');
        }

        if (_e(event.type, MagicFormEvent.FORM_TABS_GENERATED ) ){
                event.additional.fieldTab.hideFromSelection('pages.issue.forms.groups.connection')
        }

        if(_e(event.type, MagicFormEvent.FORM_TOAST_REQUESTED)) {

          if(!_e(event.additional.type, ToastType.ERROR)) {
            Issue.saveIssueToast(event);

            return false;
          }
        
      }
    }
}


class IssueToIssue {

  static actionArray = [{ name: 'delete', allowOnMultiSelect: false }, { name: 'edit', allowOnMultiSelect: false },]

  static payload = {
		"id": 0,
		"linkType": 0,
		"parent": 0,
		"linked": 0,
		"action": 0
	}

  static CLASS = "issue-to-issue__"
	static SEARCH_PATH = "/api/v2/flaw/issue_to_issue_link/";

  #issueContainer = h.div(IssueToIssue.CLASS  + 'container');

  #addBtn = h.div(IssueToIssue.CLASS + "add").text("pages.issue.create").click(() => this.loadForm());

  #changeRow;
  #parentIssue;

  #id;
  #where;

	constructor(where, id = MagicPage.getPageParam(Issue.ISSUE_PARAM)) {
		this.#where = where;
		this.#id = id;
	}

	init() {

    this.getParentIssue();

    this.draw();
		
		return this;
	}

  getParentIssue(){
        if (_e(this.#id, 0)){
            return;
        }
    Executor.runGet(Environment.dataApi + "/api/v2/flaw/issue/root/fetch/details/" + this.#id, (data) => {
      this.#parentIssue = data.data;
    })
  }

  presetParentIssue(form) {
      _.each(form.getFields(), (field) => {
        if(_e(field.getField(), "parent")) {

          let value= {
            id: 0,
            linkType: 0,
            parent: {
                key: this.#parentIssue.id,
                value:  this.#parentIssue.name,
                additional:  this.#parentIssue.icon,
            },
            linked: 0,
            action: null
          }

          field.setValue(value);
        }
      })
  }

  formListener = (event) => {
    if(_e(event.type, MagicFormEvent.FORM_SHOW)){

      this.presetParentIssue(event.form)
    }

    if(_e(event.type, MagicFormEvent.FORM_SAVED)){
      if(event.form.getId()){
        if(event.additional){
          this.redrawChangedRow(event.additional.id);
        }
      } else {
        this.addLinkedIssue(event.additional.id)
      }
    }
  }

  redrawChangedRow(id){
        if (_e(id, 0)) {return}
    Executor.runGet(Environment.dataApi + IssueToIssue.SEARCH_PATH + 'root/fetch/details/' + id, (data) => {
      let row = this.createRow(data.data);
      
      this.#issueContainer.addBefore(row, this.#changeRow);
      this.#changeRow.remove()
    })
  }

	draw() {
    this.#where.text(null);
    
    this.#addBtn.pointer().appendTo(this.#where)
    this.#issueContainer.appendTo(this.#where);

		Issue.getLinkedIssuesWithId((dataArr) => {

      if(dataArr.length){

        _.each(dataArr, item => {

          this.createRow(item).appendTo(this.#issueContainer);
        })
      }

		}, this.#id);
	}

  createRow(linkItem){
    let row = h.div(IssueToIssue.CLASS + "row").setData("id", linkItem.id);

    h.div(IssueToIssue.CLASS + "issue").cl(IssueToIssue.CLASS + "parent").appendTo(row)
      .addIf(linkItem.parent.additional, h.img(linkItem.parent.additional, Environment.defaultIconSize) )
      .add(h.span(IssueToIssue.CLASS + "issue-name").text(linkItem.parent.value, false));

    let linkType = h.div(IssueToIssue.CLASS + "type").appendTo(row)

    if(linkItem.linkType.additional){
      linkType.add(h.img(linkItem.linkType.additional, Environment.defaultIconSize));
    }

    linkType.add(h.span(IssueToIssue.CLASS + "link-type-name").text(linkItem.linkType.value, false));
    
    h.div(IssueToIssue.CLASS + "issue").cl(IssueToIssue.CLASS + "linked").appendTo(row)
      .addIf(linkItem.linked.additional, h.img(linkItem.linked.additional, Environment.defaultIconSize) )
      .add(h.span(IssueToIssue.CLASS + "issue-name").text(linkItem.linked.value, false));

    let options = new MagicMenuOptions(row, '', this, IssueToIssue.CLASS + "row").setActions(IssueToIssue.actionArray);

    options.setListner(this.menuListener);

    new MagicMenu(options, row);

    return row;
  }

	menuListener = (event) => {

		if(_e(event.eventType, "delete")){
      this.deleteIssueLink(event.data.getData("id"), event.data)
    }

    if(_e(event.eventType, "edit")){
      this.#changeRow = event.data;

      this.loadForm(Number(event.data.getData("id")))
    }
	}

  loadForm(id = null){
    let path = "flaw/issue_to_issue_link";

    let magicFormOptions = new MagicFormOptions(path);

    magicFormOptions.setFormListener(this.formListener);

    MagicForm.Instance(path, magicFormOptions).load(id)

  }


  deleteIssueLink(id, row){
    Issue.deleteLinkedIssues(id, (data) => {

      row.remove();
    })
  }

	addLinkedIssue(id) {
    Executor.runGet(Environment.dataApi + IssueToIssue.SEARCH_PATH + 'root/fetch/details/' + id, (data) => {
      this.createRow(data.data).appendTo(this.#issueContainer);
    })
	};
}