/**
 * @since Last modified: 2024/06/11 09:56:25
 * @function deepMerge
 * @description Merge two objects. The key name of Source is allowed to be the Symbol type, and the Symbol key name of the source will be added directly to the target.
 * @param {Object} target  - he original target of the merged.
 * @param {Object} source  - Active merger object.
 * @param {Object} [opt]  - Parameters used by merging objects.
 * @param {boolean} opt.arrAppend=false  - If value is an array,override or push.
 * @param {boolean} opt.propAppend=true  - If target does not have properties,assign or not.
 * @param {boolean} opt.targetClone=false  - Whether to change target,if true means target will not be changed.
 * @returns {Object} - Return the merge object.
 * @see {@link https://codepen.io/axui/pen/bGzWPJE|demo @ codepen}
 * @example
 * let x ={a:'man',b:0,c:[]},b={a:'woman',b:2};
 * ax.deepMerge(x,y);
 * <!--return {a:'woman',b:2,c:[]}-->
 */
'use strict';
import getDataType from './getDataType';
import deepClone from './deepClone';
const deepMerge = (target, source, opt) => {
    let targetType = getDataType(target), sourceType = getDataType(source), options = Object.assign({ arrAppend: false, propAppend: true, targetClone: false, override: 'partial' }, opt), result = options.targetClone ? deepClone(target) : target;
    if (targetType !== 'Object' || sourceType !== 'Object') {
        return result;
    }
    for (let k in source) {
        if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
            let _resultType = getDataType(result[k]), _sourceType = getDataType(source[k]);
            if (_resultType !== _sourceType) {
                if (options.override === 'partial' && result.hasOwnProperty(k) && result[k]?.hasOwnProperty('enable') && typeof source[k] === 'boolean') {
                    if (result[k]?.hasOwnProperty('enable') && typeof source[k] === 'boolean') {
                        result[k].enable = source[k];
                    }
                    else if (source[k]?.hasOwnProperty('enable') && typeof result[k] === 'boolean') {
                        result = Object.assign({ enable: result[k] }, source[k]);
                    }
                    else {
                        result[k] = source[k];
                    }
                }
                else {
                    result[k] = source[k];
                }
            }
            else {
                if (_sourceType === 'Object') {
                    result[k] = deepMerge(result[k], source[k], options);
                }
                else if (_sourceType === 'Array' && options.arrAppend) {
                    result[k].push(...source[k]);
                }
                else {
                    result[k] = source[k];
                }
            }
        }
        else if (source.hasOwnProperty(k) && !result.hasOwnProperty(k) && options.propAppend) {
            result[k] = source[k];
        }
    }
    let symbols = Object.getOwnPropertySymbols(source);
    if (symbols.length > 0) {
        for (let k of symbols) {
            result[k] = source[k];
        }
    }
    return result;
};
export default deepMerge;
