#include "profilewindow.hpp"
#include "../abaddon.hpp"
#include "../components/inotifyswitched.hpp"

ProfileWindow::ProfileWindow(Snowflake user_id)
    : ID(user_id)
    , m_main(Gtk::ORIENTATION_VERTICAL)
    , m_upper(Gtk::ORIENTATION_HORIZONTAL)
    , m_badges(Gtk::ORIENTATION_HORIZONTAL)
    , m_pane_info(user_id)
    , m_pane_guilds(user_id)
    , m_pane_friends(user_id) {
    auto &discord = Abaddon::Get().GetDiscordClient();
    auto user = *discord.GetUser(ID);

    discord.FetchUserProfile(user_id, sigc::mem_fun(*this, &ProfileWindow::OnFetchProfile));

    set_name("user-profile");
    set_default_size(450, 375);
    set_title(user.Username + "#" + user.Discriminator);
    set_position(Gtk::WIN_POS_CENTER);
    get_style_context()->add_class("app-window");
    get_style_context()->add_class("app-popup");
    get_style_context()->add_class("user-profile-window");
    m_main.get_style_context()->add_class("profile-main-container");
    m_avatar.get_style_context()->add_class("profile-avatar");
    m_username.get_style_context()->add_class("profile-username");
    m_switcher.get_style_context()->add_class("profile-switcher");
    m_stack.get_style_context()->add_class("profile-stack");
    m_badges.get_style_context()->add_class("profile-badges");

    m_scroll.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
    m_scroll.set_vexpand(true);
    m_scroll.set_propagate_natural_height(true);

    if (user.HasAvatar())
        AddPointerCursor(m_avatar_ev);
    m_avatar_ev.signal_button_press_event().connect([this, user](GdkEventButton *event) -> bool {
        if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY)
            if (user.HasAnimatedAvatar())
                LaunchBrowser(user.GetAvatarURL("gif", "512"));
            else
                LaunchBrowser(user.GetAvatarURL("png", "512"));
        return false;
    });

    static const bool show_animations = Abaddon::Get().GetSettings().GetShowAnimations();
    auto &img = Abaddon::Get().GetImageManager();
    m_avatar.property_pixbuf() = img.GetPlaceholder(64);
    if (user.HasAvatar()) {
        auto icon_cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
            set_icon(pb);
        };
        img.LoadFromURL(user.GetAvatarURL("png", "64"), sigc::track_obj(icon_cb, *this));

        if (show_animations && user.HasAnimatedAvatar()) {
            auto cb = [this](const Glib::RefPtr<Gdk::PixbufAnimation> &pb) {
                m_avatar.property_pixbuf_animation() = pb;
            };
            img.LoadAnimationFromURL(user.GetAvatarURL("gif", "64"), 64, 64, sigc::track_obj(cb, *this));
        } else {
            auto cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
                m_avatar.property_pixbuf() = pb->scale_simple(64, 64, Gdk::INTERP_BILINEAR);
            };
            img.LoadFromURL(user.GetAvatarURL("png", "64"), sigc::track_obj(cb, *this));
        }
    }

    m_username.set_markup(user.GetEscapedString());

    m_switcher.set_stack(m_stack);
    m_switcher.set_halign(Gtk::ALIGN_START);
    m_switcher.set_hexpand(true);

    m_stack.property_visible_child().signal_changed().connect([this]() {
        if (auto *w = dynamic_cast<INotifySwitched *>(m_stack.property_visible_child().get_value()))
            w->on_switched_to();
    });

    m_stack.add(m_pane_info, "info", "User Info");
    m_stack.add(m_pane_guilds, "guilds", "Mutual Servers");
    m_stack.add(m_pane_friends, "friends", "Mutual Friends");

    m_badges.set_valign(Gtk::ALIGN_CENTER);
    m_badges_scroll.set_hexpand(true);
    m_badges_scroll.set_propagate_natural_width(true);
    m_badges_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER);

    m_upper.set_halign(Gtk::ALIGN_START);
    m_avatar.set_halign(Gtk::ALIGN_START);
    m_username.set_halign(Gtk::ALIGN_START);
    m_avatar_ev.add(m_avatar);
    m_upper.add(m_avatar_ev);
    m_upper.add(m_username);
    m_badges_scroll.add(m_badges);
    m_upper.add(m_badges_scroll);
    m_main.add(m_upper);
    m_main.add(m_switcher);
    m_scroll.add(m_stack);
    m_main.add(m_scroll);
    add(m_main);
    show_all_children();
}

void ProfileWindow::OnFetchProfile(const UserProfileData &data) {
    m_pane_info.SetConnections(data.ConnectedAccounts);
    m_pane_guilds.SetMutualGuilds(data.MutualGuilds);

    for (auto child : m_badges.get_children())
        delete child;

    if (!data.User.PublicFlags.has_value()) return;
    const auto x = *data.User.PublicFlags;
    for (uint64_t i = 1; i <= UserData::MaxFlag; i <<= 1) {
        if (!(x & i)) continue;
        const std::string name = UserData::GetFlagName(i);
        if (name == "unknown") continue;
        Glib::RefPtr<Gdk::Pixbuf> pixbuf;
        try {
            if (name == "verifiedbot")
                pixbuf = Gdk::Pixbuf::create_from_file("./res/checkmark.png", 24, 24);
            else
                pixbuf = Gdk::Pixbuf::create_from_file("./res/" + name + ".png", 24, 24);
        } catch (const Glib::Exception &e) {
            pixbuf = Abaddon::Get().GetImageManager().GetPlaceholder(24);
        }
        if (!pixbuf) continue;
        auto *image = Gtk::manage(new Gtk::Image(pixbuf));
        image->get_style_context()->add_class("profile-badge");
        image->set_tooltip_text(UserData::GetFlagReadableName(i));
        image->show();
        m_badges.add(*image);
    }
}
