#include <terminal/MDspPeerVolumeDetail.h>
#include <terminal/DisplayUpdateEvent.h>
#include <terminal/DisplayConsts.h>
#include <terminal/KeyCodes.h>
#include <terminal/HelpText.h>
#include <objects/DrbdResource.h>
#include <string>

MDspPeerVolumeDetail::MDspPeerVolumeDetail(const ComponentsHub& comp_hub):
    MDspMenuBase::MDspMenuBase(comp_hub)
{
    cmd_fn_actions =
        [this]() -> void
        {
            opt_actions();
        };
    cmd_actions = std::unique_ptr<ClickableCommand>(
        new ClickableCommand("A", 1, 15, 1, 20, cmd_fn_actions)
    );
}

MDspPeerVolumeDetail::~MDspPeerVolumeDetail() noexcept
{
}

void MDspPeerVolumeDetail::display_content()
{
    dsp_comp_hub.dsp_common->display_page_id(DisplayId::MDSP_PEER_VLM_DETAIL);

    dsp_comp_hub.dsp_io->cursor_xy(1, DisplayConsts::PAGE_NAV_Y + 1);
    dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
    dsp_comp_hub.dsp_io->write_text("Peer volume details");

    uint32_t current_line = DisplayConsts::PAGE_NAV_Y + 3;
    dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
    dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
    dsp_comp_hub.dsp_io->write_text("Resource:");
    dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
    dsp_comp_hub.dsp_io->cursor_xy(21, current_line);
    if (!dsp_comp_hub.dsp_shared->monitor_rsc.empty())
    {
        DrbdResource* const rsc = dsp_comp_hub.get_monitor_resource();
        const std::string& rsc_name = (rsc != nullptr ? rsc->get_name() : dsp_comp_hub.dsp_shared->monitor_rsc);
        dsp_comp_hub.dsp_io->write_string_field(rsc_name, dsp_comp_hub.term_cols - 20, false);
        ++current_line;

        dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
        dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
        dsp_comp_hub.dsp_io->write_text("Connection:");
        dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
        dsp_comp_hub.dsp_io->cursor_xy(21, current_line);

        if (!dsp_comp_hub.dsp_shared->monitor_con.empty())
        {
            DrbdConnection* const con = dsp_comp_hub.get_monitor_connection();
            const std::string& con_name = (con != nullptr ? con->get_name() : dsp_comp_hub.dsp_shared->monitor_con);
            dsp_comp_hub.dsp_io->write_string_field(con_name, dsp_comp_hub.term_cols - 20, false);
            ++current_line;

            const uint16_t vlm_nr = dsp_comp_hub.dsp_shared->monitor_peer_vlm;

            dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
            dsp_comp_hub.dsp_io->write_text("Volume:");
            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
            dsp_comp_hub.dsp_io->cursor_xy(21, current_line);
            if (vlm_nr != DisplayConsts::VLM_NONE)
            {
                dsp_comp_hub.dsp_io->write_fmt("%u", static_cast<unsigned int> (vlm_nr));
                ++current_line;

                dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
                dsp_comp_hub.dsp_io->write_text("Status:");
                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
                dsp_comp_hub.dsp_io->cursor_xy(21, current_line);

                if (rsc != nullptr)
                {
                    if (con != nullptr)
                    {
                        DrbdVolume* const vlm = con->get_volume(vlm_nr);
                        if (vlm != nullptr)
                        {
                            if (vlm->has_alert_state() || vlm->has_warn_state())
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->alert.c_str());
                                dsp_comp_hub.dsp_io->write_text("Degraded");
                            }
                            else
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->norm.c_str());
                                dsp_comp_hub.dsp_io->write_text("Normal");
                            }
                            ++current_line;

                            dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
                            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
                            dsp_comp_hub.dsp_io->write_text("Disk state:");
                            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
                            dsp_comp_hub.dsp_io->cursor_xy(21, current_line);
                            if (vlm->has_disk_alert())
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->alert.c_str());
                            }
                            else
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->norm.c_str());
                            }
                            const char* const disk_state_label = vlm->get_disk_state_label();
                            DrbdVolume::disk_state vlm_disk_state = vlm->get_disk_state();
                            dsp_comp_hub.dsp_io->write_text(disk_state_label);
                            if (vlm_disk_state == DrbdVolume::disk_state::DISKLESS)
                            {
                                if (vlm->has_disk_alert())
                                {
                                    dsp_comp_hub.dsp_io->write_text(" (Detached/Failed)");
                                }
                                else
                                {
                                    dsp_comp_hub.dsp_io->write_text(" (DRBD client)");
                                }
                            }
                            ++current_line;

                            dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
                            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
                            dsp_comp_hub.dsp_io->write_text("Replication state:");
                            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
                            dsp_comp_hub.dsp_io->cursor_xy(21, current_line);
                            if (vlm->has_replication_alert())
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->alert.c_str());
                            }
                            else
                            if (vlm->has_replication_warning())
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->warn.c_str());
                            }
                            else
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->norm.c_str());
                            }
                            const char* const repl_state_label = vlm->get_replication_state_label();
                            dsp_comp_hub.dsp_io->write_text(repl_state_label);
                            ++current_line;

                            dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
                            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->emphasis_text.c_str());
                            dsp_comp_hub.dsp_io->write_text("Quorum:");
                            dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
                            dsp_comp_hub.dsp_io->cursor_xy(21, current_line);
                            if (vlm->has_quorum_alert())
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->alert.c_str());
                                dsp_comp_hub.dsp_io->write_text("No");
                            }
                            else
                            {
                                dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->norm.c_str());
                                dsp_comp_hub.dsp_io->write_text("Yes");
                            }

                            if (is_action_available())
                            {
                                current_line += 2;
                                dsp_comp_hub.dsp_io->cursor_xy(1, current_line);
                                if (dsp_comp_hub.enable_drbd_actions)
                                {
                                    dsp_comp_hub.dsp_io->write_text(
                                        dsp_comp_hub.active_color_table->hotkey_field.c_str()
                                    );
                                    dsp_comp_hub.dsp_io->write_text(" A ");
                                    dsp_comp_hub.dsp_io->write_text(
                                        dsp_comp_hub.active_color_table->hotkey_label.c_str()
                                    );
                                    dsp_comp_hub.dsp_io->write_text(" Actions");
                                }
                                else
                                {
                                    dsp_comp_hub.dsp_io->write_text(dsp_comp_hub.active_color_table->rst.c_str());
                                    dsp_comp_hub.dsp_io->write_text("[Actions disabled]");
                                }

                                if (current_line != saved_options_line)
                                {
                                    clear_options();
                                    options_configured = false;
                                }

                                if (!options_configured)
                                {
                                    cmd_actions->clickable_area.row = current_line;

                                    add_option_clickable(*cmd_actions);

                                    saved_options_line = current_line;
                                    options_configured = true;
                                }
                            }
                        }
                        else
                        {
                            dsp_comp_hub.dsp_io->write_text("Volume not active");
                        }
                    }
                    else
                    {
                        dsp_comp_hub.dsp_io->write_text("Connection not active");
                    }
                }
                else
                {
                    dsp_comp_hub.dsp_io->write_text("Resource not active");
                }
            }
            else
            {
                dsp_comp_hub.dsp_io->write_text("No selected volume");
            }
        }
        else
        {
            dsp_comp_hub.dsp_io->write_text("No selected connection");
        }
    }
    else
    {
        dsp_comp_hub.dsp_io->write_text("No selected resource");
    }
}

