let API = {
  host: "http://127.0.0.1:8080/Synergy/",

  getHttpClient: function(){
    let client = new org.apache.commons.httpclient.HttpClient();
    let creds = new org.apache.commons.httpclient.UsernamePasswordCredentials(login, password);
    client.getParams().setAuthenticationPreemptive(true);
    client.getState().setCredentials(org.apache.commons.httpclient.auth.AuthScope.ANY, creds);
    return client;
  },
  httpGetMethod: function(methods, type) {
    let client = this.getHttpClient();
    let get = new org.apache.commons.httpclient.methods.GetMethod(this.host + methods);
    get.setRequestHeader("Content-type", "application/json");
    client.executeMethod(get);
    let resp = get.getResponseBodyAsString();
    get.releaseConnection();
    return type == 'text' ? resp : JSON.parse(resp);
  },
  httpPostMethod: function(methods, params, contentType) {
    let client = this.getHttpClient();
    let post = new org.apache.commons.httpclient.methods.PostMethod(this.host + methods);
    if(contentType) post.setRequestBody(JSON.stringify(params));
    else for(let key in params) post.addParameter(key, params[key]);
    post.setRequestHeader("Content-type", contentType || "application/x-www-form-urlencoded; charset=utf-8");
    let resp = client.executeMethod(post);
    if(contentType) resp = JSON.parse(post.getResponseBodyAsString());
    post.releaseConnection();
    return resp;
  },
  createDocRCC: function(registryCode, data) {
    return this.httpPostMethod("rest/api/registry/create_doc_rcc", {
      registryCode: registryCode,
      data: data
    }, "application/json; charset=utf-8");
  },
  activateDoc: function(documentID) {
    return this.httpGetMethod("rest/api/registry/activate_doc?documentID=" + documentID);
  },
  getFormData: function(asfDataId) {
    return this.httpGetMethod("rest/api/asforms/data/" + asfDataId)
  },
  saveFormData: function(asfData) {
    return this.httpPostMethod("rest/api/asforms/form/multipartdata", {
      form: asfData.form,
      uuid: asfData.uuid,
      data: "\"data\":" + JSON.stringify(asfData.data)
    });
  },
  mergeFormData: function(asfData) {
    return this.httpPostMethod("rest/api/asforms/data/merge", {
      uuid: asfData.uuid,
      data: asfData.data
    }, "application/json; charset=utf-8");
  },
  sendNotification: function(body) {
    /*body = {
      header: 'theme',
      message: 'subject',
      emails: [emails]
    }*/
    return this.httpPostMethod("rest/api/notifications/send", body, "application/json; charset=utf-8");
  },
  getAsfDataId: function(documentID) {
    return this.httpGetMethod("rest/api/formPlayer/getAsfDataUUID?documentID=" + documentID, 'text');
  },
  getDocumentID: function(asfDataId) {
    return this.httpGetMethod("rest/api/formPlayer/documentIdentifier?dataUUID=" + asfDataId, 'text');
  },
  getDocumentInfo: function(documentID) {
    return this.httpGetMethod("rest/api/docflow/doc/document_info?documentID=" + documentID);
  },
  getDocMeaningContent: function(documentID) {
    return this.httpGetMethod("rest/api/formPlayer/getDocMeaningContent?documentId=" + documentID, 'text');
  },
  getProcesses: function(documentID) {
    return this.httpGetMethod("rest/api/workflow/get_execution_process?documentID=" + documentID);
  },
  getWorkCompletionData: function(workID) {
    return this.httpGetMethod("rest/api/workflow/work/get_completion_data?workID=" + workID);
  },
  getFormDescription: function(formID) {
    return this.httpGetMethod("rest/api/asforms/form/" + formID + "?isMobile=false");
  },
  getSynergyCalendar: function(start, finish) {
    return this.httpGetMethod("rest/api/settings/calendar?date_start=" + start + "&date_finish=" + finish);
  },
  getWorkTime: function(startDate, finishDate) {
    return this.httpGetMethod("rest/api/workflow/getWorkTime?startDate=" + encodeURIComponent(startDate) + "&finishDate=" + encodeURIComponent(finishDate));
  },
  getFinishDate: function(startDate, duration) {
    return this.httpGetMethod("rest/api/workflow/get_finish_date?startDate=" + encodeURIComponent(startDate) + "&duration=" + duration);
  },
  getFormForResult: function(formCode, workID) {
    return this.httpGetMethod("rest/api/workflow/work/get_form_for_result?formCode=" + formCode + "&workID=" + workID);
  },
  finishWork: function(actionID, file_identifier) {
    return this.httpPostMethod("rest/api/workflow/work/set_result", {
        workID: actionID,
        completionForm: "FORM",
        type: 'work',
        file_identifier: file_identifier
    });
  },
  getPrintFilePDF: function(asfDataId) {
    let client = this.getHttpClient();
    let post = new org.apache.commons.httpclient.methods.PostMethod(this.host + "rest/api/asforms/data/print");
    post.setRequestBody('{"dataUUID": "' + asfDataId + '", "format": "PDF"}');
    post.setRequestHeader("Content-type", "application/json");
    post.setRequestHeader("Content-disposition", "attachment; filename=printFile.pdf");
    let resp = client.executeMethod(post);
    let pdfResult = post.getResponseBody();
    post.releaseConnection();
    return pdfResult;
  },
  startUpload: function() {
    return this.httpGetMethod("rest/api/storage/start_upload");
  },
  uploadPart: function(filePath, file) {
    //filePath - result api/storage/start_upload
    let client = this.getHttpClient();
    let uploadPart = new org.apache.commons.httpclient.methods.PostMethod(this.host + "rest/api/storage/upload_part?file=" + filePath);
    let base64 = java.util.Base64.getEncoder();
    let encodedBytes = base64.encode(file);
    encodedBytes = new org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource("filename.txt", encodedBytes);
    let filePart = new org.apache.commons.httpclient.methods.multipart.FilePart("body", encodedBytes);
    let parts = new Array();
    parts.push(filePart);
    let entity = new org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity(parts, uploadPart.getParams());
    uploadPart.setRequestEntity(entity);
    let uploadStatus = client.executeMethod(uploadPart);
    let uploadResult = uploadPart.getResponseBodyAsString();
    uploadPart.releaseConnection();
    return uploadResult;
  },
  addFileInForm: function(asfDataId, fileName, filePath, overwrite) {
    //filePath - result api/storage/start_upload
    let client = this.getHttpClient();
    let params = "?dataUUID=" + asfDataId + "&fileName=" + fileName + "&filePath=" + filePath;
    if(overwrite) params += "&overwrite=true";
    let post = new org.apache.commons.httpclient.methods.PostMethod(this.host + "rest/api/storage/asffile/addFile" + params);
    post.setRequestHeader("Content-type", "application/json; charset=utf-8");
    let resp = client.executeMethod(post);
    resp = JSON.parse(post.getResponseBodyAsString());
    post.releaseConnection();
    return resp;
  },
  appendTable: function(uuid, tableId, data) {
    return this.httpPostMethod("rest/api/asforms/data/append_table", {
      uuid: uuid,
      tableId: tableId,
      data: data
    }, "application/json; charset=utf-8");
  },
  getDictionary: function(dictionaryCode) {
    return this.httpGetMethod("rest/api/dictionary/get_by_code?dictionaryCode=" + dictionaryCode);
  }
};

