/*-
 * ~~~~~~licensing~~~~~~
 * object-runtime-shell
 * ==========
 * 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.objects.runtime.shell;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.support.table.ShellTable;

import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.base.support.karaf.shell.ShellTableExt;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectContainer;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectResource;

@Service
@Command(name = "object-info", scope = EntaxyRuntimeObjectServiceSupport.OBJECTS_SCOPE, description = "Get object info")
public class ObjectInfo extends RuntimeObjectAwareCommand {

    @Override
    public Object doExecute(EntaxyRuntimeObject entaxyObject) throws Exception {

        EntaxyRuntimeObjectContainer container = entaxyObject.getContainer();

        String message = "Object Info for ".concat(entaxyObject.getObjectFullId())
                .concat("\n----------------------------------------")
                .concat("\nID: ".concat(entaxyObject.getId()))
                .concat("\nTYPE: ".concat(entaxyObject.getType()))
                .concat("\nFULL ID: ".concat(entaxyObject.getObjectFullId()))
                .concat("\nFACTORY ID: ".concat(entaxyObject.getFactoryId()))
                .concat("\nCONTAINER: ".concat(RuntimeObjectShellUtils.getContainerPrintString(container)))
                .concat("\nBUNDLE ID: ".concat(entaxyObject.getBundleInfo().getBundleId() + ""))
                .concat("\nCOLOCATED WITH OBJECTS: ")
                .concat(
                        container.getObjects().stream()
                                .filter(obj -> !obj.getObjectFullId().equals(entaxyObject.getObjectFullId()))
                                .map(obj -> ("\n\t" + obj.getObjectFullId()))
                                .collect(Collectors.joining())
                                .concat("\nPARENT OBJECTS: ")
                                .concat(
                                        RuntimeObjectShellUtils.getRelationListMainPrintString(
                                                entaxyObject.getIncomiingSubordRelations(), "\n\t"))
                                .concat("\nDEPENDENCIES: ")
                                .concat(
                                        RuntimeObjectShellUtils.getRelationListMainPrintString(
                                                RuntimeObjectShellUtils.getObjectDependenciesAndUses(entaxyObject),
                                                "\n\t")))
                .concat("\nCHILD OBJECTS: ")
                .concat(
                        RuntimeObjectShellUtils.getRelationListDependentPrintString(
                                entaxyObject.getSubordRelations(), "\n\t"))
                .concat("\nDEPENDENTS: ")
                .concat(
                        RuntimeObjectShellUtils.getRelationListDependentPrintString(
                                RuntimeObjectShellUtils.getObjectIncomingDependenciesAndUses(entaxyObject), "\n\t"));

        // object resources
        ShellTable table = new ShellTable();
        table.column("Scope");
        table.column("Exists");
        table.column("Url");

        for (EntaxyRuntimeObjectResource res : entaxyObject.getResources())
            table.addRow().addContent(
                    res.getScope().name(),
                    (res.getResource() == null ? "" : (res.getResource().exists() ? "*" : "")),
                    res.getResourceUrl());

        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                PrintStream printStream = new PrintStream(outputStream)) {

            table.print(printStream);
            message = message.concat("\nRESOURCES: \n").concat(outputStream.toString());
        }

        ShellTableExt tableExt = new ShellTableExt();
        tableExt.column("Attribute");
        tableExt.column("Value").maxSize(70);

        for (Map.Entry<String, Object> entry : entaxyObject.getAllAttributes().entrySet()) {

            String toOutput = "";

            if (entry.getValue() != null) {
                if (entry.getValue() instanceof List)
                    toOutput = ((List) entry.getValue())
                            .stream().map(v -> v == null ? "" : v.toString())
                            .collect(Collectors.joining("\n")).toString();
                else if (entry.getValue() instanceof Map) {
                    toOutput = JSONUtils.GSON.toJsonTree((Map) entry.getValue()).toString();
                } else {
                    toOutput = entry.getValue().toString();
                }
            }

            tableExt.addRow().addContent(entry.getKey(), toOutput);

        }

        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                PrintStream printStream = new PrintStream(outputStream)) {

            tableExt.print(printStream);
            message = message.concat("\nATTRIBUTES: \n").concat(outputStream.toString());
        }


        // output to console
        System.out.println(message);

        return null;
    }

}
