// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Basic 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 "BasicEncryption.h"
#include <iostream>
#include <random>
#include <algorithm>
#include <cctype>

// Constructor
BasicEncryption::BasicEncryption() : mDebugMode(false) {
    if (mDebugMode) {
        std::cout << "BasicEncryption object created" << std::endl;
    }
}

// Destructor
BasicEncryption::~BasicEncryption() {
    if (mDebugMode) {
        std::cout << "BasicEncryption object destroyed" << std::endl;
    }
}

// Caesar Cipher Encryption
std::string BasicEncryption::EncryptCaesar(const std::string& plaintext, int shift) {
    if (plaintext.empty()) {
        return "";
    }
    
    // Normalize shift to be within 0-25 range
    shift = ((shift % 26) + 26) % 26;
    
    std::string encrypted_text = "";
    
    for (char character : plaintext) {
        encrypted_text += ShiftCharacter(character, shift);
    }
    
    if (mDebugMode) {
        std::cout << "Caesar encryption completed with shift: " << shift << std::endl;
    }
    
    return encrypted_text;
}

// Caesar Cipher Decryption
std::string BasicEncryption::DecryptCaesar(const std::string& ciphertext, int shift) {
    if (ciphertext.empty()) {
        return "";
    }
    
    // Normalize shift to be within 0-25 range
    shift = ((shift % 26) + 26) % 26;
    
    std::string decrypted_text = "";
    
    for (char character : ciphertext) {
        decrypted_text += UnshiftCharacter(character, shift);
    }
    
    if (mDebugMode) {
        std::cout << "Caesar decryption completed with shift: " << shift << std::endl;
    }
    
    return decrypted_text;
}

// XOR Encryption
std::string BasicEncryption::EncryptXor(const std::string& plaintext, const std::string& key) {
    if (plaintext.empty() || !IsValidKey(key)) {
        return "";
    }
    
    std::string encrypted_text = ProcessXorEncryption(plaintext, key);
    
    if (mDebugMode) {
        std::cout << "XOR encryption completed with key length: " << key.length() << std::endl;
    }
    
    return encrypted_text;
}

// XOR Decryption (same as encryption for XOR)
std::string BasicEncryption::DecryptXor(const std::string& ciphertext, const std::string& key) {
    if (ciphertext.empty() || !IsValidKey(key)) {
        return "";
    }
    
    std::string decrypted_text = ProcessXorEncryption(ciphertext, key);
    
    if (mDebugMode) {
        std::cout << "XOR decryption completed with key length: " << key.length() << std::endl;
    }
    
    return decrypted_text;
}

// Generate Random Key for XOR encryption
std::string BasicEncryption::GenerateRandomKey(int length) {
    if (length < MIN_KEY_LENGTH) {
        return "";
    }
    
    std::random_device random_device;
    std::mt19937 generator(random_device());
    std::uniform_int_distribution<> distribution(33, 126); // Printable ASCII characters
    
    std::string random_key = "";
    
    for (int i = 0; i < length; ++i) {
        random_key += static_cast<char>(distribution(generator));
    }
    
    if (mDebugMode) {
        std::cout << "Generated random key of length: " << length << std::endl;
    }
    
    return random_key;
}

// Validate encryption key
bool BasicEncryption::IsValidKey(const std::string& key) {
    return !key.empty() && key.length() >= MIN_KEY_LENGTH;
}

// Set debug mode
void BasicEncryption::SetDebugMode(bool enabled) {
    mDebugMode = enabled;
    if (mDebugMode) {
        std::cout << "Debug mode enabled" << std::endl;
    }
}

// Private helper method: Shift character for Caesar cipher
char BasicEncryption::ShiftCharacter(char character, int shift) {
    if (std::isalpha(character)) {
        char base = std::islower(character) ? 'a' : 'A';
        return static_cast<char>((character - base + shift) % 26 + base);
    }
    return character; // Non-alphabetic characters remain unchanged
}

// Private helper method: Unshift character for Caesar cipher
char BasicEncryption::UnshiftCharacter(char character, int shift) {
    if (std::isalpha(character)) {
        char base = std::islower(character) ? 'a' : 'A';
        return static_cast<char>((character - base - shift + 26) % 26 + base);
    }
    return character; // Non-alphabetic characters remain unchanged
}

// Private helper method: Process XOR encryption/decryption
std::string BasicEncryption::ProcessXorEncryption(const std::string& input, const std::string& key) {
    std::string result = "";
    size_t key_length = key.length();
    
    for (size_t i = 0; i < input.length(); ++i) {
        char encrypted_char = input[i] ^ key[i % key_length];
        result += encrypted_char;
    }
    
    return result;
}