AS.SERVICES.showWaitWindow = Cons.showLoader;
AS.SERVICES.hideWaitWindow = Cons.hideLoader;
AS.SERVICES.showErrorMessage = str => showMessage(str, 'error');

this.UTILS = {
  createField: function(fieldData) {
    const field = {};
    for (let key in fieldData) field[key] = fieldData[key];
    return field;
  },
  getValue: function(data, cmpID) {
    data = data.data ? data.data : data;
    return data.find(x => x.id == cmpID);
  },
  setValue: function(asfData, cmpID, data) {
    let field = this.getValue(asfData, cmpID);
    if(field) {
      for (let key in data) {
        if(key === 'id' || key === 'type') continue;
        field[key] = data[key];
      }
      return field;
    } else {
      asfData = asfData.data ? asfData.data : asfData;
      field = this.createField(data);
      field.id = cmpID;
      asfData.push(field);
      return field;
    }
  },
  getTableBlockIndex: function(data, cmp) {
    let res = 0;
    data = data.data ? data.data : data;
    data.forEach(item => {
      if (item.id.slice(0, item.id.indexOf('-b')) === cmp) res++;
    });
    return res === 0 ? 1 : ++res;
  }
}

UTILS.show = id => fire({type: 'set_hidden', hidden: false}, id);
UTILS.hide = id => fire({type: 'set_hidden', hidden: true}, id);
UTILS.changeLabel = (id, ru, kk, en = ru) => fire({type: 'change_label', text: localizedText(ru, ru, kk, en)}, id);

UTILS.getPageParamValue = paramName => {
  const {paramValues, params, pageParams} = Cons.getCurrentPage();
  const param = params.find(x => x.name == paramName);
  if(!param || !param.hasOwnProperty('id')) return null;
  return paramValues.find(x => x.pageParamID == param.id || x.pageParamName == paramName)?.value || null;
}

UTILS.formatDate = function(datetime, time) {
  let result = datetime.getFullYear() + '-' +
    ('0' + (datetime.getMonth() + 1)).slice(-2) + '-' +
    ('0' + datetime.getDate()).slice(-2) + ' ' +
    ('0' + datetime.getHours()).slice(-2) + ':' +
    ('0' + datetime.getMinutes()).slice(-2) + ':' +
    ('0' + datetime.getSeconds()).slice(-2);
  return time ? result : result.substring(0, result.indexOf(' '));
};

UTILS.getCurrentDateParse = () => UTILS.formatDate(new Date(), true); /*yyyy-mm-dd HH:MM:SS*/

UTILS.parseDateTime = datetime => {
  datetime = datetime.split(/\D/);
  return new Date(datetime[0], datetime[1] - 1, datetime[2], datetime[3] || 0, datetime[4] || 0, datetime[5] || 0);
};

UTILS.customFormatDate = datetime => {
  datetime = datetime.split(/\D/);
  return datetime[2] + '.' + datetime[1] + '.' + datetime[0] + ' ' + datetime[3] + ':' + datetime[4];
}

UTILS.filterProcesses = (processes, actionID) => {
  const result = [];
  const search = p => {
    p.forEach(x => {
      if (!x.finished && x.actionID == actionID && x.responsibleUserID == AS.OPTIONS.currentUser.userid && x.typeID != '') result.push(x);
      if (x.subProcesses.length) search(x.subProcesses);
    });
  }
  search(processes);
  return result;
}

UTILS.parseAsfValue = asfDataValue => {
  if(!asfDataValue) return null;
  const {type, value = '', key = ''} = asfDataValue;
  return key ? {type, value, key} : {type, value};
}

