/******************************************************************************
 * Christopher Thompson
 *
 * A simple quilt program using prime numbers
 *
 * Created with VIM and G++ in January 2009 on an HP Pavilion dv9744CA running
 * Ubuntu 8.04
 *****************************************************************************/

#include <climits>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <sstream>

using namespace std;

bool prime(int integer);
void output(int width, int length, list<int> primes);
void chart(list<int> primes, int total);
void illustrate(int width, int length, list<int> primes);

int main (int argc, char * argv[] ) {

    /* Variable List */
    int total;
    list<int> primelist;
    int digits = 0;

    /* Validates command line arguments */
    if (argc != 3) {
        cerr<<"Usage: "<<argv[0]<<" length width"<<endl;
        return 1;
    }
    if (!(total = atoi(argv[1]) * atoi(argv[2])) || (total < 1)) {
        cerr<<"Usage: "<<argv[0]<<"width (pos int) length (pos int)"<<endl;
        return 1;
    }

    /* Finds primes */
    for (int i = 1; i < INT_MAX; i++) {

        if (prime(i)) {

            /* Adds prime to list */
            primelist.push_back(i);

            /* Increments digit counter */
            int number = i;
            while (number > 0) {
                ++digits;
                number /= 10;
            }
        }

        /* Checks whether quilt size achieved */
        if (digits >= total ) {
            break;
        }
    }

    cout<<"Total squares: "<<total<<endl;
    cout<<"Frequency chart"<<endl;
    chart(primelist, (atoi(argv[1]) * atoi(argv[2])));
    cout<<"Pattern: ";
    output(atoi(argv[1]), atoi(argv[2]), primelist);
    illustrate(atoi(argv[1]), atoi(argv[2]), primelist);
}

bool prime(int integer) {
    for (int i = 2; i < integer; i++) {
        if ((integer % i) == 0)
            return false;
    }
    return true;
}

void output(int width, int length, list<int> primes) {
    int digits = 0;
    int total = width * length;
    for (list<int>::iterator it = primes.begin(); it != primes.end(); ++it) {
        int number = *it;
        stringstream ss;
        char c;
        ss<<number;
        while (ss.get(c) && (digits < total)) {
            if ((digits%width) == 0) {
                cout<<"\n"<<c;
            } else {
                cout<<c;
            }
            ++digits;
        }
    } 
}

void chart(list<int> primes, int total) {
    map<int, unsigned> score;
    int digits = 0;

    for (list<int>::iterator it = primes.begin(); it != primes.end(); ++it) {
        int number = *it;
        stringstream ss;
        char c;
        ss<<number;
        while (ss.get(c) && (digits < total)) {
            score[c]++;
            ++digits;
        }
    } 

    for (map<int, unsigned>::const_iterator it = score.begin();
         it != score.end(); ++it) {
        cout<<(it->first - 48)<<": "<<setw(5)<<it->second<<" ";
        for (unsigned i = 0; i < it->second; ++i) {
            if ((i % 3) == 0)
                cout<<"*";
        }
        cout<<endl;

    }
}

void illustrate(int width, int length, list<int> primes) {
    ofstream f("layout.html");
    if (!f) {
        cerr<<"Unable to open file"<<endl;
        exit(1);
    }
    f<<"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>"<<endl;
    f<<"<!DOCTYPE html"<<endl;
    f<<"    PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""<<endl;
    f<<"    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"<<endl;
    f<<"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" ";
    f<<"lang=\"en\" dir=\"ltr\" id=\"christhompson\">\n<head>"<<endl;
    f<<"    <title>Layout 6</title>\n</head>\n<body ";
    f<<"style=\" background-color: #000;\">\n    <p>"<<endl;
    int digits = 0;
    int total = width * length;
    for (list<int>::iterator it = primes.begin(); it != primes.end(); ++it) {
        int number = *it;
        stringstream ss;
        char c;
        ss<<number;
        while (ss.get(c) && (digits < total)) {
            if ((digits%width) == 0) {
                f<<"    <br />";
            }
            switch ((c-48)) {
            case 0:
                f<<"<span style=\"color: #FF4500;";
                f<<" background-color: #FF4500;\"> ** </span>";
                break;
            case 1:
                f<<"<span style=\"color: #00F;";
                f<<" background-color: #00F;\"> ** </span>";
                break;
            case 2:
                f<<"<span style=\"color: #0FF;";
                f<<" background-color: #0FF;\"> ** </span>";
                break;
            case 3:
                f<<"<span style=\"color: #222;";
                f<<" background-color: #222;\"> ** </span>";
                break;
            case 4:
                f<<"<span style=\"color: #FFD700;";
                f<<" background-color: #FFD700\"> ** </span>";
                break;
            case 5:
                f<<"<span style=\"color: #0F0;";
                f<<" background-color: #0F0;\"> ** </span>";
                break;
            case 6:
                f<<"<span style=\"color: #ADFF2F;";
                f<<" background-color: #ADFF2F;\"> ** </span>";
                break;
            case 7:
                f<<"<span style=\"color: #778899;";
                f<<" background-color: #778899;\"> ** </span>";
                break;
            case 8:
                f<<"<span style=\"color: #F00;";
                f<<" background-color: #F00;\"> ** </span>";
                break;
            case 9:
                f<<"<span style=\"color: #F00;";
                f<<" background-color: #FFD700;\"> ** </span>";
                break;
            }
            ++digits;
        }
    }
    f<<"    </p>\n</body>\n</html>"<<endl;
}

