//Tabulator용 공통함수
const tb_common_funtions = {
  //토글버튼 출력
  formatterToggleboxIcon: function (tgt, params) {
    let cell = tgt._cell;
    let span = document.createElement("span");

    if ( params.checkval && cell.value == params.checkval || !params.checkval && cell.value == true) {
      span.className = "bi bi-toggle-on tb_toggle";
    } else {
      span.className = "bi bi-toggle-off tb_toggle";
    }
    return span;
  },

  //토글버튼 출력 red
  formatterToggleboxRedIcon: function (tgt, params) {
    let cell = tgt._cell;
    let span = document.createElement("span");

    if ( params.checkval && cell.value == params.checkval || !params.checkval && cell.value == true) {
      span.className = "bi bi-toggle-on tb_toggle red";
    } else {
      span.className = "bi bi-toggle-off tb_toggle red";
    }
    return span;
  },

  //토글버튼 출력 green
  formatterToggleboxGreenIcon: function (tgt, params) {
    let cell = tgt._cell;
    let span = document.createElement("span");

    if ( params.checkval && cell.value == params.checkval || !params.checkval && cell.value == true) {
      span.className = "bi bi-toggle-on tb_toggle green";
    } else {
      span.className = "bi bi-toggle-off tb_toggle green";
    }
    return span;
  },

  //토글버튼 TEXT Icon
  formatterToggleboxText: function (tgt, params) {
    let cell = tgt._cell;
    let label = document.createElement("label");
    let span = document.createElement("span");
    let span2 = document.createElement("span");
    span2.classList.add("switch");

    label.classList.add("toggle-switchy");
    label.setAttribute("data-size", params.size||"xs");//크기
    label.setAttribute("data-style", params.shape||"rounded");//모양

    if ( params.checkval && cell.value === params.checkval || !params.checkval && cell.value === true) {
      span.classList.add('checked');
    } else {
      span.classList.add('notchecked');
    }
    span.classList.add('toggle');
    span.setAttribute('on',params.onval||'ON');
    span.setAttribute('off',params.offval||'OFF');
    span.appendChild(span2);
    label.appendChild(span);
    return label;
  },

  //Selected Circle 출력
  formatterSelCircleIcon: function (tgt, params) {
    let cell = tgt._cell;
    let em = document.createElement("i");

    if (cell.value == "Y") {
      em.className = "bi bi-circle-fill fa-2xs";
    } else {
      em.className = "";
    }
    return em;
  },



  //국가명  출력
  formatterNations: function (tgt, params) {
    let cell = tgt._cell;
    let nval = Object.keys(varsNations).filter(key => key === cell.value );
    return varsNations[nval[0]];
  },
  //통화 출력
  formatterCurrency: function (tgt, params) {
    let cell = tgt._cell;
    let nval = Object.keys(varsCurrency).filter(key => key === cell.value );
    return varsCurrency[nval[0]];
  },

  //Number / 통화. 출력
  formatterNumber: function (tgt, params) {
    if(!tgt.getValue()) return;

    let val = tgt.getValue();
    let config = {symbol:params?.symbol||'',precision:params?.precision||0,};
    if( params?.group) config.group = params.group;
    if( params?.pattern) config.pattern = params.pattern;
    if( params?.decimal) config.decimal = params.decimal;
    if( params?.separator) config.separator = params.separator;
    if( params?.negativePattern) config.negativePattern = params.negativePattern;
    let nval = currency(Number(val), config);

    return nval.format();
  },

  //체크버튼 출력 true/false
  formatterCheckboxIcon: function (tgt, params) {
    let cell = tgt._cell;
    let label = document.createElement("label");
    let input = document.createElement("input");
    input.type = "checkbox";
    input.className = "tb_checkbox";
    if( cell.value ){
      input.checked = true;
    }
    label.append(input);
    return label;
  },

  //체크버튼 출력 Y/N
  formatterCheckboxIconYn: function (tgt, params) {
    let cell = tgt._cell;
    let label = document.createElement("label");
    let input = document.createElement("input");
    input.type = "checkbox";
    input.className = "tb_checkbox";
    if( cell.value === 'Y' ){
      input.checked = true;
    }
    label.append(input);
    return label;
  },

  //체크버튼 조회용 출력
  formatterCheckboxViewIcon: function (tgt, params) {
    let cell = tgt._cell;
    let label = document.createElement("label");
    if( cell.value ){
      let input = document.createElement("input");
      input.addEventListener("click",function(e){ e.stopPropagation(); e.preventDefault(); });
      input.type = "checkbox";
      input.className = "tb_checkbox";
      input.checked = true;
      label.append(input);
    } //else { input.checked = false; label.append(input); }
    return label;
  },

  //체크버튼 조회용 출력
  formatterCheckboxViewIcon2: function (tgt, params) {
    let cell = tgt._cell;
    let label = document.createElement("label");
    let input = document.createElement("input");
    input.addEventListener("click",function(e){ e.stopPropagation(); e.preventDefault(); });
    input.type = "checkbox";
    input.className = "tb_checkbox";
    label.append(input);
    if( cell.value ){
      input.checked = true;
    } else {
      input.checked = false;
    }
    return label;
  },

  //Check or Not 조회아이콘 출력
  formatterCheckIcon: function (tgt, params) {
    let cell = tgt._cell;
    let span = document.createElement("span");
    if( cell.value ){
      span.className = "bi bi-check-circle-fill tb_icon";
    }
    return span;
  },

  //Check or Not 조회아이콘 출력2
  formatterCheckIcon2: function (tgt, params) {
    let cell = tgt._cell;
    let span = document.createElement("span");
    if( cell.value == params.checkval ){
      span.className = "bi bi-check-circle-fill";
    }else{
      span.className = "bi bi-circle text-black-50";
    }
    return span;
  },

  //O or X 조회아이콘 출력
  formatterToggleIcon: function (tgt, params) {
    var cell = tgt._cell;
    let span = document.createElement("span");
    if( cell.value ){
      span.className = "bi bi-toggle-on tb_toggle";
    }else{
      span.className = "bi bi-toggle-off tb_toggle";
    }
    return span;
  },

  formatterSelect: function (tgt, formatterParams) {
    var cell = tgt._cell;
    let div = document.createElement("div");
    if(formatterParams.class) div.className = formatterParams.class;
    let nval = cell.value || formatterParams.default;
    div.innerHTML = formatterParams.values[nval] || (formatterParams.defaultValue || '');
    return div;
  },

  formatterButton: function (tgt, params) {
    var cell = tgt._cell;
    let btn = document.createElement("a");
    btn.className = params.btnClass;
    btn.innerHTML = params.btnTitle;
    if( params.event &&  params.cfunc ){
      if( !Array.isArray(params.event) ) params.event = Array(params.event);
      params.event.forEach( evt => btn.addEventListener(evt, ()=>{params.cfunc(cell);}));
    }
    return btn;
  },

  //Json formatter
  formatterJson: function( tgt, params ){
    var cell = tgt._cell;
    return params.values[cell.value];
  },

  //multicheckbox or radio formatter
  formatterMultiCheckBox: function( tgt, params ){
    var cell = tgt._cell;
    let div = document.createElement("form");
    if(params.class) div.className = params.class;
    params.inputs.forEach( ipt => {
      let label = document.createElement("label");
      label.className = ipt.class;
      let nipt = document.createElement("input");
      nipt.type = params.type||'checkbox';
      nipt.value = ipt.value;
      nipt.name = ipt.name;
      nipt.checked = ipt.value == (tgt.getData()[ipt.name]||params.default);
      nipt.addEventListener('change',(e)=>{
        if( e.target.checked ){
          cell.setValue(ipt.value);
        }
        return true;
      })
      label.append(ipt.title);
      label.append(nipt);
      div.append(label);
    } )
    return div;
  },

  formatterInvalidVal: function( tgt, params ){
    let boool = false;
    switch( params.sp ){
      case "=":
        boool = tgt.getData()[params.field] === params.value; break;
      case ">":
        boool = tgt.getData()[params.field] > params.value; break;
      case "<":
        boool = tgt.getData()[params.field] < params.value; break;
      case ">=":
        boool = tgt.getData()[params.field] >= params.value; break;
      case "<=":
        boool = tgt.getData()[params.field] <= params.value; break;
      case "!=":
      case "<>":
        boool = tgt.getData()[params.field] !== params.value; break;
      case "in":
        boool = params.value.includes(tgt.getData()[params.field]); break;
    }

    if( boool ){
      if( params.validClass ){
        tgt.getElement().classList.add(params.validClass);
      }
      if( params.validValue ){
        return params.validValue;
      }
    }else{
      if( params.invalidClass ){
        tgt.getElement().classList.add(params.invalidClass);
      }
      if( params.invalidValue ){
        return params.invalidValue;
      }
    }
    return tgt.getValue();
  },

  editorSelect: function(cell, onRendered, success, cancel, editorParams){
    let edSelect = document.createElement("select");
    let params = editorParams.values;
    params = params || {};
    Object.keys(params).forEach(key => {
      let edOption = document.createElement("option");
      edOption.value = key;
      edOption.text = params[key];
      edSelect.append(edOption);
    });
    edSelect.className = 'form-select form-select-sm';
    edSelect.value = cell._cell.value;
    onRendered(function() {
      edSelect.focus();
    });

    let cback = function(){
      success( edSelect.value);
    }

    edSelect.addEventListener("change", cback);
    edSelect.addEventListener("blur", cback);

    return edSelect;
  },

  editorGrpSelect: function(cell, onRendered, success, cancel, editorParams){
    let edSelect = document.createElement("select");
    let params = editorParams.values;
    params = params || {};
    params.forEach(optg => {
      let edOptGrp = document.createElement("optgroup");
      edOptGrp.label = optg.name;
      Object.keys(optg.options).forEach( k => {
        let edOption = document.createElement("option");
        edOption.value = k;
        edOption.text = optg.options[k];
        edOptGrp.append(edOption);
      } );
      edSelect.append(edOptGrp);
    });
    //edSelect.className = 'form-select form-select-sm';
    edSelect.value = cell._cell.value;
    edSelect.classList.add("chosen");
    onRendered(function() {
      edSelect.focus();
      edSelect.style.width='100%';
    });

    let cback = function(){
      success(
        editorParams.cfunc ? editorParams.cfunc(cell, edSelect.value) : edSelect.value
      );
    }

    edSelect.addEventListener("change", cback);
    edSelect.addEventListener("blur", cback);
    return edSelect;
  },

  //필드 입력폼 (날짜입력)
  editorDate: function(cell, onRendered, success, cancel, editorParams) {
    let dateInput = document.createElement("input");
    dateInput.setAttribute("type", "date");
    dateInput.className = 'px-2 w-100';
    dateInput.value = cell._cell.value;
    onRendered(function() {
      dateInput.focus();
    });

    let cback = function(){
      success( (dateInput.value ? luxon.DateTime.fromISO(dateInput.value).toFormat('yyyy-MM-dd') : "") );
    }

    dateInput.addEventListener("change", cback);
    dateInput.addEventListener("blur", cback);

    return dateInput;
  },

  //필드 입력폼 (월/년도)
  editorMonth: function(cell, onRendered, success, cancel, editorParams) {
    let dateInput = document.createElement("input");
    new Cleave(dateInput, {
      date: true,
      datePattern: ['m', 'Y'],
      delimiter: '/'
    });

    // dateInput.setAttribute("type", "date");
    dateInput.className = 'px-2 w-100';
    dateInput.value = cell._cell.value;
    onRendered(function() {
      dateInput.focus();
    });

    let cback = function(){
      success( dateInput.value);
    }

    dateInput.addEventListener("change", cback);
    dateInput.addEventListener("blur", cback);

    return dateInput;
  },

  //필드 입력폼 (시간입력,단가입력)
  editorTm: function(cell, onRendered, success, cancel, editorParams) {
    let tmInput = document.createElement("input");
    tmInput.setAttribute("type", "number");
    tmInput.value = cell._cell.value;

    if (typeof onRendered === "function") {
        onRendered(function() {
            tmInput.focus();
        });
    } else {
        // onRendered가 함수가 아닐 경우 바로 포커스
        tmInput.focus();
    }

    let cback = function(){
        success(tmInput.value);
    }

    tmInput.addEventListener("change", cback);
    tmInput.addEventListener("blur", cback);

    return tmInput;
},


    //필드 입력폼 (텍스트입력)
    editorString: function(cell, onRendered, success, cancel, editorParams) {
      let stringInput = document.createElement("input");
      stringInput.setAttribute("type", "textarea");
      // stringInput.className = 'px-2 w-100';
      stringInput.value = cell._cell.value;
      onRendered(function() {
        stringInput.focus();
      });

      let cback = function(){
        success( stringInput.value);
      }

      stringInput.addEventListener("change", cback);
      stringInput.addEventListener("blur", cback);

      return stringInput;
    },


  
  //필드 입력폼 (전화번호,팩스) 
  editorTel: function(cell, onRendered, success, cancel, editorParams) {
    // 입력 요소 생성
    let telInput = document.createElement("input");
    telInput.setAttribute("type", "text");
    telInput.value = cell.getValue();
  
    telInput.addEventListener("input", function() {
      telInput.value = telInput.value
        .replace(/[^0-9]/g, "") 
        .replace(/^(\d{2,3})(\d{3,4})(\d{4})$/, "$1-$2-$3"); 
    });
  

    onRendered(function() {
      telInput.focus();
    });
  
    let cback = function() {
      success(telInput.value);
    };
  
    telInput.addEventListener("change", cback);
    telInput.addEventListener("blur", cback);
  
    return telInput;
  },


  //Row checked class Toggle
  toggleRowChecked: function( tgt, row ){
    if( typeof tgt == "object" ){
      row = tgt;
      row.parent.element.querySelectorAll(".tabulator-table .tabulator-row.tabulator-checked").forEach(tgt => tgt.classList.remove("tabulator-checked"));
    }else{
      document.querySelectorAll(tgt + " .tabulator-table .tabulator-row.tabulator-checked").forEach(tgt => tgt.classList.remove("tabulator-checked"));
    }
    if( row != undefined ){
      row.element.classList.add("tabulator-checked");
    }
  },

  /* Tabulator to Excel
   * params : 타블레이터 테이블, 생성할 엑셀 파일명, 엑셀 안에 들어갈 제목, 엑셀에 입력될 데이터(선택)
   */
  tabu2xls: function( tab_table, filename, title, udata ){
    //let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined).map(s=>({key:s.field, width:Math.round(((s.minWidth||s.width.replace(/[^0-9]/,''))||100)/6), title:s.title}));
    //width %는 고려하지 않음
    let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined && !v.noxls)
      .reduce( (retv,row) => {
        if( row.columns ){
          row.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined && !v.noxls).forEach(crow => {
            retv.push({
              key  : crow.field,
              width: Math.round(((crow.minWidth||crow.width.replace(/[^0-9]/,'')*10)||100)/6),
              title: crow.title.replaceAll('<br>',''),
              dcss: crow.dcss,
            });
          });
        }else{
          retv.push({
            key  : row.field,
            width: Math.round(((row.minWidth||row.width.replace(/[^0-9]/,'')*10)||100)/6),
            title: row.title.replaceAll('<br>',''),
            dcss: row.dcss,
          });
        }
        return retv;
      }, [] );

      let datas = udata || tab_table.getData("active").map(data => header.map(s=>s.key).reduce((ov,cv) => ({...ov, [cv]:(data[cv]||"")}), {})); //"active" <= filtered 된 데이터만 가져온다.
      console.log(datas);
    
    json2xls(filename, title, header, datas);
  },


  /* 
   * Tabulator to Excel
   * 서브컬럼이 있을때 상위컬럼 대신에 서브 컬럼만 엑셀에 포함된다.
   * params : 타블레이터 테이블, 생성할 엑셀 파일명, 엑셀 안에 들어갈 제목, 엑셀에 입력될 데이터(선택)
   */
  tabu2xls2: function( tab_table, filename, title, udata ){
    //let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined).map(s=>({key:s.field, width:Math.round(((s.minWidth||s.width.replace(/[^0-9]/,''))||100)/6), title:s.title}));
    //width %는 고려하지 않음
    let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined && !v.noxls)
      .reduce( (retv,row,idx) => {
        retv.push({
          key  : row.field,
          width: Math.round(((row.minWidth||row?.width?.replace(/[^0-9]/,'')*10)||100)/6),
          title: row.title.replaceAll('<br>',''),
          dcss: row.dcss,
          columns : row.columns ? row.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined && !v.noxls).map(crow => {
            return{
              key  : crow.field,
              width: Math.round(((crow.minWidth||crow?.width?.replace(/[^0-9]/,'')*10)||100)/6),
              title: crow.title.replaceAll('<br>',''),
              dcss: crow.dcss,
            };
          }) : []
        });
        return retv;
      }, [] );
     let datas = udata || tab_table.getData("active").map(data => header.map(s=>s.key).reduce((ov,cv) => ({...ov, [cv]:(data[cv]||"")}), {})); //"active" <= filtered 된 데이터만 가져온다.

    json2xls(filename, title, header, datas);
  },

  /* 
   * Tabulator to Excel
   * 그룹바이한 테이블 + 서브컬럼(상위컬럼도 같이 엑셀에 포함) 있을때 사용
   * width는 px
   * params : 타블레이터 테이블, 생성할 엑셀 파일명, 엑셀 안에 들어갈 제목, 엑셀에 입력될 데이터(선택)
   */
  tabu2xls3: function( tab_table, filename, title, udata ){
    //let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined).map(s=>({key:s.field, width:Math.round(((s.minWidth||s.width.replace(/[^0-9]/,''))||100)/6), title:s.title}));
    //width %는 고려하지 않음
    // field 없어도 체크
    let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && !v.noxls)
      .reduce( (retv,row) => {
        if( row.columns ){
          // 그룹바이
          const groupRow = { columns: [], title: row.title }
          row.columns.forEach(crow =>{
            groupRow.columns.push({
                  key  : crow.field,
                  width: Math.round(((crow.minWidth||crow.width)||100)/6),
                  title: crow.title.replaceAll('<br>',''),
                  dcss: crow.dcss,
                });
          })
          retv.push(groupRow)
        }else{
          retv.push({
            key  : row.field,
            width: Math.round(((row.minWidth||row.width)||100)/6),
            title: row.title.replaceAll('<br>',''),
            dcss: row.dcss,
          });
        }
        return retv;
      }, [] );
      
      let headerLst = []
      header.forEach(h => {
        if(h.columns){
          h.columns.forEach(col =>{
            headerLst.push(col.key);
          })
        }else{
          headerLst.push(h.key);
        }
      })

      let datas = udata || tab_table.getData("active").map(data => headerLst.reduce((ov,cv) => ({...ov, [cv]:(data[cv]||"")}), {})); //"active" <= filtered 된 데이터만 가져온다.
      json2xls_num(filename, title, header, datas);
  },

  /* 
   * Tabulator to Excel
   * 서브컬럼이 있을때 상위컬럼 대신에 서브 컬럼만 엑셀에 포함된다.
   * width는 px
   * params : 타블레이터 테이블, 생성할 엑셀 파일명, 엑셀 안에 들어갈 제목, 엑셀에 입력될 데이터(선택)
   */
  tabu2xls_px: function( tab_table, filename, title, udata ){
    //let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined).map(s=>({key:s.field, width:Math.round(((s.minWidth||s.width.replace(/[^0-9]/,''))||100)/6), title:s.title}));
    //width는 px
    let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined && !v.noxls)
      .reduce( (retv,row) => {
        if( row.columns ){
          row.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined && !v.noxls).forEach(crow => {
            retv.push({
              key  : crow.field,
              width: Math.round(((crow.minWidth||crow.width)||100)/6),
              title: crow.title.replaceAll('<br>',''),
              dcss: crow.dcss,
            });
          });
        }else{
          retv.push({
            key  : row.field,
            width: Math.round(((row.minWidth||row.width)||100)/6),
            title: row.title.replaceAll('<br>',''),
            dcss: row.dcss,
          });
        }
        return retv;
      }, [] );

      let datas = udata || tab_table.getData("active").map(data => header.map(s=>s.key).reduce((ov,cv) => ({...ov, [cv]:(data[cv]||"")}), {})); //"active" <= filtered 된 데이터만 가져온다.
    
      json2xls_num(filename, title, header, datas);
  },

  /* 
   * Tabulator to Excel
   * visible이 false라도 엑셀에 포함됨.
   * 서브컬럼이 있을때 상위컬럼 대신에 서브 컬럼만 엑셀에 포함된다.
   * width는 px
   * params : 타블레이터 테이블, 생성할 엑셀 파일명, 엑셀 안에 들어갈 제목, 엑셀에 입력될 데이터(선택)
   */
  all_tabu2xls_px: function( tab_table, filename, title, udata ){
    //let header = tab_table.options.columns.filter(v=>(v.visible != false || v.yesxls) && v.field != undefined).map(s=>({key:s.field, width:Math.round(((s.minWidth||s.width.replace(/[^0-9]/,''))||100)/6), title:s.title}));
    let header = tab_table.options.columns.filter(v=> v.field != undefined && !v.noxls)
      .reduce( (retv,row) => {
        if( row.columns ){
          row.columns.filter(v=>v.field != undefined && !v.noxls).forEach(crow => {
            retv.push({
              key  : crow.field,
              width: Math.round(((crow.minWidth||crow.width)||100)/6),
              title: crow.title.replaceAll('<br>',''),
              dcss: crow.dcss,
            });
          });
        }else{
          retv.push({
            key  : row.field,
            width: Math.round(((row.minWidth||row.width)||100)/6),
            title: row.title.replaceAll('<br>',''),
            dcss: row.dcss,
          });
        }
        return retv;
      }, [] );


      let datas = udata || tab_table.getData("active").map(data => header.map(s=>s.key).reduce((ov,cv) => ({...ov, [cv]:(data[cv]||"")}), {})); //"active" <= filtered 된 데이터만 가져온다.
    
    json2xls_num(filename, title, header, datas);
  },

  precs: function( abool,dnum,num ){
    num = (typeof num !== "undefined") ? num : dnum;
    num = abool?num:dnum;
    return {precision: num};
  }

  // filter_clear: function(table){
  //   document.getElementById("filter-clear").addEventListener("click", function(){
  //     document.getElementsByName("filter-clear")filter.value = "";
  //     valueEl.value = "";

  //     table.clearFilter();
  //   });
  // }
}