// Data models implementation
#include "data_models.h"
#include <iostream>

// Global data instances
SettingsData g_settings;
PhoneData g_phone;
BrowserData g_browser;
std::vector<Conversation> g_conversations;
std::vector<Contact> g_contacts;
int g_selected_conversation = -1;
int g_selected_contact = -1;

// Data model handles
Rml::DataModelHandle g_settings_model;
Rml::DataModelHandle g_phone_model;
Rml::DataModelHandle g_messages_model;
Rml::DataModelHandle g_contacts_model;
Rml::DataModelHandle g_browser_model;

void initializeSampleData()
{
    // Initialize contacts
    g_contacts = {
        {1, "Alice Johnson", "+1 (555) 123-4567", "alice@example.com", "#E91E63", "A"},
        {2, "Andrew Smith", "+1 (555) 234-5678", "andrew@example.com", "#9C27B0", "A"},
        {3, "Bob Williams", "+1 (555) 345-6789", "bob@example.com", "#2196F3", "B"},
        {4, "Brian Davis", "+1 (555) 456-7890", "brian@example.com", "#00BCD4", "B"},
        {5, "Carol Martinez", "+1 (555) 567-8901", "carol@example.com", "#4CAF50", "C"},
        {6, "David Lee", "+1 (555) 678-9012", "david@example.com", "#FF9800", "D"},
        {7, "John Wilson", "+1 (555) 789-0123", "john@example.com", "#F44336", "J"},
        {8, "Mom", "+1 (555) 890-1234", "mom@example.com", "#673AB7", "M"},
        {9, "Mike Brown", "+1 (555) 901-2345", "mike@example.com", "#3F51B5", "M"},
        {10, "Sarah Taylor", "+1 (555) 012-3456", "sarah@example.com", "#009688", "S"}
    };

    // Initialize conversations
    g_conversations = {
        {1, "John Wilson", "#4CAF50", "Hey, are you coming to the party tonight?", "2:30 PM", 2, {
            {"them", "Hey!", "2:25 PM"},
            {"them", "What are you up to?", "2:26 PM"},
            {"me", "Not much, just working", "2:27 PM"},
            {"them", "Cool! There's a party at Mike's tonight", "2:28 PM"},
            {"them", "Hey, are you coming to the party tonight?", "2:30 PM"}
        }},
        {2, "Mom", "#673AB7", "Don't forget to call your grandmother!", "1:15 PM", 0, {
            {"them", "Hi sweetie!", "1:00 PM"},
            {"me", "Hi Mom!", "1:05 PM"},
            {"them", "How are you doing?", "1:10 PM"},
            {"me", "I'm good, how are you?", "1:12 PM"},
            {"them", "Don't forget to call your grandmother!", "1:15 PM"}
        }},
        {3, "Alice Johnson", "#E91E63", "Thanks for the help with the project!", "Yesterday", 0, {
            {"me", "Here's the file you needed", "Yesterday"},
            {"them", "Thanks for the help with the project!", "Yesterday"}
        }},
        {4, "Bob Williams", "#2196F3", "Did you see the game last night?", "Yesterday", 0, {
            {"them", "Did you see the game last night?", "Yesterday"}
        }},
        {5, "Work Group", "#FF9800", "Sarah: Meeting moved to 3pm", "Mon", 0, {
            {"Sarah", "Meeting moved to 3pm", "Mon"}
        }},
        {6, "Sarah Taylor", "#009688", "See you at the coffee shop!", "Sun", 0, {
            {"them", "See you at the coffee shop!", "Sun"}
        }},
        {7, "David Lee", "#F44336", "Great talking to you!", "Sat", 0, {
            {"them", "Great talking to you!", "Sat"}
        }}
    };

    // Initialize browser tabs
    g_browser.tabs = {
        {"example.com", "Example Domain", false},
        {"rmlui.github.io", "RmlUi Documentation", false},
        {"github.com", "GitHub", false}
    };

    std::cout << "Sample data initialized: " << g_contacts.size() << " contacts, "
              << g_conversations.size() << " conversations, "
              << g_browser.tabs.size() << " browser tabs" << std::endl;
}

