#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <set>
#include <string>

using namespace std;

int main()
{
    // Allows for iteration over const vectors
    // ONLY ALLOWS FOR ACCESS, not modification
    typedef string::const_iterator iterator;
    // Instruct the user
    cout << "***PLEASE SAVE CIPHER-TEXT AS cipher.txt IN THE SAME DIRECTORY YOU RUN THIS FROM***\n\n";
    // Read in file for cipher string
    ifstream file("cipher.txt");
    // Read file contents into string
    string cipherText;
    getline(file, cipherText);
    // Create character array for character mapping
    char *sAsCharArray= new char[cipherText.size()+1];
    // Zero the array
    sAsCharArray[cipherText.size()]=0;
    memcpy(sAsCharArray,cipherText.c_str(),cipherText.size());
    int frequency[256] = {0};
    int chars = 0, charCount = 0;
    double percentile;
    cout << "Printing character frequencies as the following: Character\t--\tCount\t--\tPercentage\n";
    // Convert the string to character array
    for (charCount = 0; sAsCharArray[charCount] != '\0'; charCount++){
        frequency[sAsCharArray[charCount]]++;
        chars++;
    }
    // Print the characters (lower ascii characters)
    for (charCount = 97; charCount < 123; charCount++)
    {
        percentile = ((double) frequency[charCount])/(chars) * 100;
        // Ignore characters that do not show up in the array (pros and cons to this)
        if (frequency[charCount] != 0)
            cout <<(char) charCount << "\t--\t" << frequency[charCount] << "\t--\t" << setprecision(3) << percentile << "\n";
    }
    set<string> substr;
    cout << "\n\nPrinting all reoccuring substrings within the string:\n";
    // Minimum length of substring = 2
    if (2 < cipherText.size())
        // Using iterators to traverse the length of the string -- something we could not do in C!
        for (iterator i = cipherText.begin() + 1, j = cipherText.end(); i != j; ++i)
            for (iterator k = cipherText.begin(); k != i; ++k)
            {
                // Refers to the second value on the map. If we do not see this, we do not have multiple occurrences
                // Without this line we would see every substring, including those that appear only once
                iterator buff = mismatch(i, j, k).second;;
                if (buff - k > 1)
                {
                    substr.insert(string(k, buff));
                }
            }
            // Writes sequentially to the output stream as is necessary
            //TODO: Calculate number of times each substring appears
            copy(substr.begin(), substr.end(),ostream_iterator<string>(cout, "\n"));
}