#include "lumacs/modeline.hpp"
#include "lumacs/window.hpp"
#include "lumacs/buffer.hpp"
#include <sstream>

namespace lumacs {

// === Segments ===

class FlagsSegment : public ModelineSegment {
public:
    std::vector<ModelineChunk> generate(const std::shared_ptr<Window>& window, bool active) override {
        const auto& buffer = window->buffer();
        std::string flags = buffer.is_modified() ? "**" : "--";
        // Use standard mode-line face
        std::string face = active ? "mode-line" : "mode-line-inactive";
        
        // Add padding
        return {{ " -" + flags + "- ", face }};
    }
    std::string name() const override { return "flags"; }
};

class BufferNameSegment : public ModelineSegment {
public:
    std::vector<ModelineChunk> generate(const std::shared_ptr<Window>& window, bool active) override {
        const auto& buffer = window->buffer();
        // Emacs uses mode-line-buffer-id face for name, fallback to mode-line if not defined
        std::string face = active ? "mode-line-buffer-id" : "mode-line-inactive";
        return {{ buffer.name() + "  ", face }};
    }
    std::string name() const override { return "buffer-name"; }
};

class CursorPositionSegment : public ModelineSegment {
public:
    std::vector<ModelineChunk> generate(const std::shared_ptr<Window>& window, bool active) override {
        auto cursor = window->cursor();
        std::string text = "(" + std::to_string(cursor.line + 1) + "," + std::to_string(cursor.column) + ") ";
        std::string face = active ? "mode-line" : "mode-line-inactive";
        return {{ text, face }};
    }
    std::string name() const override { return "cursor-position"; }
};

class PercentageSegment : public ModelineSegment {
public:
    std::vector<ModelineChunk> generate(const std::shared_ptr<Window>& window, bool active) override {
        const auto& buffer = window->buffer();
        auto [start_line, end_line] = window->visible_line_range();
        size_t total_lines = buffer.line_count();
        std::string position;

        if (total_lines <= 1) {
            position = "All";
        } else if (start_line == 0 && end_line >= total_lines) {
            position = "All";
        } else if (start_line == 0) {
            position = "Top";
        } else if (end_line >= total_lines) {
            position = "Bot";
        } else {
            int percent = static_cast<int>((static_cast<double>(start_line) / total_lines) * 100);
            position = std::to_string(percent) + "%";
        }
        
        std::string face = active ? "mode-line" : "mode-line-inactive";
        return {{ position + "  ", face }};
    }
    std::string name() const override { return "percentage"; }
};

class ModeSegment : public ModelineSegment {
public:
    std::vector<ModelineChunk> generate(const std::shared_ptr<Window>& window, bool active) override {
        const auto& buffer = window->buffer();
        std::string mode = buffer.language();
        if (mode.empty()) mode = "Fundamental";
        
        std::string face = active ? "mode-line" : "mode-line-inactive";
        return {{ "(" + mode + ")", face }};
    }
    std::string name() const override { return "mode"; }
};

// === Manager ===

ModelineManager::ModelineManager() {
    create_default_segments();
}

void ModelineManager::create_default_segments() {
    segments_.clear();
    add_segment(std::make_shared<FlagsSegment>());
    add_segment(std::make_shared<BufferNameSegment>());
    add_segment(std::make_shared<CursorPositionSegment>());
    add_segment(std::make_shared<PercentageSegment>());
    add_segment(std::make_shared<ModeSegment>());
}

void ModelineManager::add_segment(std::shared_ptr<ModelineSegment> segment) {
    segments_.push_back(segment);
}

void ModelineManager::clear_segments() {
    segments_.clear();
}

std::vector<ModelineChunk> ModelineManager::generate_content(const std::shared_ptr<Window>& window, bool active) {
    std::vector<ModelineChunk> content;
    if (!window) return content;
    
    for (const auto& segment : segments_) {
        auto chunks = segment->generate(window, active);
        content.insert(content.end(), chunks.begin(), chunks.end());
    }
    
    return content;
}

} // namespace lumacs