void setupDataModels(Rml::Context* context)
{
    // Messages data model
    if (auto constructor = context->CreateDataModel("messages"))
    {
        if (auto msg_handle = constructor.RegisterStruct<Message>())
        {
            msg_handle.RegisterMember("from", &Message::from);
            msg_handle.RegisterMember("text", &Message::text);
            msg_handle.RegisterMember("time", &Message::time);
        }

        if (auto conv_handle = constructor.RegisterStruct<Conversation>())
        {
            conv_handle.RegisterMember("id", &Conversation::id);
            conv_handle.RegisterMember("name", &Conversation::name);
            conv_handle.RegisterMember("color", &Conversation::color);
            conv_handle.RegisterMember("last_message", &Conversation::last_message);
            conv_handle.RegisterMember("time", &Conversation::time);
            conv_handle.RegisterMember("unread", &Conversation::unread);
            conv_handle.RegisterMember("messages", &Conversation::messages);
        }

        constructor.RegisterArray<std::vector<Message>>();
        constructor.RegisterArray<std::vector<Conversation>>();

        constructor.Bind("conversations", &g_conversations);
        constructor.Bind("selected_conversation", &g_selected_conversation);

        constructor.BindEventCallback("select_conversation",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                if (!args.empty()) {
                    g_selected_conversation = args[0].Get<int>();
                    std::cout << "Selected conversation: " << g_selected_conversation << std::endl;
                    handle.DirtyVariable("selected_conversation");
                }
            });

        g_messages_model = constructor.GetModelHandle();
        std::cout << "Messages data model created" << std::endl;
    }

    // Contacts data model
    if (auto constructor = context->CreateDataModel("contacts"))
    {
        if (auto contact_handle = constructor.RegisterStruct<Contact>())
        {
            contact_handle.RegisterMember("id", &Contact::id);
            contact_handle.RegisterMember("name", &Contact::name);
            contact_handle.RegisterMember("phone", &Contact::phone);
            contact_handle.RegisterMember("email", &Contact::email);
            contact_handle.RegisterMember("color", &Contact::color);
            contact_handle.RegisterMember("initial", &Contact::initial);
        }

        constructor.RegisterArray<std::vector<Contact>>();

        constructor.Bind("contacts", &g_contacts);
        constructor.Bind("selected_contact", &g_selected_contact);

        constructor.BindEventCallback("select_contact",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                if (!args.empty()) {
                    g_selected_contact = args[0].Get<int>();
                    std::cout << "Selected contact: " << g_selected_contact << std::endl;
                    handle.DirtyVariable("selected_contact");
                }
            });

        g_contacts_model = constructor.GetModelHandle();
        std::cout << "Contacts data model created" << std::endl;
    }

    // Settings data model
    if (auto constructor = context->CreateDataModel("settings"))
    {
        constructor.Bind("wifi", &g_settings.wifi);
        constructor.Bind("bluetooth", &g_settings.bluetooth);
        constructor.Bind("airplane_mode", &g_settings.airplane_mode);
        constructor.Bind("location", &g_settings.location);
        constructor.Bind("dark_mode", &g_settings.dark_mode);
        constructor.Bind("notifications", &g_settings.notifications);
        constructor.Bind("do_not_disturb", &g_settings.do_not_disturb);
        constructor.Bind("user_name", &g_settings.user_name);
        constructor.Bind("user_email", &g_settings.user_email);
        constructor.Bind("wifi_network", &g_settings.wifi_network);
        constructor.Bind("battery_percent", &g_settings.battery_percent);
        constructor.Bind("battery_remaining", &g_settings.battery_remaining);
        constructor.Bind("storage_used", &g_settings.storage_used);

        g_settings_model = constructor.GetModelHandle();
        std::cout << "Settings data model created" << std::endl;
    }

    // Phone data model
    if (auto constructor = context->CreateDataModel("phone"))
    {
        constructor.Bind("dial_number", &g_phone.dial_number);
        constructor.Bind("is_calling", &g_phone.is_calling);
        constructor.Bind("call_contact", &g_phone.call_contact);
        constructor.Bind("call_duration", &g_phone.call_duration);

        constructor.BindEventCallback("dial_press",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                if (!args.empty()) {
                    g_phone.dial_number += args[0].Get<Rml::String>();
                    std::cout << "Dial: " << g_phone.dial_number << std::endl;
                    handle.DirtyVariable("dial_number");
                }
            });

        constructor.BindEventCallback("dial_backspace",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                if (!g_phone.dial_number.empty()) {
                    g_phone.dial_number.pop_back();
                    handle.DirtyVariable("dial_number");
                }
            });

        constructor.BindEventCallback("dial_clear",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                g_phone.dial_number.clear();
                handle.DirtyVariable("dial_number");
            });

        constructor.BindEventCallback("make_call",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                if (!g_phone.dial_number.empty()) {
                    g_phone.is_calling = true;
                    g_phone.call_contact = g_phone.dial_number;
                    std::cout << "Calling: " << g_phone.call_contact << std::endl;
                    handle.DirtyVariable("is_calling");
                    handle.DirtyVariable("call_contact");
                }
            });

        constructor.BindEventCallback("end_call",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                g_phone.is_calling = false;
                g_phone.call_contact = "";
                g_phone.call_duration = "00:00";
                handle.DirtyVariable("is_calling");
                handle.DirtyVariable("call_contact");
                handle.DirtyVariable("call_duration");
            });

        g_phone_model = constructor.GetModelHandle();
        std::cout << "Phone data model created" << std::endl;
    }

    // Browser data model
    if (auto constructor = context->CreateDataModel("browser"))
    {
        if (auto tab_handle = constructor.RegisterStruct<BrowserTab>())
        {
            tab_handle.RegisterMember("url", &BrowserTab::url);
            tab_handle.RegisterMember("title", &BrowserTab::title);
            tab_handle.RegisterMember("is_loading", &BrowserTab::is_loading);
        }

        constructor.RegisterArray<std::vector<BrowserTab>>();

        constructor.Bind("current_url", &g_browser.current_url);
        constructor.Bind("page_title", &g_browser.page_title);
        constructor.Bind("page_content", &g_browser.page_content);
        constructor.Bind("tabs", &g_browser.tabs);
        constructor.Bind("current_tab", &g_browser.current_tab);
        constructor.Bind("can_go_back", &g_browser.can_go_back);
        constructor.Bind("can_go_forward", &g_browser.can_go_forward);

        constructor.BindEventCallback("navigate",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                if (!args.empty()) {
                    g_browser.current_url = args[0].Get<Rml::String>();
                    g_browser.page_title = "Loading...";
                    g_browser.can_go_back = true;
                    std::cout << "Navigating to: " << g_browser.current_url << std::endl;
                    handle.DirtyVariable("current_url");
                    handle.DirtyVariable("page_title");
                    handle.DirtyVariable("can_go_back");
                }
            });

        constructor.BindEventCallback("refresh",
            [](Rml::DataModelHandle handle, Rml::Event& event, const Rml::VariantList& args) {
                std::cout << "Refreshing page" << std::endl;
            });

        g_browser_model = constructor.GetModelHandle();
        std::cout << "Browser data model created" << std::endl;
    }

    std::cout << "All data models initialized" << std::endl;
}
