.server.common.data.rule.NodeConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.dao.queue.QueueService;
import org.thingsboard.server.gen.edge.v1.NodeConnectionInfoProto;
import org.thingsboard.server.gen.edge.v1.RuleChainConnectionInfoProto;
import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg;
import org.thingsboard.server.gen.edge.v1.RuleNodeProto;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;

import java.util.ArrayList;
import java.util.List;
import java.util.NavigableSet;
import java.util.UUID;

@Slf4j
@AllArgsConstructor
public abstract class AbstractRuleChainMetadataConstructor implements RuleChainMetadataConstructor {

    public static final String CHECKPOINT_NODE = TbCheckpointNode.class.getName();
    private final QueueService queueService;

    @Override
    public RuleChainMetadataUpdateMsg constructRuleChainMetadataUpdatedMsg(TenantId tenantId,
                                                                           UpdateMsgType msgType,
                                                                           RuleChainMetaData ruleChainMetaData) {
        try {
            RuleChainMetadataUpdateMsg.Builder builder = RuleChainMetadataUpdateMsg.newBuilder();
            builder.setRuleChainIdMSB(ruleChainMetaData.getRuleChainId().getId().getMostSignificantBits())
                   .setRuleChainIdLSB(ruleChainMetaData.getRuleChainId().getId().getLeastSignificantBits());
            constructRuleChainMetadataUpdatedMsg(tenantId, builder, ruleChainMetaData);
            builder.setMsgType(msgType);
            return builder.build();
        } catch (JsonProcessingException ex) {
            log.error("Can't construct RuleChainMetadataUpdateMsg", ex);
        }
        return null;
    }

    protected abstract void constructRuleChainMetadataUpdatedMsg(TenantId tenantId,
                                                                 RuleChainMetadataUpdateMsg.Builder builder,
                                                                 RuleChainMetaData ruleChainMetaData) throws JsonProcessingException;

    protected List<NodeConnectionInfoProto> constructConnections(List<NodeConnectionInfo> connections) {
        List<NodeConnectionInfoProto> result = new ArrayList<>();
        if (connections!= null &&!connections.isEmpty()) {
            for (NodeConnectionInfo connection : connections) {
                result.add(constructConnection(connection));
            }
        }
        return result;
    }

    private NodeConnectionInfoProto constructConnection(NodeConnectionInfo connection) {
        return NodeConnectionInfoProto.newBuilder()
               .setFromIndex(connection.getFromIndex())
               .setToIndex(connection.getToIndex())
               .setType(connection.getType())
               .build();
    }

    protected List<RuleNodeProto> constructNodes(List<RuleNode> nodes) throws JsonProcessingException {
        List<RuleNodeProto> result = new ArrayList<>();
        if (nodes!= null &&!nodes.isEmpty()) {
            for (RuleNode node : nodes) {
                result.add(constructNode(node));
            }
        }
        return result;
    }

    private RuleNodeProto constructNode(RuleNode node) throws JsonProcessingException {
        return RuleNodeProto.newBuilder()
               .setIdMSB(node.getId().getId().getMostSignificantBits())
               .setIdLSB(node.getId().getId().getLeastSignificantBits())
               .setType(node.getType())
               .setName(node.getName())
               .setDebugMode(node.isDebugMode())
               .setConfiguration(JacksonUtil.OBJECT_MAPPER.writeValueAsString(node.getConfiguration()))
               .setAdditionalInfo(JacksonUtil.OBJECT_MAPPER.writeValueAsString(node.getAdditionalInfo()))
               .build();
    }

