//
// Created by bastian on 08.03.22.
//

#include "WeightedRandomNode.h"

WeightedRandomNode::WeightedRandomNode(const std::string &name, const NodeConfiguration &config)
        : ControlNode::ControlNode(name, config), selected_child_index(0), select_next(true) {
    setRegistrationID("Sequence");
}

void WeightedRandomNode::halt() {
    select_next = true;
    ControlNode::halt();
}

NodeStatus WeightedRandomNode::tick() {
    if (select_next) {
        size_t children_count = children_nodes_.size();

        std::string weightString;

        if(!getInput<std::string>("weights",weightString)){
            std::cout<< "Weights are REQUIRED." <<std::endl;
            return NodeStatus::FAILURE;
        }

        std::regex rgx(",");
        std::sregex_token_iterator iter(weightString.begin(),
                                        weightString.end(),
                                        rgx,
                                        -1);
        std::sregex_token_iterator end;
        std::vector<double> weights;
        double sum = 0;
        unsigned long i=0;
        for (; iter != end; ++iter) {
            sum+=stod(*iter);
            weights.push_back(sum);
            i++;
        }

        if(weights.size()!=children_count){
            return NodeStatus::FAILURE;
        }

        std::uniform_real_distribution<double> randomRange(0, sum);
        double random = randomRange(rng);

        i=0;
        while (i<weights.size() && random>weights[i]){
            i++;
        }

        selected_child_index = i;
        
        std::cout<< "Selected child:" << selected_child_index <<std::endl;
        
        select_next = false;
    }

    TreeNode *current_child_node = children_nodes_[selected_child_index];
    NodeStatus child_status = current_child_node->executeTick();
    
    if (child_status != NodeStatus::RUNNING) {
        select_next = true;
        resetChildren();
    }

    return child_status;
}

PortsList WeightedRandomNode::providedPorts() {
    return { InputPort<std::string>("weights") };
}