uint64_t MDspPeerVolumeDetail::get_update_mask() noexcept
{
    return update_event::UPDATE_FLAG_DRBD;
}

bool MDspPeerVolumeDetail::key_pressed(const uint32_t key)
{
    // Skip MDspMenuBase, not using the option field
    bool intercepted = MDspBase::key_pressed(key);
    if (!intercepted)
    {
        if (key == KeyCodes::FUNC_01)
        {
            helptext::open_help_page(helptext::id_type::PVLM_DETAIL, dsp_comp_hub);
            intercepted = true;
        }
        else
        if (key == static_cast<uint32_t> ('A') || key == static_cast<uint32_t> ('a'))
        {
            opt_actions();
            intercepted = true;
        }
    }
    return intercepted;
}

void MDspPeerVolumeDetail::text_cursor_ops()
{
    // no-op; prevents MDspMenuBase from positioning the cursor for the option field, which is not used
}

void MDspPeerVolumeDetail::display_activated()
{
    MDspBase::display_activated();
    dsp_comp_hub.dsp_shared->ovrd_peer_volume_selection = true;
}

void MDspPeerVolumeDetail::display_deactivated()
{
    MDspBase::display_deactivated();
    clear_options();
    options_configured = false;
}

void MDspPeerVolumeDetail::opt_actions()
{
    if (is_action_available() && dsp_comp_hub.enable_drbd_actions)
    {
        dsp_comp_hub.dsp_selector->switch_to_display(DisplayId::display_page::PEER_VLM_ACTIONS);
    }
}

bool MDspPeerVolumeDetail::is_action_available()
{
    bool available = false;
    const uint16_t vlm_nr = dsp_comp_hub.dsp_shared->monitor_peer_vlm;
    if (vlm_nr != DisplayConsts::VLM_NONE)
    {
        DrbdConnection* const con = dsp_comp_hub.get_monitor_connection();
        if (con != nullptr)
        {
            DrbdConnection::state con_state = con->get_connection_state();
            if (con_state == DrbdConnection::state::CONNECTED)
            {
                DrbdVolume* const vlm = con->get_volume(dsp_comp_hub.dsp_shared->monitor_peer_vlm);
                if (vlm != nullptr)
                {
                    available = true;
                }
            }
        }
    }
    return available;
}