UTILS.parseAsfTable = asfTable => {
  const result = [];
  try {
    if(!asfTable.hasOwnProperty('data')) return result;

    const data = asfTable.data.filter(x => x.type != 'label');
    if(!data.length) return result;

    const ids = data.map(x => x.id.slice(0, x.id.indexOf('-b'))).uniq();
    let tbi =  data.slice(-1)[0].id;
    tbi = Number(tbi.slice(tbi.indexOf('-b') + 2));

    for(let i = 1; i <= tbi; i++) {
    	const item = {};
      ids.forEach(key => {
        const parseValue = UTILS.parseAsfValue(UTILS.getValue(asfTable, `${key}-b${i}`));
        if(parseValue) item[key] = parseValue;
      });
      result.push(item);
    }

    return result;
  } catch (err) {
    console.log('ERROR parseAsfTable', err);
    return result;
  }
}

UTILS.getSynergyPlayer = (dataUUID, editable = false, dataVersion = null) => {
  const player = AS.FORMS.createPlayer();
  if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
    player.model.showView('mobile');
  }
  player.view.setEditable(editable);
  player.showFormData(null, null, dataUUID, dataVersion);
  return player;
}

UTILS.getModalDialog = async (title, body, buttonName, buttonAction) => {
  const dialog = $('<div class="uk-flex-top" uk-modal>');
  const md = $('<div class="uk-modal-dialog uk-margin-auto-vertical">');
  const modalBody = $('<div class="uk-modal-body" uk-overflow-auto>');
  const footer = $('<div class="uk-modal-footer uk-text-right">');
  const exitText = i18n.tr("Закрыть");

  modalBody.append(body);
  footer.append(`<button class="uk-button uk-button-default uk-modal-close" type="button">${exitText}</button>`);
  md.append(`<button class="uk-modal-close-default modal-close-custom" type="button" uk-close></button>`,
  `<div class="uk-modal-header"><h3>${title}</h3></div>`, modalBody, footer);
  dialog.append(md);

  if(buttonName) {
    const actionButton = $('<button class="uk-button uk-button-primary uk-margin-left" type="button">');
    actionButton.html(buttonName).on('click', buttonAction);
    footer.append(actionButton);
  }

  return dialog;
}

UTILS.getSmallModalDialog = (title, body) => {
  const dialog = $('<div class="uk-flex-top" uk-modal>');
  const md = $('<div class="uk-modal-dialog uk-margin-auto-vertical">');
  const modalBody = $('<div class="uk-modal-body" uk-overflow-auto>');
  const footer = $('<div class="uk-modal-footer uk-text-right">');

  modalBody.append(body);
  footer.append(`<button class="uk-button uk-button-default uk-modal-close" type="button">${i18n.tr("Закрыть")}</button>`);
  md.append(`<button class="uk-modal-close-default modal-close-custom" type="button" uk-close></button>`,
  `<div class="uk-modal-header"><h3>${title}</h3></div>`, modalBody, footer);
  dialog.append(md);
  return dialog;
}

UTILS.getDialogFinishProcess = async (title, buttons, typeID, handler) => {
  const dialog = $('<div class="uk-flex-top" uk-modal>');
  const header = $('<div>', {class: 'uk-modal-header', style: 'width: 100%; height: 40px;'});
  const titleHeader = $('<h3>');
  const md = $('<div class="uk-modal-dialog uk-margin-auto-vertical">');
  const modalBody = $('<div class="uk-modal-body" uk-overflow-auto>');
  const footer = $('<div class="uk-modal-footer uk-text-right">');
  const commentInput = $(`<textarea class="uk-textarea" rows="5" placeholder="${i18n.tr("Комментарий")}"></textarea>`);

  modalBody.append($('<div class="uk-margin">').append(commentInput));

  titleHeader.text(title);
  titleHeader.css({
    'white-space': 'nowrap',
    'overflow': 'hidden',
    'text-overflow': 'ellipsis',
    'width': 'calc(100% - 50px)'
  });

  header.append(titleHeader);

  dialog.append(md);
  md.append(header).append(modalBody).append(footer);

  buttons.forEach(button => {
    const agreeButton = $('<button class="uk-button uk-button-default uk-margin-left" type="button">');
    agreeButton.html(button.label).on('click', () => handler(button.signal, commentInput.val()));
    footer.append(agreeButton);
  });

  return dialog;
}