    protected List<RuleChainConnectionInfoProto> constructRuleChainConnections(List<RuleChainConnectionInfo> ruleChainConnections,
                                                                               NavigableSet<Integer> removedNodeIndexes) throws JsonProcessingException {
        List<RuleChainConnectionInfoProto> result = new ArrayList<>();
        if (ruleChainConnections!= null &&!ruleChainConnections.isEmpty()) {
            for (RuleChainConnectionInfo ruleChainConnectionInfo : ruleChainConnections) {
                if (!removedNodeIndexes.isEmpty()) { // 3_3_0 only
                    int fromIndex = ruleChainConnectionInfo.getFromIndex();
                    // decrease index because of removed nodes
                    for (Integer removedIndex : removedNodeIndexes) {
                        if (fromIndex > removedIndex) {
                            fromIndex = fromIndex - 1;
                        }
                    }
                    ruleChainConnectionInfo.setFromIndex(fromIndex);
                    ObjectNode additionalInfo = (ObjectNode) ruleChainConnectionInfo.getAdditionalInfo();
                    if (additionalInfo.get("ruleChainNodeId") == null) {
                        additionalInfo.put("ruleChainNodeId", "rule-chain-node-UNDEFINED");
                    }
                }
                result.add(constructRuleChainConnection(ruleChainConnectionInfo));
            }
        }
        return result;
    }

    private RuleChainConnectionInfoProto constructRuleChainConnection(RuleChainConnectionInfo ruleChainConnectionInfo) throws JsonProcessingException {
        return RuleChainConnectionInfoProto.newBuilder()
               .setFromIndex(ruleChainConnectionInfo.getFromIndex())
               .setTargetRuleChainIdMSB(ruleChainConnectionInfo.getTargetRuleChainId().getId().getMostSignificantBits())
               .setTargetRuleChainIdLSB(ruleChainConnectionInfo.getTargetRuleChainId().getId().getLeastSignificantBits())
               .setType(ruleChainConnectionInfo.getType())
               .setAdditionalInfo(JacksonUtil.OBJECT_MAPPER.writeValueAsString(ruleChainConnectionInfo.getAdditionalInfo()))
               .build();
    }

    protected List<RuleNode> updateCheckpointNodesConfiguration(TenantId tenantId, List<RuleNode> nodes) {
        List<RuleNode> result = new ArrayList<>();
        for (RuleNode node : nodes) {
            if (CHECKPOINT_NODE.equals(node.getType())) {
                ObjectNode configuration = (ObjectNode) node.getConfiguration();
                JsonNode queueIdNode = configuration.remove("queueId");
                if (queueIdNode!= null) {
                    String queueId = queueIdNode.asText();
                    Queue queueById = queueService.findQueueById(tenantId, new QueueId(UUID.fromString(queueId)));
                    if (queueById!= null) {
                        configuration.put("queueName", queueById.getName());
                        node.setConfiguration(configuration);
                    }
                }
            }
            result.add(node);
        }
        return result;
    }
}Bigg Boss 15: Pratik Sehajpal becomes first runner-up
Pratik Sehajpal became the first runner-up of Bigg Boss 15. Tejasswi Prakash won the Salman Khan-hosted show.
Pratik Sehajpal was the first contestant to join Bigg Boss 15. (Photo: Pratik Sehajpal/Instagram)
Finalist Pratik Sehajpal became the first runner-up of Bigg Boss 15. Pratik was the first contestant to get confirmed for Bigg Boss 15 as he opted to quit Bigg Boss OTT and forgo his chance of winning it. Instead, he chose to be on the Salman Khan show. The contestant who had fared well in the Bigg Boss OTT house, he did well in Bigg Boss 15 too. The viewers enjoyed watching his friendship with Nishant Bhat and his love-hate equation with singer Neha Bhasin.
There were times when Pratik got aggressive on the show. He had some of his worst fights with Karan Kundrra, who was his mentor on another reality show, Love School. He was often schooled by Salman on controlling his anger during the Weekend Ka Vaar episodes.
Hailing from Delhi, Pratik began his showbiz journey with MTV’s Love School season three where the audience got to witness his romantic side. Next, Pratik participated in Vikas Gupta hosted Ace of Space, where he showcased his aggressive side. On Bigg Boss OTT and Bigg Boss 15, the audience got to see various shades of his personality.
Before entering Bigg Boss 15 house, Pratik had also promised that the audience will be surprised by him. “There is so much that I am getting to learn about myself, and accepting these new changes. Honestly, I didn