/**  
 * @since Last modified: 2024/06/20 21:06:09
 * @class PubUpdate
 * @description Public methods, only the methods about save and update, can be extended.
 * @example
 * class Demo extends pipe(PubUpdate)(PubBase) {};
 */

import { T_fn_none, T_obj } from '../../../types/ax';
import breakpoints from '../utils/breakpoints';
import deepClone from '../utils/deepClone';
import deepMerge from '../utils/deepMerge';
import extend from '../utils/extend';
import isEmpty from '../utils/isEmpty';
import spreadBool from '../utils/spreadBool';
import storage from '../utils/storage';
import Observe from './Observe';
const PubUpdate = (parent: any) => {
    return class extends (parent || class Empty { }) {
        
        storKeys: string[] = [];
        storObs: any;
        storTmp: any;
        
        
        /**
        * @function PubUpdate.createProxy
        * @description Detect data change, automatically save parameters.
        * @returns null
        */
        
        createProxy(): any {
            /**
             * @name PubUpdate.storTmp
             * @description Cache object.The "updateCache" method will update the variable.
             * @type object
             */
            
            this.storTmp = {}
            /**
            * @name PubUpdate.storObs
            * @description Cache listener(proxy) that listens for "storTmp" changes and automatically updates the local storage.
            * @type any
            */
            
            this.storObs = new Observe(this.storTmp);
        }

        /**
         * @function PubUpdate.clearCache
         * @description Clean up local storage data.
         * @returns null
         */
        
        clearCache(cb?: T_fn_none) {
            if (this.options.storName) {
                
                for (let k in this.storObs.proxy) {
                    Reflect.deleteProperty(this.storObs.proxy, k);
                }
                
                this.listen && this.listen({ name: 'clearCache', cb });
            }
            
            this.save();
            return this;
        }
        /**
         * @function PubUpdate.updateCache
        * @description Update local storage data.
         * @param {object} value - The value to be updated.
        * @returns null
        */
        
        updateCache(value: T_obj) {
            if (this.options.storName && !isEmpty(value)) {
                
                let temp: T_obj = {};
                for (let k in value) {
                    value.hasOwnProperty(k) && this.storKeys.includes(k) ? temp[k] = value[k] : null;
                }
                
                deepMerge(this.storObs.proxy, temp, {
                    
                    
                });
            }
            
            this.save();
            return this;
        }


        /**
         * @function PubUpdate.optsMergeStorage
         * @description Merge options with local storage.
         * @returns null
         */
        
        optsMergeStorage() {
            
            if (this.options.storName) {
                
                let storageVal = storage.get(this.options.storName);
                if (!isEmpty(storageVal)) {
                    
                    this.updateCache(storageVal);
                    
                    extend({target:this.options, source:storageVal});
                } else {
                    
                    this.clearCache();
                }
            }
        }


        /**
         * @function PubUpdate.save
        * @description Storing settings locally.
        * @param {fn_cb_options} [cb] - Call back after save settings.
        * @returns {*} Return the instance itself
        */
        
        save(cb?: Function): any {
            
            if (this.destroyed || !this.options.storName) {
                return this;
            }
            
            let value = !isEmpty(this.storTmp) ? deepClone(this.storTmp) : {};
            storage.set(this.options.storName, value); 
            this.listen && this.listen({ name: 'save', cb, params: [value] });
            return this;
        }





    }
}
export default PubUpdate;
