/*-
 * ~~~~~~licensing~~~~~~
 * test-producers
 * ==========
 * 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.executor.generationmodel;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.google.gson.Gson;

import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;

public class ResolveRefTask extends AbstractRefTask {

    protected ResolveRefTask(FactoredObjectRef objectRef) {
        super(objectRef);
    }

    @Override
    public String getInfo() {
        return "RESOLVE-REF "
                + "["
                + objectRef.definedIn.getObjectId()
                + "] -> "
                + "["
                + objectRef.getTargetId()
                + "]";
        // + objectRef.factoryId;
    }

    @Override
    public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
            EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
        GenerationModel generationModel = currentResult.findResultObject(GenerationModel.class);
        String fieldName = objectRef.getOrDefault(FIELDS.REF_FIELD, FIELDS.OBJECT_ID).toString();
        printOutput("RESOLVING REF TO FIELD [" + fieldName + "]");
        List<AbstractTask> generateTasks = generationModel.tasks.stream()
                .filter(t -> (t instanceof GenerateTask))
                .map(t -> (GenerateTask) t)
                .filter(t -> t.origin == objectRef.getTargetObject())
                .collect(Collectors.toList());
        if (generateTasks.size() == 0)
            generateTasks = generationModel.tasks.stream()
                    .filter(t -> (t instanceof ResolveObjectTask))
                    .map(t -> (ResolveObjectTask) t)
                    .filter(t -> t.origin == objectRef.getTargetObject())
                    .collect(Collectors.toList());
        if (generateTasks.size() == 0) {
            printOutput("None of GenerateTask or ResolveObjectTask found for [" + objectRef.getTargetId() + "/"
                    + objectRef.getTargetObject().getObjectType() + "]");
            return false;
        }
        AbstractTask provider = generateTasks.get(0);
        Object value = null;
        if (provider instanceof GenerateTask) {
            GenerateTask generateTask = (GenerateTask) provider;
            if (GenerateTask.CONTENT_FIELD.equals(fieldName)) {
                Object val = generateTask.getGeneratedResult().getObject();
                if (val != null)
                    value = val.toString();
                else
                    value = "";
            } else {
                value = generateTask.generationProperties.getOrDefault(fieldName, null);
                if (value == null)
                    value = generateTask.getGeneratedResult().getProperties().getOrDefault(fieldName, "");
            }
        } else if (provider instanceof ResolveObjectTask) {
            ResolveObjectTask task = (ResolveObjectTask) provider;
            value = ObjectResolveHelper.getInstance().resolve(task.targetObject, fieldName);
            if (value == null)
                value = "";
        }
        printOutput("RESOLVED REF TO FIELD [" + fieldName + "] to VALUE [" + value.toString() + "]");
        printOutput("REPLACE: [" + objectRef.origin.toString() + "] in PATH ["
                + objectRef.relativePath + "] in OBJECT "
                + objectRef.definedIn.origin.toString());
        JSONUtils.setValue(objectRef.definedIn.origin,
                GenerationModel.UNRESOLVED_CONTAINER_NAME + "." + objectRef.relativePath, objectRef.origin, false,
                true);
        JSONUtils.replaceValue(objectRef.definedIn.origin, objectRef.relativePath, (new Gson()).toJsonTree(value));
        printOutput("AFTER REPLACEMENT: [" + objectRef.definedIn.origin.toString() + "]");
        return true;
    }

    @Override
    public boolean isFinal() {
        return false;
    }

}