let log = {
  parse: function(args) {
    let result = [];
    for (let x in args) result.push(JSON.stringify(args[x], null, 4));
    return documentID + '\n' + result.join('\n');
  },
  info: function() {
    console.info(this.parse(arguments));
  },
  error: function() {
    console.error(this.parse(arguments));
  }
}

let UTILS = {
  createField: function(fieldData) {
    let field = {};
    for (let key in fieldData) field[key] = fieldData[key];
    return field;
  },
  getValue: function(data, cmpID) {
    data = data.data ? data.data : data;
    for(let i = 0; i < data.length; i++)
    if (data[i].id === cmpID) return data[i];
    return null;
  },
  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(function(item) {
      if (item.id.slice(0, item.id.indexOf('-b')) === cmp) res++;
    });
    return res === 0 ? 1 : ++res;
  }
};

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 = function() {
  return this.formatDate(new Date(), true); /*yyyy-mm-dd HH:MM:SS*/
};

UTILS.parseDateTime = function(datetime /*yyyy-mm-dd HH:MM:SS*/) {
  datetime = datetime.split(/\D/);
  return new Date(datetime[0], datetime[1] - 1, datetime[2], datetime[3] || 0, datetime[4] || 0, datetime[5] || 0);
};

UTILS.getCmpType = function(formDescription, cmpID) {
  let result = null;
  for (let i = 0; i < formDescription.properties.length; i++) {
    if (formDescription.properties[i].id === cmpID) {
      result = formDescription.properties[i].type;
      break;
    }
    if (formDescription.properties[i].type === "table") {
      result = this.getCmpType(formDescription.properties[i], cmpID) || result;
    }
  }
  return result;
};

UTILS.getParams = function(str){
  return str.split('$').filter(function(item) {
    if (item.indexOf('{') !== -1) return item;
  }).map(function(item) {
    return item.substring(item.indexOf('{') + 1, item.indexOf('}'));
  });
};

UTILS.parseAsfValue = function(asfDataValue){
  if(!asfDataValue) return null;
  if(asfDataValue.hasOwnProperty('key')) {
    return {
      type: asfDataValue.type,
      value: asfDataValue.value || '',
      key: asfDataValue.key || ''
    }
  } else if (asfDataValue.type == "check") {
    return {
      type: asfDataValue.type,
      values: asfDataValue.values || '',
      keys: asfDataValue.keys || ''
    }
  } else {
    return {
      type: asfDataValue.type,
      value: asfDataValue.value || ''
    }
  }
}

UTILS.parseAsfTable = function(asfTable){
  let result = [];
  try {
    if(!asfTable || !asfTable.hasOwnProperty('data')) return result;

    let data = asfTable.data.filter(function(x){
      if(x.type != 'label') return x;
    });
    if(!data.length) return result;

    let tmpids = [];
    data.forEach(function(x){
      tmpids.push(x.id.slice(0, x.id.indexOf('-b')));
    });
    let ids = tmpids.uniq();

    let tbi =  data.slice(-1)[0].id;
    tbi = Number(tbi.slice(tbi.indexOf('-b') + 2));

    for(let i = 1; i <= tbi; i++) {
    	let item = {};
      ids.forEach(function(id){
        let cmpID = id + '-b' + i;
        let parseValue = UTILS.parseAsfValue(UTILS.getValue(asfTable, cmpID));
        if(parseValue) item[id] = parseValue;
      });
      result.push(item);
    }
    return result;
  } catch (err) {
    return result;
  }
}

function getDictValue(item, id){
	return item.values.filter(function(x){if(x.columnID == id) return x})[0].value;
}

UTILS.parseDict = function(dict){
  let result = [];
  try {
    if(!dict) throw new Error('Не передан справочник');
    
    dict.items.forEach(function(item){
      let tmp = {};
      tmp.itemID = item.itemID;
      dict.columns.forEach(function(col){
        tmp[col.code] = getDictValue(item, col.columnID)
      });
      result.push(tmp);
    });

    return result;
  } catch (err) {
    return result;
  }
}

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