#include <iostream>
#include <cctype>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iomanip>

#include "functionInst.h"
#include "functionUser.h"
#include "parserVar.h"
#include "graph.h"

extern bool verbose;

bool setting_file::init_settings (functionUser *fun) {
    repeat = 0; // initialization
	if(verbose)cout << endl << "---------- Input variables ----------" << endl << endl;
    //string filename = "settings.net";
    s.open(name.c_str(),ios::in);
    if (s) {
        string line,namevar;
        //getline(s,line);
        //nb_cycles = atoi((line.substr (7)).c_str()) ;   //supposed to set the number of cycles, useless since Fabrice's update
		//getline(s,line);
		//getline(s,line);
		//getline(s,line);
		getline(s,line);

        istringstream aliasline (line);
        while(aliasline >> namevar) {
            //cout << "Defined input variable : " << namevar << endl;
            if(namevar=="0"){
            	cerr << "Settings parser ERROR : \"" << namevar << "\" is a keyword." << endl;
            	return false;
            }
            if(namevar=="1"){
            	cerr << "Settings parser ERROR : \"" << namevar << "\" is a keyword." << endl;
            	return false;
            }
            variable *var = fun->GetVariable(namevar, false);
            if(!var){
            	cerr << "Settings parser ERROR : variable \"" << namevar << "\" does not exist." << endl;
            	return false;
            }
            if(find(variables.begin(),variables.end(),var)!=variables.end()){
            	cerr << "Settings parser ERROR : variable \"" << var->GetName() << "\" is duplicated." << endl;
            	return false;
            }
            variables.push_back (var);
        }
		//cout << "The behaviour of those variables is dictated by settings.net unless they are overwritten by functions" << endl;
        //pos = s.tellg();

        string printInputs;
        string printOthers;
        short definedOthers=0;
        short definedInputs=0;

        for(vector<variable *>::iterator it=variables.begin();it!=variables.end();it++){
			if(fun->IsInput(*it)){
				if(printInputs!="")printInputs+=", ";
				printInputs+=(*it)->GetName();
				definedInputs++;
			}else{
				if(printOthers!="")printOthers+=", ";
				printOthers+=(*it)->GetName();
				definedOthers++;
			}
        }

		if(definedInputs){
			if(verbose)cout << "Define " << definedInputs << "/" << fun->GetNumberOfInputs() << " inputs : " << endl;
			if(verbose)cout << "    " << printInputs << endl;
			if(definedInputs != fun->GetNumberOfInputs()){
				cout << "Settings parser WARNING : some inputs are not defined." << endl;
			}
		}else if(fun->GetNumberOfInputs()){
			cout << "Settings parser WARNING : no input is defined." << endl;
		}

        if(definedOthers){
			cout << endl;
			if(verbose)cout << "Define " << definedOthers << " non-input variables : " << endl;
			if(verbose)cout << "    " << printOthers << endl;
			cout << "Settings parser WARNING : this feature should be used only for debugging." << endl;
        }

		return true;
    } else {
        cerr << "Settings parser ERROR : unable to read the settings file." << endl;
        return false;
    }
}


bool setting_file::forced_var () {
    //string filename = "settings.net";
    int value;
    //ifstream s(filename.c_str(),ios::in);
    if (s) {
        string line;
        //s.seekg (pos);
        int npos = s.tellg();

        getline(s,line);

        if(!s)return false;

        istringstream aliasline (line);
        int i=0;
        while(aliasline >> value) {
            variable *var = variables[i];
            (*var).SetValue(value != 0);
            //cout << (*var).GetName() << ":" << (*var).GetValue() << endl;;
            i++;
        }

        char c;
        c = s.get();
            //cout <<c << ":" << repeat << endl;
        if (c == '*') {
            //cout << "skip" << endl;
            getline(s,line);
            if (repeat == 0) {
                int nbrepeat;
                istringstream aliasline (line,istringstream::in);
                aliasline >> nbrepeat;
                repeat = nbrepeat;
                if(repeat<=0){
                	cerr << "    Settings parser ERROR : *n instruction with n<=0." << endl;
                	return false;
                }
            }
			repeat --;
			if(repeat>0){
                s.seekg (npos);
            }
        }
        else {
            //pos = npos;
            s.unget();
        }
    } else {
        //cout << "    Settings parser ERROR : unable to read the settings file" << endl;
        return false;
    }

    return true;
}