UTILS.getFullModalDialog = (title = '', body) => {
  const dialog = $('<div class="uk-modal-full" uk-modal="stack: true;" style="z-index: 500;">');
  const md = $('<div class="uk-modal-dialog" style="height: 100%; background: #d3d3d3;">');
  const header = $('<div>', {class: 'uk-modal-header', style: 'width: 100%; height: 40px;'});
  const titleHeader = $('<h3>');

  titleHeader.text(title);
  titleHeader.css({
    'white-space': 'nowrap',
    'overflow': 'hidden',
    'text-overflow': 'ellipsis',
    'width': 'calc(100% - 50px)'
  });

  header.append(titleHeader);

  md.append(
    `<button class="uk-modal-close-full uk-close-custom" type="button" uk-close></button>`,
    header, body
  );

  dialog.append(md);
  return dialog;
}

UTILS.printForm = content => {
  const css = '<link rel="stylesheet" href="synergyForms.css" type="text/css" />';
  const WinPrint = window.open();
  WinPrint.document.write('');
  WinPrint.document.write(css);
  WinPrint.document.write(content.innerHTML);
  WinPrint.document.write('');
  WinPrint.document.close();
  WinPrint.focus();
  WinPrint.print();
}

UTILS.generateGuid = prefix => prefix+'-'+Math.random().toString(36).substring(2, 15)+Math.random().toString(36).substring(2, 15);

UTILS.parseSignXML = XMLText => {
  const parser = new DOMParser();
  const xmlDoc = parser.parseFromString(XMLText, "text/xml");
  const nodeContent = [...xmlDoc.getElementsByTagName('signature')];
  const result = [];

  nodeContent.forEach(node => {
  	const children = [...node.children];
    const tmp = {};
  	children.forEach(item => {
      const {tagName, textContent} = item;
      tmp[tagName] = textContent;
    });
    result.push(tmp);
  });

  return result;
}

UTILS.getCurrentUserFullName = () => {
  const {firstname, lastname, patronymic} = AS.OPTIONS.currentUser;
  const fio = lastname.substr(0, 1).toUpperCase() + lastname.substr(1) + ' ' + firstname.substr(0, 1).toUpperCase() + '.';
  return patronymic ? fio + ' ' + patronymic.substr(0, 1).toUpperCase() + '.' : fio;
}

UTILS.fileDownload = async (fileName, identifier) => {
  const blob = await appAPI.getFile(identifier);
  Cons.hideLoader();
  if(blob) {
    const fileURL = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    if(typeof a.download === 'undefined') {
      window.location = fileURL;
    } else {
      a.href = fileURL;
      a.download = fileName;
      document.body.appendChild(a);
      a.click();
    }
  }
}

UTILS.parseRegistryList = list => {
  const result = [];
  function s(data) {
    data.forEach(item => {
      item.consistOf && item.consistOf.length > 0 ? s(item.consistOf) : result.push(item);
    });
  }
  s(list);
  return result;
}

UTILS.createSelectComponent = (label, items, multiple = false) => {
  const container = $('<div>', {class: 'uk-margin-small'});
  const fc = $('<div>', {class: 'uk-form-controls'});
  const select = $('<select class="uk-select" style="min-width: 100px;">');

  if(multiple) select.attr('multiple', 'multiple');
  if(items) items.sort((a,b) => a.value - b.value)
  .forEach(item => select.append(`<option value="${item.value}" title="${item.label}">${item.label}</option>`));

  fc.append(select);
  container.append(`<label class="uk-form-label uk-text-bold">${label}</label>`).append(fc);

  return {container, select};
}

