/*-
 * ~~~~~~licensing~~~~~~
 * object-producer-core
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.platform.core.producer.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import ru.entaxy.platform.base.objects.factory.EntaxyFactory.CONFIGURATION.DIRECTIVES.OVERRIDE_MODE;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;

public class InstructionsHelper {

    public static final String DEFAULT_INSTRUCTIONS = "{'validate':{}}";
    public static final String LIFECYCLE_DIRECTIVE = EntaxyProducerService.DIRECTIVES.LIFECYCLE;

    protected JsonObject lifecyclesOrigin;

    protected Map<String, JsonObject> lifecycles = new HashMap<>();

    protected Map<String, JsonObject> lifecycleExtensions = new HashMap<>();

    protected Object lifecycleExtensionsLock = new Object();

    public InstructionsHelper(JsonObject lifecycles) {
        super();
        this.lifecyclesOrigin = lifecycles.deepCopy();
        fillMap(this.lifecyclesOrigin);
    }

    protected void fillMap(JsonObject origin) {
        for (Entry<String, JsonElement> entry : origin.entrySet())
            if (entry.getValue().isJsonObject())
                this.lifecycles.put(entry.getKey(), entry.getValue().getAsJsonObject().deepCopy());
    }

    public String prepareInstructions(String originalInstructions) {
        JsonObject origin = JSONUtils.getJsonRootObject(originalInstructions);
        JsonObject result = new JsonObject();
        if (origin.has(LIFECYCLE_DIRECTIVE)) {
            JsonElement directiveValue = origin.get(LIFECYCLE_DIRECTIVE);
            List<String> lcIdToApply = new ArrayList<>();
            List<JsonObject> lcToApply = new ArrayList<>();
            if (directiveValue.isJsonPrimitive())
                lcIdToApply.add(directiveValue.getAsString());
            if (directiveValue.isJsonArray()) {
                JsonArray ja = directiveValue.getAsJsonArray();
                for (int i = 0; i < ja.size(); i++)
                    lcIdToApply.add(ja.get(i).getAsString());
            }
            origin.remove(LIFECYCLE_DIRECTIVE);
            for (String id : lcIdToApply)
                if (this.lifecycles.containsKey(id)) {
                    EntaxyFactoryUtils.processObjectOverriding(
                            result, this.lifecycles.get(id), OVERRIDE_MODE.UPDATE);
                    synchronized (lifecycleExtensionsLock) {
                        if (lifecycleExtensions.containsKey(id))
                            EntaxyFactoryUtils.processObjectOverriding(result, this.lifecycleExtensions.get(id),
                                    OVERRIDE_MODE.UPDATE);
                    }
                }
        }
        EntaxyFactoryUtils.processObjectOverriding(
                result, origin, OVERRIDE_MODE.UPDATE);
        return result.toString();
    }

    public void setLifecycleExtensions(Map<String, Map<String, Map<String, Object>>> lcExtensions) {
        synchronized (lifecycleExtensionsLock) {
            this.lifecycleExtensions = new HashMap<>();
            for (String lc : lcExtensions.keySet()) {
                Map<String, Map<String, Object>> lcContent = lcExtensions.get(lc);

                JsonObject jo =
                        lcContent == null ? new JsonObject() : JSONUtils.GSON.toJsonTree(lcContent).getAsJsonObject();

                this.lifecycleExtensions.put(lc, jo);
            }
        }
    }

}
