// Dump the mapping table.

#include <fstream>
#include <iostream>
#include <iomanip>
#include <map>
#include <algorithm>
#include "globaldef.h"
#include "messages_manager.h"
#include "tags.h"

#ifdef _USE_NAMESPACES
    namespace Else { 
#endif // _USE_NAMESPACES

typedef multimap<ContractedTag, pair<Natural, AlternatedTagsSet> > Map;

conform_string strMap1, strMap2;
Map map1, map2;

void dumpHelp();
void checkParams(Parameters&);
void readMap(const string& file, Map& map);
void dumpMap(const Map& map);
int  main(int argc, char* argv[]);

void dumpHelp()
{
    cerr << "Read 2 map file, and give difference.\n"
            "\n"
            "Usage: cmp_map <map1> <map2>\n"
            "  <mapx>   : Format: <entryTag> <mappedTag>|<mappedTag>...\n";
	msg.switchesFormat(cerr);
	cerr << endl;
    exit (0);
}

void checkParams(Parameters& params)
{
    if ((params.size() < 2)
        ||
           !(strcmp(params.front(), "?"))
        ||
           !(strcmp(params.front(), "-?"))
        || 
           !(strcmp(params.front(), "-h"))
        ||
           !(strcmp(params.front(), "-help"))
        ||
           !(strcmp(params.front(), "--help"))
       ) dumpHelp();

    strMap1 = params.front(); params.erase(params.begin());
    strMap2 = params.front(); params.erase(params.begin());
   	msg.checkParams(params);
}

void readMap(const string& file, Map& map)
{
	map.clear();
	ifstream in(file.c_str(), ios::in);
	Natural line(0);
	AtomicTag entry,exit; 

	while (in) {
		while (in.peek()=='#') { in.ignore(SKIP_UNTIL_EOF, '\n'); ++line; }
		in >> entry;
		in >> ws;
		in >> exit;
		in.ignore(SKIP_UNTIL_EOF, '\n');
		map.insert(make_pair(ContractedTag(entry), make_pair(++line, AlternatedTagsSet(exit))));
	}
	in.close();
}

void dumpMap(const Map& map)
{
	for (Map::const_iterator i(map.begin()); i != map.end(); ++i)
		cout << i->first.str() << " (" << i->second.first << ") -> " << i->second.second.str() << '\n';
}		
	

int main(int argc, char* argv[]) {
    Parameters params(argc, argv);
    checkParams(params);
    readMap(strMap1, map1);
    readMap(strMap2, map2);
    Natural len(max(strMap1.size(), strMap2.size()));
    if (len > 15) {
    	strMap1 = "file1";
    	strMap2 = "file2";
    	len = 5;
    }
    cout.setf(ios::left,ios::adjustfield);

    for (Map::iterator i(map1.begin()); i != map1.end(); ) {
    	Map::iterator j(map2.find(i->first));    	
    	if (j != map2.end()) {
    		if (i->second.second != j->second.second)
    			cout << setw(len) << strMap1.c_str() << " at " << i->second.first << ": " << i->first.str() << " -> " << i->second.second.str() << '\n'
    			     << setw(len) << strMap2.c_str() << " at " << j->second.first << ": " << j->first.str() << " -> " << j->second.second.str() << '\n'
    			     << '\n';
    		map2.erase(j);
    		j = i;
    		++i;
    		map1.erase(j);
    	} else ++i;
    }
    if (!map1.empty()) {
    	cout << "\nMissed in " << strMap2 << ":\n";
    	for (Map::const_iterator i(map1.begin()); i!= map1.end(); ++i)
    		cout << setw(len) << strMap1.c_str() << " at " << i->second.first << ": " << i->first.str() << " -> " << i->second.second.str() << '\n';
    }
    if (!map2.empty()) {
    	cout << "\nMissed in " << strMap1 << ":\n";
    	for (Map::const_iterator i(map2.begin()); i!= map2.end(); ++i)
    		cout << setw(len) << strMap2.c_str() << " at " << i->second.first << ": " << i->first.str() << " -> " << i->second.second.str() << '\n';
    }
}

#ifdef _USE_NAMESPACES
    }
#endif // _USE_NAMESPACES