UTILS.detectBrowser = () => {
  const browserVersion = (userAgent, regex) => {
    return userAgent.match(regex) ? userAgent.match(regex)[2] : null;
  }

  const userAgent = navigator.userAgent;
  let browser = 'unknown';

  browser = /ucbrowser/i.test(userAgent) ? 'UCBrowser' : browser;
  browser = /edg/i.test(userAgent) ? 'Edge' : browser;
  browser = /googlebot/i.test(userAgent) ? 'GoogleBot' : browser;
  browser = /chromium/i.test(userAgent) ? 'Chromium' : browser;
  browser =
    /firefox|fxios/i.test(userAgent) && !/seamonkey/i.test(userAgent) ?
    'Firefox' :
    browser;
  browser =
    /; msie|trident/i.test(userAgent) && !/ucbrowser/i.test(userAgent) ?
    'IE' :
    browser;
  browser =
    /chrome|crios/i.test(userAgent) &&
    !/opr|opera|chromium|edg|ucbrowser|googlebot/i.test(userAgent) ?
    'Chrome' :
    browser;
  browser =
    /safari/i.test(userAgent) &&
    !/chromium|edg|ucbrowser|chrome|crios|opr|opera|fxios|firefox/i.test(
      userAgent
    ) ?
    'Safari' :
    browser;
  browser = /opr|opera/i.test(userAgent) ? 'Opera' : browser;

  // detect browser version
  switch (browser) {
    case 'UCBrowser':
      return {name: browser, version: browserVersion(userAgent, /(ucbrowser)\/([\d\.]+)/i)};
    case 'Edge':
      return {name: browser, version: browserVersion(userAgent, /(edge|edga|edgios|edg)\/([\d\.]+)/i)};
    case 'GoogleBot':
      return {name: browser, version: browserVersion(userAgent, /(googlebot)\/([\d\.]+)/i)};
    case 'Chromium':
      return {name: browser, version: browserVersion(userAgent, /(chromium)\/([\d\.]+)/i)};
    case 'Firefox':
      return {name: browser, version: browserVersion(userAgent, /(firefox|fxios)\/([\d\.]+)/i)};
    case 'Chrome':
      return {name: browser, version: browserVersion(userAgent, /(chrome|crios)\/([\d\.]+)/i)};
    case 'Safari':
      return {name: browser, version: browserVersion(userAgent, /(safari)\/([\d\.]+)/i)};
    case 'Opera':
      return {name: browser, version: browserVersion(userAgent, /(opera|opr)\/([\d\.]+)/i)};
    case 'IE':
      const version = browserVersion(userAgent, /(trident)\/([\d\.]+)/i);
      return version
        ? {name: browser, version: parseFloat(version) + 4.0}
        : {name: browser, version: '7.0'};
    default:
      return {name: 'unknown', version: '0.0.0.0'};
  }
}

const getDictValue = (item, id) => item.values.find(x => x.columnID == id)?.value || null;

UTILS.parseDict = dict => {
  const result = [];
  try {
    if(!dict) throw new Error('Не передан справочник');

    dict.items.forEach(item => {
      const tmp = {};
      tmp.itemID = item.itemID;
      dict.columns.forEach(col => tmp[col.code] = getDictValue(item, col.columnID));
      result.push(tmp);
    });

    return result;
  } catch (err) {
    console.log(`ERROR [parseDict]: ${err.message}`);
    return result;
  }
}

UTILS.Cookie = {
  get: function(name) {
    let matches = document.cookie.match(new RegExp(
      "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
    ));
    return matches ? decodeURIComponent(matches[1]) : undefined;
  },

  set: function(name, value, options = {}) {
    options = {path: '/', ...options};

    if (options.expires instanceof Date) options.expires = options.expires.toUTCString();

    let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);

    for (let optionKey in options) {
      updatedCookie += "; " + optionKey;
      let optionValue = options[optionKey];
      if (optionValue !== true) updatedCookie += "=" + optionValue;
    }

    document.cookie = updatedCookie;
  },

  delete: function(){
    UTILS.Cookie.set(name, "", {'max-age': -1});
  }
}

//выпиливыние из массива повторяющихся елементов
Array.prototype.uniq = function() {
  return this.filter(function(v, i, a){ return i == a.indexOf(v) });
}
