#include <cassert>
#include <fstream>

#include "utils.hpp"
#include "general_dichotomy.hpp"
#include "basesolver.hpp"

#include <iostream>

//----------------------------------------------------------------
void Utils::printCostVec(dichotomy::CostVec& costVec, std::ostream& os) {

    os << "[";
    for(size_t i = 0; i < costVec.size(); i ++) {
        os << costVec[i];
        if(i < costVec.size()-1) {
            os << ",";
        }
    }
    os << "]";

}



//----------------------------------------------------------------
void Utils::printWeightVec(dichotomy::WeightVec& weightVec, std::ostream& os) {
    
    for(size_t i = 0; i < weightVec.size(); i ++) {
        os << weightVec[i];
        if(i < weightVec.size()-1) {
            os << ",";
        }
    }

}

//----------------------------------------------------------------
void Utils::printParameters(GeneralDichotomy::Parameters& parameters, std::ostream& os) {
    os << "Parameters: " << std::endl;
    os << "\t-verbose: " << parameters.verbose << std::endl;
    os << "\t-optimization directions: ";
    for(size_t i = 0; i < parameters.directions.size(); i ++) {
        if(parameters.directions[i] == dichotomy::MIN) {
            os << "Min";
        } else {
            os << "Max";
        }
        os << ", ";
    }
    os << std::endl;
    os << "\t-cost scale: " << parameters.cost_scale << std::endl;
    os << "\t-search scheme: ";
    if(parameters.search_scheme == GeneralDichotomy::DIVERSIFICATION) {
        os << "Diversification" << std::endl;
    } else {
        os << "Intensification" << std::endl;
    }
    os << "\t-inital weight: ";
    for(size_t w_ind = 0; w_ind < parameters.initial_weight.size(); w_ind ++) {
        os << parameters.initial_weight[w_ind] << ",";
    }
    os << std::endl;
    os << "\t-max iterations: " << parameters.max_iter << std::endl;
    os << "\t-max depth: " << parameters.max_depth << std::endl;
    os << "\t-backend: " << parameters.backend << std::endl;
    os << "\t-wnorm: " << parameters.wnorm << std::endl;
    os << "\t-export_weight_graph: " << parameters.export_weight_graph << std::endl;
}

//----------------------------------------------------------------
void Utils::exportDecomposition(BaseSolver& solver, dichotomy::Result& result, std::string fname) {

    std::ofstream file(fname);

    // problem size: n variables ?

    // problem size: n objectives
    file << solver.getNObj() << std::endl;

    // pre: no removed extreme weight 

    // n extreme weights
    file << result.weights.size() << std::endl;

    // n solutions
    file << result.solutions.size() << std::endl;

    for(size_t wind = 0; wind < result.weights.size(); wind ++) {

        // weight vector
        for(size_t obj_ind = 0; obj_ind < solver.getNObj(); obj_ind ++) {
            file << result.weights[wind].weight[obj_ind] << " ";
        }

        // solution adjacency
        file << (result.weights[wind].bnd.size() + result.weights[wind].adj.size()) << " ";

        for(auto it = result.weights[wind].bnd.begin(); it != result.weights[wind].bnd.end(); it ++) {
            file << *it << " ";
        }

        for(auto it = result.weights[wind].adj.begin(); it != result.weights[wind].adj.end(); it ++) {
            file << *it << " ";
        }

        file << std::endl;
            
    }

    // weight graph
    if(!result.weightGraph.empty()) {
        for(size_t wind = 0; wind < result.weights.size(); wind ++) {

            // number of neighbours
            file << result.weightGraph[wind].size() << " ";

            // neighbours
            for(auto it = result.weightGraph[wind].begin(); it != result.weightGraph[wind].end(); it ++) {
                file << *it << " ";
            }

            file << std::endl;

        }
    }

    file.close();

}
