/*************************************************************************
* ADOBE CONFIDENTIAL
* ___________________
*
*  Copyright 2015 Adobe Systems Incorporated
*  All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any.  The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by all applicable intellectual property laws,
* including trade secret and or copyright laws.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
import{dcLocalStorage as e}from"../../../common/local-storage.js";import{loggingApi as s}from"../../../common/loggingApi.js";import{evaluateDefaultValue as t}from"./default-value-evaluator.js";import{PreferenceUtils as n}from"./preference-utils.js";export class StateManager{constructor(){this.changedPreferences=new Map,this.pendingAnalytics=new Map,this.subscribers=new Map,this.changeListeners=[],this.refreshListeners=[],this.optionsPageSource=""}async getValue(s,n){if(!s)return await t(n);for(const[e,t]of this.changedPreferences.entries())if(t.storageKey===s)return t.newValue;const a=e.getItem(s);if(null==a||""===a){const e=await t(n);return e}return a}async getOriginalValue(s,n){if(!s)return await t(n);const a=e.getItem(s);return null==a||""===a?await t(n):a}setValue(s,t){if(!s)return;let n;n=Array.isArray(t)||"object"==typeof t&&null!==t?t:String(t),e.setItem(s,n),this.notifySubscribers(s,n)}markAsChanged(e,s,t,n,a=!1,r=null,i=null,c=null){this.pendingAnalytics.has(e)&&this.pendingAnalytics.delete(e);const o=this.changedPreferences.get(e);if(o){const t=o.oldValue;if(String(n)===String(t))return this.changedPreferences.delete(e),void this.notifyChangeListeners();this.changedPreferences.set(e,{storageKey:s,oldValue:t,newValue:n,requiresReload:a||o.requiresReload,saveCallback:r||o.saveCallback,backgroundPreferencesKey:i||o.backgroundPreferencesKey,analytics:c||o.analytics,timestamp:Date.now()})}else{if(String(n)===String(t))return;this.changedPreferences.set(e,{storageKey:s,oldValue:t,newValue:n,requiresReload:a,saveCallback:r,backgroundPreferencesKey:i,analytics:c,timestamp:Date.now()})}this.notifyChangeListeners()}addPendingAnalytics(e,s){s&&e&&this.pendingAnalytics.set(e,s)}hasChanged(e){return this.changedPreferences.has(e)}getChangedPreferences(){return Array.from(this.changedPreferences.entries()).map(([e,s])=>({id:e,...s}))}clearChanges(){this.changedPreferences.clear(),this.pendingAnalytics.clear(),this.notifyChangeListeners()}setOptionsPageSource(e){this.optionsPageSource=e}getOptionsPageSource(){return this.optionsPageSource}async sendAnalytics(e,s={}){try{const t=await chrome.runtime.sendMessage({main_op:"resolve-analytics-event",eventKey:e});if(t?.eventValue){const e={pageSource:"new_preferences_page",optionsPageSource:this.getOptionsPageSource()||"",...s};chrome.runtime.sendMessage({main_op:"analytics",analytics:[[t.eventValue,e]]})}}catch(e){console.error("Error sending analytics:",e)}}async resolveEventKey(e){if(!e)return null;try{const s=await chrome.runtime.sendMessage({main_op:"resolve-analytics-event",eventKey:e});return s?.eventValue||null}catch(s){return console.error(`Failed to resolve analytics event key: ${e}`,s),null}}async getAnalyticsForChange(e){if(!e.analytics)return null;let s=null,t={pageSource:"new_preferences_page"};const n=this.getOptionsPageSource()||"";if(t.optionsPageSource=n,"string"==typeof e.analytics)s=e.analytics;else if("object"==typeof e.analytics)if(e.analytics.enabled&&e.analytics.disabled)s=!0===e.newValue||"true"===e.newValue?e.analytics.enabled:e.analytics.disabled;else if(e.analytics.event)s=e.analytics.event,e.analytics.params&&(t={...t,...e.analytics.params});else if(e.analytics.params){s=Object.keys(e.analytics).find(e=>"params"!==e),t={...t,...e.analytics.params}}if(!s)return null;const a=await this.resolveEventKey(s);return a?Object.keys(t).length>0?[a,t]:[a]:null}async savePreferences(){const e=this.getChangedPreferences(),t=[],a=[];let r=!1;const i={};for(const s of e)if(s.storageKey){if(s.saveCallback)try{let e,t=[];if("string"==typeof s.saveCallback?e=n[s.saveCallback]:"object"==typeof s.saveCallback&&s.saveCallback.function&&(e=n[s.saveCallback.function],t=s.saveCallback.args||[]),"function"==typeof e){const n=e(this,s.newValue,s.oldValue,...t);n instanceof Promise&&await n}}catch(e){throw e}this.setValue(s.storageKey,s.newValue),s.requiresReload&&(r=!0),s.backgroundPreferencesKey&&(i[s.backgroundPreferencesKey||s.storageKey]=s.newValue);const e=await this.getAnalyticsForChange(s);e&&(t.push(e),a.push(e[0]))}for(const[e,s]of this.pendingAnalytics.entries()){const e=await this.getAnalyticsForChange({analytics:s});e&&(t.push(e),a.push(e[0]))}i.environment&&(chrome.runtime.sendMessage({main_op:"init-floodgate"}),chrome.runtime.sendMessage({main_op:"closeOffscreenDocument"}));const c=e.length;return c>0&&s.info({message:"Options preferences updated",updatedSettingsCount:c,analyticsEvents:a,optionsPageSource:this.getOptionsPageSource()}),new Promise((s,n)=>{chrome.runtime.sendMessage({main_op:"save-preferences",analytics:t,...i},async a=>{a&&a.success?(await new Promise(e=>setTimeout(e,100)),this.clearChanges(),this.notifyRefreshListeners(),s({success:!0,changes:e,analytics:t,requiresReload:r,backgroundPreferences:i})):n(new Error("Failed to save preferences"))})})}subscribe(e,s){this.subscribers.has(e)||this.subscribers.set(e,[]),this.subscribers.get(e).push(s)}unsubscribe(e,s){if(this.subscribers.has(e)){const t=this.subscribers.get(e),n=t.indexOf(s);n>-1&&t.splice(n,1)}}notifySubscribers(e,s){this.subscribers.has(e)&&this.subscribers.get(e).forEach(t=>{try{t(e,s)}catch(e){}})}onChangeUpdated(e){this.changeListeners.push(e)}offChangeUpdated(e){const s=this.changeListeners.indexOf(e);s>-1&&this.changeListeners.splice(s,1)}notifyChangeListeners(){this.changeListeners.forEach(e=>{try{e(this.getChangedPreferences())}catch(e){}})}onRefresh(e){this.refreshListeners.push(e)}offRefresh(e){const s=this.refreshListeners.indexOf(e);s>-1&&this.refreshListeners.splice(s,1)}notifyRefreshListeners(){this.refreshListeners.forEach(e=>{try{e()}catch(e){console.error("Error in refresh listener:",e)}})}async resetToDefaults(e){if(!e||!e.tabs)return;const s=[];e.tabs.forEach(e=>{e.sections&&e.sections.forEach(e=>{e.controls&&e.controls.forEach(e=>{if(e.storageKey&&void 0!==e.defaultValue){const n=t(e.defaultValue).then(s=>{this.setValue(e.storageKey,s)});s.push(n)}})})}),await Promise.all(s),this.clearChanges()}}