/*-
 * ~~~~~~licensing~~~~~~
 * application-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.integration.applications.shell.application;

import java.util.Comparator;
import java.util.stream.Collectors;

import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import org.apache.karaf.shell.api.action.lifecycle.Service;

import ru.entaxy.esb.resources.EntaxyResource;
import ru.entaxy.esb.resources.EntaxyResourceService;
import ru.entaxy.platform.base.support.karaf.shell.ShellTableFixed;
import ru.entaxy.platform.integration.applications.ApplicationItem;
import ru.entaxy.platform.integration.applications.EntaxyApplication;
import ru.entaxy.platform.integration.applications.EntaxyApplicationRevision;
import ru.entaxy.platform.integration.applications.EntaxyApplicationVersion;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationDescriptor;
import ru.entaxy.platform.integration.applications.descriptor.ApplicationRequirement;
import ru.entaxy.platform.integration.applications.shell.ApplicationShell;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObject;
import ru.entaxy.platform.objects.runtime.EntaxyRuntimeObjectService;

@Service
@Command(name = "app-revision-info", scope = ApplicationShell.COMMAND_SCOPE)
public class RevisionInfoCommand extends RevisionSupport {

    @Reference
    EntaxyRuntimeObjectService entaxyRuntimeObjectService;

    @Reference
    EntaxyResourceService entaxyResourceService;

    @Override
    protected void doExecute(EntaxyApplication application, EntaxyApplicationVersion version,
            EntaxyApplicationRevision revision) {

        System.out.println("");
        // output main revision info
        String data = "Application  : ".concat(application.getName()).concat("\n")
                .concat("Group        : ").concat(version.getDescriptor().group).concat("\n")
                .concat("Version      : ").concat(version.getVersionNumber()).concat("\n")
                .concat("Revision     : ").concat(revision.getRevisionNumber() + "").concat("\n")
                .concat("Status       : ").concat(revision.getStatus().name()).concat("\n")
                .concat("Revisionable : ")
                .concat(revision.getItems().stream().filter(item -> item.isRevisionable()).count() > 0 ? "true"
                        : "false")
                .concat("\n")
                .concat("Editable     : ")
                .concat(revision.getItems().stream().filter(item -> item.isEditable()).count() > 0 ? "true" : "false");
        System.out.println(data);

        // output items
        System.out.println("\n\tITEMS");
        ShellTableFixed itemsTable = new ShellTableFixed();
        itemsTable.column("Id");
        itemsTable.column("Type");
        itemsTable.column("Revisionable").alignCenter();
        itemsTable.column("Editable").alignCenter();

        for (ApplicationItem item : revision.getItems().stream().sorted(new Comparator<ApplicationItem>() {

            @Override
            public int compare(ApplicationItem o1, ApplicationItem o2) {
                return o1.getType().name().compareTo(o2.getType().name());
            }
        }).collect(Collectors.toList())) {

            itemsTable.addRow().addContent(item.getId(), item.getType().name(), item.isRevisionable() ? "*" : "",
                    item.isEditable() ? "*" : "");

        }

        itemsTable.print(System.out);

        // output requirements
        ApplicationDescriptor applicationDescriptor = revision.getDescriptor();
        System.out.println("\n\tREQUIREMENTS");
        ShellTableFixed requirementsTable = new ShellTableFixed();
        requirementsTable.column("Id").colorProvider(ApplicationShell.normalColorProvider);
        requirementsTable.column("Type").colorProvider(ApplicationShell.normalColorProvider);
        requirementsTable.column("Scope").colorProvider(ApplicationShell.normalColorProvider);
        requirementsTable.column("Status").colorProvider(ApplicationShell.requirementStatusColorProvider).alignCenter();

        for (ApplicationRequirement req : applicationDescriptor.requirements) {
            requirementsTable.addRow().addContent(
                    req.id,
                    req.type.name(),
                    req.scope.name(),
                    checkRequirement(req) ? "V" : "X");
        }

        requirementsTable.print(System.out);

        System.out.println("");
    }

    protected boolean checkRequirement(ApplicationRequirement requirement) {
        switch (requirement.type) {
            case OBJECT:
                EntaxyRuntimeObject runtimeObject = entaxyRuntimeObjectService.getRuntimeObject(requirement.id);
                return runtimeObject != null && !runtimeObject.isGhost();
            case RESOURCE:
                EntaxyResource entaxyResource = entaxyResourceService.getResource(requirement.id);
                return entaxyResource.exists();
            case BUNDLE:
            case CONFIG:
                // TODO implement
                return true;
            default:
                return true;
        }
    }
}
