/*
	Pikaohjelma joka kerää tietoa kansion lähdekoodeista.
*/
 
#include <iostream>
#include <fstream>
#include <stdint.h>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/regex.hpp>
#include <string>
#include <cstring>
 
using namespace std;
using namespace boost;
using namespace boost::filesystem;
 
uint32_t countt[3] = {0, 0, 0} ;
 
string Trim(const string& str) {
    string s;
    for (int i = 0; i < str.length(); ++i)
        if ((unsigned char)str[i] > (unsigned char)' ')
            s += str[i];
        return s;
}
 
uint32_t GetType(const string &line) {
	if (line == "") {
		return 2;
	}
	regex comment("^//.*");
	cmatch match;
	if (regex_match(line.c_str(), match, comment)) {
		return 1;
	}
	return 0;
}
 
void Count(const string &file) {
	ifstream is;
	is.open(file.c_str(), ios::binary);
 
	string temp;
	while (getline(is, temp)) {
		countt[GetType(Trim(temp))]++;
		//cout << temp << endl;
	}
}
 
void Search(const string &dir) {
	path full_path = system_complete(path(dir.c_str()));
	if (!exists(full_path)) {
		cerr << "Something is fucked up!" << endl;
		return;
	}
 
	if (!is_directory(full_path)) {
		cerr << "Something is fucked up!" << endl;
		return;
	}
 
	regex expr(".*\\.(cpp|h|js|cb)$");
	directory_iterator end;
	for (directory_iterator it(full_path); it != end; it++) {
		try {
			if (is_regular_file(it->status())) {
				cmatch match;
				if (regex_match(it->leaf().c_str(), match, expr)) {
					Count(it->path().string());
				}
			}
			else if (is_directory(full_path)) {
				Search(it->path().string());
			}
		}
		catch (const std::exception &e) {
			cout << it->leaf() << " " << e.what() << endl;
		}
	}	
}
 
int32_t main() {
	path full_path( initial_path<path>() );
	Search(full_path.string());
 
	cout << countt[0] << " lines of code" << endl;
	cout << countt[1] << " lines commented" << endl;
	cout << countt[2] << " empty lines" << endl;
	cout << "-----------------------------------------------" << endl;
	cout << countt[0] + countt[1] + countt[2] << " lines total" << endl;
 
	return 0;
}