/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.24/esri/copyright.txt for details. */ import{difference as e}from"../../core/arrayUtils.js";import t from"../../core/Error.js";import a from"../../core/Logger.js";import{isNone as r,isSome as o}from"../../core/maybe.js";import{debounce as s,eachAlways as l}from"../../core/promiseUtils.js";import{updateOrigins as i}from"../../core/accessorSupport/originUtils.js";import n from"../FeatureLayer.js";import{fetchFeatureService as u}from"../support/arcgisLayers.js";import{parse as p}from"../support/arcgisLayerUrl.js";import{isFeatureCollectionLayer as c,isFeatureServiceLayer as y}from"../support/layerUtils.js";import d from"../../portal/Portal.js";import m from"../../portal/PortalItem.js";import{createForItemWrite as f}from"../../portal/support/jsonContext.js";import{addTypeKeyword as w,TypeKeyword as h,getWGS84ExtentForItem as v,removeTypeKeyword as b}from"../../portal/support/portalItemUtils.js";const I=a.getLogger("esri.layers.FeatureLayer"),S="Feature Service";function g(e,t){return`Layer (title: ${e.title}, id: ${e.id}) of type '${e.declaredClass}' ${t}`}function j(e,a){if(a.type!==S)throw new t("feature-layer:portal-item-wrong-type",g(e,`should have portal item of type "${S}"`))}async function L(e){if(await e.load(),c(e))throw new t("feature-layer:save",g(e,"using an in-memory source cannot be saved to a portal item"))}function P(e,a){let r=e.messages.filter((({type:e})=>"error"===e)).map((({name:e,message:a,details:r})=>new t(e,a,r)));if(a?.ignoreUnsupported&&(r=r.filter((({name:e})=>"layer:unsupported"!==e&&"symbol:unsupported"!==e&&"symbol-layer:unsupported"!==e&&"property:unsupported"!==e&&"url:unsupported"!==e))),r.length>0)throw new t("feature-layer:save","Failed to save feature layer due to unsupported or invalid content. See 'details.errors' for more detailed information",{errors:r})}async function J(e,t,a){"beforeSave"in e&&"function"==typeof e.beforeSave&&await e.beforeSave();const r=e.write({},t);return P(t,a),r}function N(e){const{layer:t,layerJSON:a}=e;return t.isTable?{layers:[],tables:[a]}:{layers:[a],tables:[]}}function O(e){w(e,h.JSAPI),e.typeKeywords&&(e.typeKeywords=e.typeKeywords.filter(((e,t,a)=>a.indexOf(e)===t)))}function E(e){const a=e.portalItem;if(!a)throw I.error("save: requires the portalItem property to be set"),new t("feature-layer:portal-item-not-set",g(e,"requires the portalItem property to be set"));if(!a.loaded)throw new t("feature-layer:portal-item-not-loaded",g(e,"cannot be saved to a portal item that does not exist or is inaccessible"));j(e,a)}async function T(e,t){return/\/\d+\/?$/.test(e.url)?N(t[0]):$(e,t)}async function $(e,t){const{layer:{url:a,customParameters:r,apiKey:o}}=t[0];let s=await e.fetchData("json");s&&null!=s.layers&&null!=s.tables||(s=await x(s,{url:a,customParameters:r,apiKey:o},t.map((e=>e.layer.layerId))));for(const l of t)K(l.layer,l.layerJSON,s);return s}async function x(e,t,a){var r,o;e||(e={}),(r=e).layers||(r.layers=[]),(o=e).tables||(o.tables=[]);const{url:s,customParameters:l,apiKey:i}=t,{serviceJSON:n,layersJSON:p}=await u(s,{customParameters:l,apiKey:i}),c=A(e.layers,n.layers,a),y=A(e.tables,n.tables,a);e.layers=c.itemResources,e.tables=y.itemResources;const d=[...c.added,...y.added],m=p?[...p.layers,...p.tables]:[];return await U(e,d,s,m),e}function A(t,a,r){const o=e(t,a,((e,t)=>e.id===t.id));t=t.filter((e=>!o.removed.some((t=>t.id===e.id))));const s=o.added.map((({id:e})=>({id:e})));return s.forEach((({id:e})=>{t.push({id:e})})),{itemResources:t,added:s.filter((({id:e})=>!r.includes(e)))}}async function U(e,t,a,o){const s=t.map((({id:e})=>new n({url:a,layerId:e,sourceJSON:o.find((({id:t})=>t===e))})));await l(s.map((e=>e.load()))),s.forEach((t=>{const{layerId:a,loaded:o,defaultPopupTemplate:s}=t;if(!o||r(s))return;K(t,{id:a,popupInfo:s.toJSON()},e)}))}function K(e,t,a){e.isTable?F(a.tables,t):F(a.layers,t)}function F(e,t){const a=e.findIndex((({id:e})=>e===t.id));-1===a?e.push(t):e[a]=t}function R(e){const{portalItem:t}=e;return y(e)&&!e.dynamicDataSource&&!!t?.loaded&&t.type===S}async function D(e){if(!e?.length)throw new t("feature-layer-utils-saveall:missing-parameters","'layers' array should contain at least one feature layer");await Promise.all(e.map((e=>e.load())));for(const o of e)if(!R(o))throw new t("feature-layer-utils-saveall:invalid-parameters",`'layers' array should only contain layers or tables in a feature service loaded from 'Feature Service' item. ${g(o,"does not conform")}`,{layer:o});const a=e.map((e=>e.portalItem.id));if(new Set(a).size>1)throw new t("feature-layer-utils-saveall:invalid-parameters","All layers in the 'layers' array should be loaded from the same portal item");const r=e.map((e=>e.layerId));if(new Set(r).size!==r.length)throw new t("feature-layer-utils-saveall:invalid-parameters","'layers' array should contain only one instance each of layer or table in a feature service")}function _(e,t){var a,r;let o=m.from(t);return o.id&&(o=o.clone(),o.id=null),(a=o).type??(a.type=S),(r=o).portal??(r.portal=d.getDefault()),j(e,o),o}async function q(e,t){const{url:a,layerId:r,title:s,fullExtent:l,isTable:i}=e,n=p(a),u=o(n)&&"FeatureServer"===n.serverType;t.url=u?a:`${a}/${r}`,t.title||(t.title=s),t.extent=null,!i&&o(l)&&(t.extent=await v(l)),b(t,h.METADATA),b(t,h.MULTI_LAYER),w(t,h.SINGLE_LAYER),i&&w(t,h.TABLE),O(t)}async function z(e,t,a){const r=e.portal;await r._signIn(),await r.user.addItem({item:e,data:t,folder:a?.folder})}const C=s(M);async function M(e,t){await L(e),E(e);const a=e.portalItem,r=f(a),o=await J(e,r,t),s=await T(a,[{layer:e,layerJSON:o}]);return O(a),await a.update({data:s}),i(r),a}const Y=s((async(e,t)=>{await D(e);const a=e[0].portalItem,r=f(a),o=await Promise.all(e.map((e=>J(e,r,t)))),s=await T(a,e.map(((e,t)=>({layer:e,layerJSON:o[t]}))));return O(a),await a.update({data:s}),await Promise.all(e.slice(1).map((e=>e.portalItem.reload()))),i(r),a.clone()})),B=s(G);async function G(e,t,a){await L(e);const r=_(e,t),o=f(r),s=N({layer:e,layerJSON:await J(e,o,a)});return await q(e,r),await z(r,s,a),e.portalItem=r,i(o),r}export{C as save,Y as saveAll,B as saveAs};