#include <bits/stdc++.h>
#ifdef _WIN32
#include <windows.h>
#endif
using namespace std;
namespace {
enum class OperationMode {
    Encrypt,
    Decrypt,
    LegacyEncrypt,
    LegacyDecrypt,
};
enum class Direction {
    Forward,
    Backward,
};
struct OperationResult {
    bool success;
    string output;
    string error;
};
struct ParsedArguments {
    OperationMode mode;
    Direction direction = Direction::Forward;
    int shift = 0;
    string text;
};
string trim(const string& value) {
    const string whitespace = " \t\r\n";
    const size_t begin = value.find_first_not_of(whitespace);
    if (begin == string::npos)return "";
    const size_t end = value.find_last_not_of(whitespace);
    return value.substr(begin, end - begin + 1);
}
optional<int> parse_int_strict(const string& value) {
    const string cleaned = trim(value);
    if (cleaned.empty()) return nullopt;
    char* end_ptr = nullptr;
    errno = 0;
    const long parsed = strtol(cleaned.c_str(), &end_ptr, 10);
    if (errno != 0 || end_ptr == cleaned.c_str() || *end_ptr != '\0') return nullopt;
    if (parsed < numeric_limits<int>::min() || parsed > numeric_limits<int>::max()) return nullopt;
    return static_cast<int>(parsed);
}
optional<Direction> parse_direction(const string& value) {
    const string cleaned = trim(value);
    if (cleaned == "+") return Direction::Forward;
    if (cleaned == "-") return Direction::Backward;
    return nullopt;
}

optional<OperationMode> parse_mode(const string& value) {
    if (value == "加密" || value == "encrypt") return OperationMode::Encrypt;
    if (value == "解密" || value == "decrypt") return OperationMode::Decrypt;
    if (value == "兼容加密" || value == "legacy-encrypt") return OperationMode::LegacyEncrypt;
    if (value == "兼容解密" || value == "legacy-decrypt") return OperationMode::LegacyDecrypt;
    return nullopt;
}

bool mode_requires_direction(OperationMode mode) {
    return mode == OperationMode::LegacyEncrypt || mode == OperationMode::LegacyDecrypt;
}

bool is_valid_shifted_code_point(int64_t value) {
    if (value < 0 || value > 0x10FFFF) return false;
    if (value >= 0xD800 && value <= 0xDFFF) return false;
    return true;
}

OperationResult decode_utf8(const string& text, vector<uint32_t>& code_points) {
    code_points.clear();
    for (size_t i = 0; i < text.size();) {
        const unsigned char lead = static_cast<unsigned char>(text[i]);
        uint32_t code_point = 0;
        size_t length = 0;
        if ((lead & 0x80U) == 0) {
            code_point = lead;
            length = 1;
        } else if ((lead & 0xE0U) == 0xC0U) {
            code_point = lead & 0x1FU;
            length = 2;
        } else if ((lead & 0xF0U) == 0xE0U) {
            code_point = lead & 0x0FU;
            length = 3;
        } else if ((lead & 0xF8U) == 0xF0U) {
            code_point = lead & 0x07U;
            length = 4;
        } else return {false, "", "输入文本不是合法的 UTF-8 编码。"};
        if (i + length > text.size()) return {false, "", "输入文本不是合法的 UTF-8 编码。"};
        for (size_t offset = 1; offset < length; ++offset) {
            const unsigned char continuation = static_cast<unsigned char>(text[i + offset]);
            if ((continuation & 0xC0U) != 0x80U) return {false, "", "输入文本不是合法的 UTF-8 编码。"};
            code_point = (code_point << 6U) | (continuation & 0x3FU);
        }

        if ((length == 2 && code_point < 0x80U) ||
            (length == 3 && code_point < 0x800U) ||
            (length == 4 && code_point < 0x10000U) ||
            !is_valid_shifted_code_point(code_point)) {
            return {false, "", "输入文本不是合法的 UTF-8 编码。"};
        }
        code_points.push_back(code_point);
        i += length;
    }
    return {true, "", ""};
}
OperationResult encode_utf8(const vector<uint32_t>& code_points) {
    string output;
    for (const uint32_t code_point : code_points) {
        if (!is_valid_shifted_code_point(code_point)) return {false, "", "存在无法编码为 UTF-8 的码点。"};
        if (code_point <= 0x7FU) output.push_back(static_cast<char>(code_point));
        else if (code_point <= 0x7FFU) {
            output.push_back(static_cast<char>(0xC0U | (code_point >> 6U)));
            output.push_back(static_cast<char>(0x80U | (code_point & 0x3FU)));
        } else if (code_point <= 0xFFFFU) {
            output.push_back(static_cast<char>(0xE0U | (code_point >> 12U)));
            output.push_back(static_cast<char>(0x80U | ((code_point >> 6U) & 0x3FU)));
            output.push_back(static_cast<char>(0x80U | (code_point & 0x3FU)));
        } else {
            output.push_back(static_cast<char>(0xF0U | (code_point >> 18U)));
            output.push_back(static_cast<char>(0x80U | ((code_point >> 12U) & 0x3FU)));
            output.push_back(static_cast<char>(0x80U | ((code_point >> 6U) & 0x3FU)));
            output.push_back(static_cast<char>(0x80U | (code_point & 0x3FU)));
        }
    }
    return {true, output, ""};
}
OperationResult shift_text_utf8(const string& text, int shift, Direction direction) {
    vector<uint32_t> code_points;
    const OperationResult decode_result = decode_utf8(text, code_points);
    if (!decode_result.success) return decode_result;
    const int64_t delta = direction == Direction::Forward ? shift : -shift;
    vector<uint32_t> shifted;
    shifted.reserve(code_points.size());
    for (const uint32_t code_point : code_points) {
        const int64_t next = static_cast<int64_t>(code_point) + delta;
        if (!is_valid_shifted_code_point(next)) return {false, "", "位移后的码点超出有效 Unicode 范围。"};
        shifted.push_back(static_cast<std::uint32_t>(next));
    }
    return encode_utf8(shifted);
}
string byte_to_binary_string(unsigned char value) {
    string binary;
    if (value == 0) return "0";
    while (value > 0) {
        binary.insert(binary.begin(), (value & 1U) != 0U ? '1' : '0');
        value >>= 1U;
    }
    return binary;
}
OperationResult parse_binary_token(const string& token) {
    if (token.empty())return {false, "", "检测到空的二进制片段。"};
    if (token.size() > 8)return {false, "", "legacy 二进制片段长度不能超过 8 位。"};
    unsigned int value = 0;
    for (const char ch : token) {
        if (ch != '0' && ch != '1') return {false, "", "legacy 模式只接受由 0 和 1 组成的二进制片段。"};
        value = (value << 1U) | static_cast<unsigned int>(ch - '0');
    }
    return {true, string(1, static_cast<char>(value)), ""};
}
vector<string> split_tokens(const string& input) {
    istringstream stream(input);
    vector<string> tokens;
    string token;
    while (stream >> token) tokens.push_back(token);
    return tokens;
}
OperationResult encode_binary_legacy(const string& text, int shift, Direction direction) {
    ostringstream output;
    for (size_t i = 0; i < text.size(); ++i) {
        const unsigned char raw = static_cast<unsigned char>(text[i]);
        const int shifted = direction == Direction::Forward ? static_cast<int>(raw) + shift
                                                            : static_cast<int>(raw) - shift;
        if (shifted < 0 || shifted > 255) {
            return {false, "", "legacy 模式位移后超出单字节范围。"};
        }

        if (i > 0) {
            output << ' ';
        }
        output << byte_to_binary_string(static_cast<unsigned char>(shifted));
    }

    return {true, output.str(), ""};
}

OperationResult decode_binary_legacy(const vector<std::string>& tokens, int shift, Direction direction) {
    if (tokens.empty()) return {false, "", "legacy 解密输入不能为空。"};
    string output;
    output.reserve(tokens.size());
    for (const string& token : tokens) {
        const OperationResult parse_result = parse_binary_token(token);
        if (!parse_result.success) return parse_result;
        const unsigned char raw = static_cast<unsigned char>(parse_result.output[0]);
        const int shifted = direction == Direction::Forward ? static_cast<int>(raw) - shift
                                                            : static_cast<int>(raw) + shift;
        if (shifted < 0 || shifted > 255) return {false, "", "legacy 解密后超出单字节范围。"};
        output.push_back(static_cast<char>(shifted));
    }
    return {true, output, ""};
}
OperationResult execute_operation(OperationMode mode,
                                  int shift,
                                  Direction direction,
                                  const std::string& payload) {
    switch (mode) {
        case OperationMode::Encrypt:
            return shift_text_utf8(payload, shift, Direction::Forward);
        case OperationMode::Decrypt:
            return shift_text_utf8(payload, shift, Direction::Backward);
        case OperationMode::LegacyEncrypt:
            return encode_binary_legacy(payload, shift, direction);
        case OperationMode::LegacyDecrypt:
            return decode_binary_legacy(split_tokens(payload), shift, direction);
    }

    return {false, "", "未知操作模式。"};
}
void print_usage() {
    cout<< "用法:\n"
        << "  main.exe --mode 加密 --shift 3 --text \"Hello\"\n"
        << "  main.exe --mode 解密 --shift 3 --text \"Khoor\"\n"
        << "  main.exe --mode 兼容加密 --shift 3 --direction + --text \"Hello\"\n"
        << "  main.exe --mode 兼容解密 --shift 3 --direction + --input \"1001011 1101000\"\n";
}

OperationResult parse_arguments(int argc, char* argv[], ParsedArguments& parsed) {
    optional<OperationMode> mode;
    optional<int> shift;
    optional<Direction> direction;
    optional<string> payload;
    for (int i = 1; i < argc; ++i) {
        const string current = argv[i];
        auto read_value = [&]() -> optional<string> {
            if (i + 1 >= argc) return nullopt;
            ++i;
            return string(argv[i]);
        };
        if (current == "--mode") {
            const auto value = read_value();
            if (!value.has_value()) return {false, "", "--mode 缺少参数值。"};
            mode = parse_mode(*value);
            if (!mode.has_value()) return {false, "", "不支持的 mode。"};
        } else if (current == "--shift") {
            const auto value = read_value();
            if (!value.has_value()) return {false, "", "--shift 缺少参数值。"};
            shift = parse_int_strict(*value);
            if (!shift.has_value()) return {false, "", "--shift 必须是合法整数。"};
        } else if (current == "--direction") {
            const auto value = read_value();
            if (!value.has_value()) return {false, "", "--direction 缺少参数值。"};
            direction = parse_direction(*value);
            if (!direction.has_value()) return {false, "", "--direction 只能是 + 或 -。"};
        } else if (current == "--text" || current == "--input") {
            const auto value = read_value();
            if (!value.has_value()) return {false, "", current + " 缺少参数值。"};
            payload = *value;
        } else if (current == "--help" || current == "-h")return {false, "", ""};
        else return {false, "", "未知参数: " + current};
    }
    if (!mode.has_value() || !shift.has_value() || !payload.has_value()) return {false, "", "缺少必需参数。"};
    if (mode_requires_direction(*mode) && !direction.has_value()) return {false, "", "legacy 模式必须提供 --direction。"};
    parsed.mode = *mode;
    parsed.shift = *shift;
    parsed.text = *payload;
    if (direction.has_value()) parsed.direction = *direction;
    return {true, "", ""};
}
optional<int> prompt_shift() {
    cout << "请输入位移量: ";
    string line;
    if (!getline(cin, line)) return nullopt;
    return parse_int_strict(line);
}
optional<Direction> prompt_direction() {
    cout << "请输入方向（+ 或 -）: ";
    string line;
    if (!getline(cin, line)) return nullopt;
    return parse_direction(line);
}
bool run_menu() {
    cout<< "欢迎使用HGN加密程序[v0.5.0]。\n"
        << "HGN保留所有权,但本程序进行开源。\n"
        << "可用命令: 加密, 解密, 兼容加密, 兼容解密, 退出\n";
    while (true) {
        cout << "\n请输入命令: ";
        string command;
        if (!getline(cin, command)) return false;
        command = trim(command);
        if (command.empty()) {
            cout << "命令不能为空。\n";
            continue;
        }
        if (command == "退出" || command == "exit") {
            cout << "已退出。\n";
            return true;
        }
        const auto mode = parse_mode(command);
        if (!mode.has_value()) {
            cout << "不支持的命令。\n";
            continue;
        }
        const auto shift = prompt_shift();
        if (!shift.has_value()) {
            cout << "位移量必须是合法整数。\n";
            if (!cin.good()) return false;
            continue;
        }
        Direction direction = Direction::Forward;
        if (mode_requires_direction(*mode)) {
            const auto parsed_direction = prompt_direction();
            if (!parsed_direction.has_value()) {
                cout << "方向只能输入 + 或 -。\n";
                if (!cin.good()) return false;
                continue;
            }
            direction = *parsed_direction;
        }
        if (*mode == OperationMode::LegacyDecrypt) cout << "请输入空格分隔的二进制内容: ";
        else cout << "请输入文本: ";
        string payload;
        if (!getline(cin, payload)) return false;
        const OperationResult result = execute_operation(*mode, *shift, direction, payload);
        if (!result.success) {
            cout << "错误: " << result.error << "\n";
            continue;
        }
        cout << "结果: " << result.output << "\n";
    }
}
void configure_console_utf8() {
#ifdef _WIN32
    SetConsoleOutputCP(CP_UTF8);
    SetConsoleCP(CP_UTF8);
#endif
}
}  // namespace
int main(int argc, char* argv[]) {
    configure_console_utf8();
    if (argc > 1) {
        ParsedArguments parsed;
        const OperationResult parse_result = parse_arguments(argc, argv, parsed);
        if (!parse_result.success) {
            if (!parse_result.error.empty()) cerr << "参数错误: " << parse_result.error << "\n";
            print_usage();
            return parse_result.error.empty() ? 0 : 1;
        }
        const OperationResult result =
            execute_operation(parsed.mode, parsed.shift, parsed.direction, parsed.text);
        if (!result.success) {
            cerr << "执行失败: " << result.error << "\n";
            return 1;
        }
        cout << result.output << "\n";
        return 0;
    }
    return run_menu() ? 0 : 1;
}