// SL_Partition.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <time.h>


using namespace std;

#include <sstream>

#include "../../Kernel/kernelincludes.h"

void Help()
{
		cerr << "Syntax: SL_Partition [-name] source.pla groupfile.dat" << endl;
		cerr << "          If -name option is specified, names are expected in groupfile, instead of ordinary numbers" << endl;
}

bool IsInGroup( list<unsigned int> &group, unsigned int val ) 
{
	list<unsigned int>::iterator groupit;

	for ( groupit = group.begin(); groupit != group.end(); groupit++ )
		if ( (*groupit) == val ) return true;
	return false;
}

int main(int argc, char* argv[])
{
    PLA source;
	PLA *dest;
	list< list<unsigned int> > grouping;
	list< list<unsigned int> >::iterator grit;
	list<unsigned int>::iterator groupit;
	unsigned int i;
	unsigned int j, gr;
	int i1;
	ifstream groupfile;
	list<unsigned int> group;
	char line[1000];
	stringstream ss;
	unsigned int groups;
	string name, allname, destname;
	Term *t;
	list<Term>::iterator ti;
	bool named = false;
	string s;
	
	srand( (unsigned)time( NULL ) );
	
	cerr << "SL_Partition 1.0, (c) December 2009 by Petr Fiser" << endl << endl;
    if ( argc < 3 ) {
		Help();
		exit(1);
    }

	i = 1;
	if ( strcmp(argv[1], "-name") == 0 ) {
		named = true;
		i++;
	}

	try {
        source.LoadPLA(argv[i]);
    } catch (IOException e) {
            cerr << e.GetMsg() << endl;
            exit(1);
    }

		// extract the name
	allname = argv[i];
	name = allname.substr(0, allname.find_last_of('.'));

		// read grouping file
	groupfile.open(argv[i+1]);
	while ( !groupfile.eof() ) {
		groupfile.getline( line, 1000 );
		if ( line[0] == 0 ) break;
		ss.clear();
		ss << line;
		group.clear();
		while ( !ss.eof() ) {
			if ( !named ) 
				ss >> i1;
			else {
				ss >> s;
				i1 = source.FindOName(s);
				if ( i1 == -1 ) throw RuntimeException( "SL_Partition: output name not found" );
			}
			group.push_back(i1);
		}
		grouping.push_back(group);
	}
	groupfile.close();
	groups = grouping.size();

	gr = 0;
	for ( grit = grouping.begin(); grit != grouping.end(); grit++ ) {
		dest = new PLA( source.inputs(), (*grit).size(), source.getType() );
		for ( ti = source.getData()->begin(); ti != source.getData()->end(); ti++ ) {
			t = new Term( source.inputs(), (*grit).size() );
			t->setCube( (*ti).getCube() );
			j = 0;
			for ( i = 0; i < source.outputs(); i++ )
				if ( IsInGroup( *grit, i ) )
					t->setOM(j++, (*ti).getOM(i) );
			for ( i = 0; i < t->outputs(); i++ )
				if ( !t->isOM_undef(i) ) break;
			if ( i != t->outputs() ) dest->AppendTerm(*t);
			delete t;
		}
		if ( !source.emptyNames() ) {
			for ( i = 0; i < source.inputs(); i++ )
				dest->setIName( i, source.getIName(i) );
			j = 0;
			for ( i = 0; i < source.outputs(); i++ )
				if ( IsInGroup( *grit, i ) ) dest->setOName( j++, source.getOName(i) );
		}
		ss.clear();
		ss << name << "_" << gr++ << ".pla";
		ss >> destname;
		dest->SavePLA(destname.c_str());
		delete dest;
	}
    return 0;
}

