// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Simple Encryption Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "SimpleEncryption.h"
#include <iostream>
#include <string>
#include <algorithm>

// Constructor
SimpleEncryption::SimpleEncryption(int shift) : mShiftValue(shift) {
    // Normalize shift value to 0-25 range
    mShiftValue = ((shift % ALPHABET_SIZE) + ALPHABET_SIZE) % ALPHABET_SIZE;
}

// Destructor
SimpleEncryption::~SimpleEncryption() {
    // No dynamic memory to clean up
}

// Encrypt a single character using Caesar cipher
char SimpleEncryption::EncryptChar(char input_char) const {
    if (IsAlpha(input_char)) {
        char base = IsUpper(input_char) ? 'A' : 'a';
        return static_cast<char>((input_char - base + mShiftValue) % ALPHABET_SIZE + base);
    }
    return input_char; // Return unchanged if not alphabetic
}

// Decrypt a single character using Caesar cipher
char SimpleEncryption::DecryptChar(char input_char) const {
    if (IsAlpha(input_char)) {
        char base = IsUpper(input_char) ? 'A' : 'a';
        return static_cast<char>((input_char - base - mShiftValue + ALPHABET_SIZE) % ALPHABET_SIZE + base);
    }
    return input_char; // Return unchanged if not alphabetic
}

// Encrypt a string
std::string SimpleEncryption::EncryptString(const std::string& plaintext) const {
    std::string encrypted_text = plaintext;
    std::transform(encrypted_text.begin(), encrypted_text.end(), encrypted_text.begin(),
                   [this](char c) { return EncryptChar(c); });
    return encrypted_text;
}

// Decrypt a string
std::string SimpleEncryption::DecryptString(const std::string& ciphertext) const {
    std::string decrypted_text = ciphertext;
    std::transform(decrypted_text.begin(), decrypted_text.end(), decrypted_text.begin(),
                   [this](char c) { return DecryptChar(c); });
    return decrypted_text;
}

// Set new shift value
void SimpleEncryption::SetShiftValue(int shift) {
    mShiftValue = ((shift % ALPHABET_SIZE) + ALPHABET_SIZE) % ALPHABET_SIZE;
}

// Get current shift value
int SimpleEncryption::GetShiftValue() const {
    return mShiftValue;
}

// Check if character is alphabetic
bool SimpleEncryption::IsAlpha(char c) const {
    return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}

// Check if character is uppercase
bool SimpleEncryption::IsUpper(char c) const {
    return c >= 'A' && c <= 'Z';
}

// Demonstration function
void SimpleEncryption::DemoEncryption() const {
    std::cout << "=== Simple Encryption Demo ===" << std::endl;
    std::cout << "Shift Value: " << mShiftValue << std::endl;
    
    std::string test_message = "Hello World! This is a test message.";
    std::cout << "Original:  " << test_message << std::endl;
    
    std::string encrypted = EncryptString(test_message);
    std::cout << "Encrypted: " << encrypted << std::endl;
    
    std::string decrypted = DecryptString(encrypted);
    std::cout << "Decrypted: " << decrypted << std::endl;
    
    std::cout << "Match: " << (test_message == decrypted ? "YES" : "NO") << std::endl;
    std::cout << "==============================" << std::endl;
}

// Main function for standalone execution
int main() {
    // Create encryption object with shift of 3
    SimpleEncryption cipher(3);
    
    // Run demonstration
    cipher.DemoEncryption();
    
    // Interactive mode
    std::cout << "\nInteractive Mode:" << std::endl;
    std::string user_input;
    
    std::cout << "Enter text to encrypt (or 'quit' to exit): ";
    std::getline(std::cin, user_input);
    
    while (user_input != "quit" && user_input != "exit") {
        std::string encrypted = cipher.EncryptString(user_input);
        std::string decrypted = cipher.DecryptString(encrypted);
        
        std::cout << "Original:  " << user_input << std::endl;
        std::cout << "Encrypted: " << encrypted << std::endl;
        std::cout << "Decrypted: " << decrypted << std::endl;
        std::cout << std::endl;
        
        std::cout << "Enter text to encrypt (or 'quit' to exit): ";
        std::getline(std::cin, user_input);
    }
    
    std::cout << "Goodbye!" << std::endl;
    return 0;
}