/*
 
 The purpose of this program is to emulate the workings of a simple substitution 
 cypher. The cypher does not distinguish between "encrypted" or "decrypted" 
 states; rather it simply translates between the characters contained in the
 cypher and allows plain passthrough of the remaining characters.

 Here's an example of a valid, albeit weak, cypher:

    TENIS
    -----
    POLAR

 This cypher is valid because it contains two rows that are of the same length
 and contain distinct characters - no two equal characters appear in any row.

 The cyphers may contain any character (alphanumeric, non-alphanumeric, 
 accented, extended Unicode...) depending on the complexity of the cypher you
 wish to have provided that character collisions do not happen.
 
 */

#include <iostream>
#include <string>
#include <vector>

typedef std::vector<char> cypherrow;

bool validate_cypher(cypherrow row1, cypherrow row2)
{
    bool statuscode = true;
    for (auto letter1 : row1) {
        for (auto letter2 : row2) {
            if (letter1 == letter2) {
                std::cout << "Warning: cypher collision detected at '" << letter1 << "'!\n";
                statuscode = false;
            }
        }
    }
    return statuscode;
}

// Begin translation. Note that it's symmetrical, as in we don't exactly have
// a "state" saying encypted or decrypted. The cypher takes a letter, sees if
// it has it available and rotates it. That's it.

std::string translate(std::string input, cypherrow r1, cypherrow r2) {
    std::string output = ""; // this will become the final string.
    bool match = false;
    int row(0);
    int index(0);
        for (auto letter : input) {
            match = false; 
            for (auto letter1 = r1.begin(); 
                    letter1 != r1.end(); ++letter1) {
                if (letter == *letter1) {
                    // we got a match!
                    match = true;
                    row = 1;
                    index = letter1 - r1.begin();
                    break;
                }
            }
            if (match == false) {
                for (auto letter2 = r2.begin(); 
                        letter2 != r2.end(); ++letter2) {
                    if (letter == *letter2) {
                        // we got a match!
                        match = true;
                        row = 2;
                        index = letter2 - r2.begin();
                        break;
                    }
                }
            }
            // uncomment the following block for debugging!
            /*
            std::cout << "Now manipulating letter " << letter << ", match is " 
                << match << " row is " << row << " index is " << index << std::endl;
            */
            if (match) {
                std::string newletter;
                // get the letter in the opposite row at the same index:
                if (row == 1) {
                    newletter = r2.at(index);
                }
                else if (row == 2) {
                    newletter = r1.at(index);
                }
                // compose the new string by appending it to the string:
                output.append(newletter);
            }
            else {
                // push the character unchanged:
                std::string unchanged;
                unchanged = std::string(1, (char)letter);
                output.append(unchanged);
            }
        }
    return output;
}

int main(int argc, char * argv[])
{
    cypherrow row1 {'p','l','e','a','i','z','o','m'};
    cypherrow row2 {'b','n','u','f','c','s','y','r'};
    if (validate_cypher(row1, row2)) {
        std::cout << "Cypher is good.\n";
    }
    else {
        std::cout << "You have a corrupted cypher.\n";
        std::cout << "Please fix it before running this program.\n";
        return 1;
    }
    std::string samplestring;
    std::cout << "Enter the text to be translated:\n>_ ";
    std::getline(std::cin, samplestring);
    std::cout << translate(samplestring, row1, row2) << std::endl;
    return 0;
}