#include <iostream>
#include <cstdio>

#include <CompactDisplay.h>
#include <DrbdMon.h>
#include <ConfigOption.h>

#include <cstring>
#include <cstdio>
#include <cstdarg>

extern "C"
{
    #include <pthread.h>
    #include <errno.h>
}

const std::string CompactDisplay::OPT_NO_HEADER_KEY("no-header");
const std::string CompactDisplay::OPT_NO_HOTKEYS_KEY("no-hotkeys");
const std::string CompactDisplay::OPT_ASCII_KEY("ascii");

const std::string CompactDisplay::HDR_SPACER(" | ");
const std::string CompactDisplay::NODE_DSP_PREFIX("Node ");
const std::string CompactDisplay::TRUNC_MARKER("...");

const ConfigOption CompactDisplay::OPT_NO_HEADER(true, OPT_NO_HEADER_KEY);
const ConfigOption CompactDisplay::OPT_NO_HOTKEYS(true, OPT_NO_HOTKEYS_KEY);
const ConfigOption CompactDisplay::OPT_ASCII(true, OPT_ASCII_KEY);

// Generic formats
const char* CompactDisplay::F_NORM  = "\x1b[0;32m";
const char* CompactDisplay::F_WARN  = "\x1b[1;33;45m";
const char* CompactDisplay::F_ALERT = "\x1b[1;33;41m";
const char* CompactDisplay::F_RESET = "\x1b[0m";

const char* CompactDisplay::F_MARK  = "\x1b[1;33;41m";

const char* CompactDisplay::F_HEADER= "\x1b[1;37;44m";

const char* CompactDisplay::F_RES_NORM   = "\x1b[0;30;42m";
const char* CompactDisplay::F_VOL_NORM   = "\x1b[0;30;46m";
const char* CompactDisplay::F_VOL_CLIENT = "\x1b[0;1;37;44m";
const char* CompactDisplay::F_VOL_MINOR  = "\x1b[0;4;36m";
const char* CompactDisplay::F_CONN_NORM  = "\x1b[0;37;44m";
const char* CompactDisplay::F_PRIMARY    = "\x1b[1;36m";
const char* CompactDisplay::F_SECONDARY  = "\x1b[0;36m";

// Foreground color for the 'Primary' role highlighting
// of connections (peer resource role)
const char* CompactDisplay::F_CONN_PRI_FG = "\x1b[1;36;44m";

const char* CompactDisplay::F_RES_NAME   = "\x1b[0;4;32m";
const char* CompactDisplay::F_RES_COUNT  = "\x1b[0;32mResources: %6llu\x1b[0m";
const char* CompactDisplay::F_PRB_COUNT  = "\x1b[0;1;31m (%llu degraded)\x1b[0m";

const char* CompactDisplay::F_CURSOR_POS = "\x1b[%u;%uH";
const char* CompactDisplay::F_HOTKEY     = "\x1b[0;30;47m%c\x1b[0;37;44m %s \033[0m";
const char* CompactDisplay::F_ALERT_HOTKEY = "\x1b[0;30;47m%c\x1b[1;33;41m %s \033[0m";

const char* CompactDisplay::UTF8_PRIMARY   = "\xE2\x9A\xAB";
const char* CompactDisplay::UTF8_SECONDARY = " "; // otherwise UTF-8 E2 9A AA
const char* CompactDisplay::UTF8_CONN_GOOD = "\xE2\x87\x84";
const char* CompactDisplay::UTF8_CONN_BAD  = "\xE2\x86\xAF";
const char* CompactDisplay::UTF8_DISK_GOOD = "\xE2\x97\x8E";
const char* CompactDisplay::UTF8_DISK_BAD  = "\xE2\x9C\x97";
const char* CompactDisplay::UTF8_MARK_OFF  = "\xE2\x9A\xAC";
const char* CompactDisplay::UTF8_MARK_ON   = "\xE2\xA4\xB7";

const char* CompactDisplay::ASCII_PRIMARY   = "*";
const char* CompactDisplay::ASCII_SECONDARY = " ";
const char* CompactDisplay::ASCII_CONN_GOOD = "+";
const char* CompactDisplay::ASCII_CONN_BAD  = "/";
const char* CompactDisplay::ASCII_DISK_GOOD = "+";
const char* CompactDisplay::ASCII_DISK_BAD  = "/";
const char* CompactDisplay::ASCII_MARK_OFF  = " ";
const char* CompactDisplay::ASCII_MARK_ON   = "+";

const char* CompactDisplay::ANSI_CLEAR      = "\x1b[H\x1b[2J";
const char* CompactDisplay::ANSI_CLEAR_LINE = "\x1b[K";

const char* CompactDisplay::ANSI_CURSOR_OFF = "\x1b[?25l";
const char* CompactDisplay::ANSI_CURSOR_ON  = "\x1b[?25h";

const char CompactDisplay::HOTKEY_PGUP = '<';
const char CompactDisplay::HOTKEY_PGDN = '>';
const char CompactDisplay::HOTKEY_PGZERO = '1';

const std::string CompactDisplay::LABEL_MESSAGES    = "Messages";
const std::string CompactDisplay::LABEL_MONITOR     = "Monitor";
const std::string CompactDisplay::LABEL_PROBLEMS    = "Problems";
const std::string CompactDisplay::LABEL_STATUS      = "Status";
const std::string CompactDisplay::LABEL_PGUP        = "PgUp";
const std::string CompactDisplay::LABEL_PGDN        = "PgDn";
const std::string CompactDisplay::LABEL_PGZERO      = "Pg1";

const uint16_t CompactDisplay::MIN_SIZE_X =   40;
const uint16_t CompactDisplay::MAX_SIZE_X = 1024;
const uint16_t CompactDisplay::MIN_SIZE_Y =   15;
const uint16_t CompactDisplay::MAX_SIZE_Y = 1024;

const int CompactDisplay::RES_NAME_WIDTH   = 32;
const int CompactDisplay::ROLE_WIDTH       = 10;
const int CompactDisplay::VOL_NR_WIDTH     = 2;
const int CompactDisplay::MINOR_NR_WIDTH   = 4;
const int CompactDisplay::CONN_NAME_WIDTH  = 20;
const int CompactDisplay::CONN_STATE_WIDTH = 20;
const int CompactDisplay::DISK_STATE_WIDTH = 20;
const int CompactDisplay::REPL_STATE_WIDTH = 20;

const uint16_t CompactDisplay::INDENT_STEP_SIZE     = 4;
const uint16_t CompactDisplay::OUTPUT_BUFFER_SIZE   = 1024;

const uint16_t CompactDisplay::MIN_NODENAME_DSP_LENGTH = 4;
const uint32_t CompactDisplay::MAX_YIELD_LOOP = 10;

// @throws std::bad_alloc
CompactDisplay::CompactDisplay(
    ResourcesMap& resources_map_ref,
    MessageLog&   log_ref,
    HotkeysMap&   hotkeys_info_ref,
    const std::string* const node_name_ref
):
    resources_map(resources_map_ref),
    log(log_ref),
    hotkeys_info(hotkeys_info_ref),
    node_name(node_name_ref)
{
    // Allocate and initialize the indent buffer
    indent_buffer_mgr = std::unique_ptr<char[]>(new char[INDENT_STEP_SIZE + 1]);
    indent_buffer = indent_buffer_mgr.get();
    for (size_t index = 0; index < INDENT_STEP_SIZE; ++index)
    {
        indent_buffer[index] = ' ';
    }
    indent_buffer[INDENT_STEP_SIZE] = '\0';

    output_buffer_mgr = std::unique_ptr<char[]>(new char[OUTPUT_BUFFER_SIZE]);
    output_buffer = output_buffer_mgr.get();

    // Hide the cursor
    write_text(ANSI_CURSOR_OFF);

    hotkeys_info.append(&HOTKEY_PGZERO, &LABEL_PGZERO);
    hotkeys_info.append(&HOTKEY_PGUP, &LABEL_PGUP);
    hotkeys_info.append(&HOTKEY_PGDN, &LABEL_PGDN);

    node_label = std::unique_ptr<std::string>(new std::string(HDR_SPACER));
    *node_label += NODE_DSP_PREFIX;
}

CompactDisplay::~CompactDisplay() noexcept
{
    // Show the cursor
    write_text(ANSI_CURSOR_ON);
}

void CompactDisplay::clear()
{
    write_text(ANSI_CLEAR);

    current_x = 0;
    current_y = 0;
}

void CompactDisplay::initial_display()
{
    clear();
    display_header();

    if (log.has_entries() && dsp_msg_active)
    {
        log.display_messages(stdout);
    }
    else
    {
        if (!log.has_entries())
        {
            dsp_msg_active = false;
        }

        write_fmt("%sReading initial DRBD status...%s\n", F_RES_NAME, F_RESET);
    }

    // End line
    next_line();

    display_hotkeys_info();
}

void CompactDisplay::status_display()
{
    uint32_t current_page = page;
    page_start = (term_y - 4) * current_page;
    page_end   = (term_y - 4) * (current_page + 1) - 1;

    prepare_flags();
    clear();
    display_header();

    if (log.has_entries() && dsp_msg_active)
    {
        log.display_messages(stdout);
    }
    else
    {
        if (!log.has_entries())
        {
            dsp_msg_active = false;
        }

        bool resources_listed = list_resources();
        if (!resources_listed)
        {
            if (dsp_problems_active)
            {
                write_fmt("%sNo resources with problems to display.%s\n", F_RES_NAME, F_RESET);
            }
            else
            {
                write_fmt("%sNo active DRBD resources.%s\n", F_RES_NAME, F_RESET);
            }
        }
    }

    // End line
    next_line();

    display_counts();

    display_hotkeys_info();
}

void CompactDisplay::display_header() const
{
    if (show_header)
    {
        write_fmt("%s%s%s v%s", F_HEADER, ANSI_CLEAR_LINE,
                  DrbdMon::PROGRAM_NAME.c_str(), DrbdMon::VERSION.c_str());

        if (node_name != nullptr)
        {
            if (enable_term_size)
            {
                // "%s v%s" format for PROGRAM_NAME and VERSION
                uint16_t x_pos = DrbdMon::PROGRAM_NAME.length() + DrbdMon::VERSION.length() + 2;
                if (term_x >= x_pos)
                {
                    uint16_t free_x = term_x - x_pos;
                    size_t label_length = node_label->length();
                    if (free_x >= label_length)
                    {
                        free_x -= label_length;
                        size_t name_length = node_name->length();
                        if (free_x > name_length)
                        {
                            // Entire node name fits on the header line
                            write_text(node_label->c_str());
                            write_text(node_name->c_str());
                        }
                        else
                        {
                            if (free_x > MIN_NODENAME_DSP_LENGTH + TRUNC_MARKER.length())
                            {
                                free_x -= TRUNC_MARKER.length() + 1;
                                // Minimum node name length and truncation marker fit on the header line
                                write_text(node_label->c_str());
                                size_t write_length = free_x < name_length ? free_x : name_length;
                                write_buffer(node_name->c_str(), write_length);
                                write_text(TRUNC_MARKER.c_str());
                            }
                        }
                    }
                }
            }
            else
            {
                write_text(node_label->c_str());
                write_text(node_name->c_str());
            }
        }
        write_char('\n');

        // Print right-aligned page number if the terminal size is known
        if (enable_term_size && term_y > MIN_SIZE_Y && term_x > 15)
        {
            write_fmt(F_CURSOR_POS, 2, static_cast<int> (term_x) - 15);
            write_text(F_RESET);
            write_fmt("Page %5lu\n", static_cast<long> (page) + 1);
        }
        else
        {
            write_char('\n');
        }
    }
}

void CompactDisplay::display_hotkeys_info() const
{
    if (show_hotkeys)
    {
        if (enable_term_size)
        {
            write_fmt(F_CURSOR_POS, static_cast<int> (term_y), 1);
        }

        HotkeysMap::NodesIterator hotkeys_iter(hotkeys_info);
        size_t count = hotkeys_iter.get_size();
        size_t index = 0;
        while (index < count)
        {
            HotkeysMap::Node* node = hotkeys_iter.next();
            const char hotkey = *(node->get_key());
            const std::string& description = *(node->get_value());
            if (index > 0)
            {
                write_char(' ');
            }
            write_fmt(F_HOTKEY, hotkey, description.c_str());
            ++index;
        }

        if (index > 0)
        {
            write_char(' ');
        }
        if (dsp_problems_active)
        {
            write_fmt(F_HOTKEY, 'p', LABEL_STATUS.c_str());
        }
        else
        {
            const char* format = problem_alert ? F_ALERT_HOTKEY : F_HOTKEY;
            write_fmt(format, 'p', LABEL_PROBLEMS.c_str());
        }

        if (dsp_msg_active)
        {
            if (index > 0)
            {
                write_char(' ');
            }
            write_fmt(F_HOTKEY, 'm', LABEL_MONITOR.c_str());
        }
        else
        if (log.has_entries())
        {
            if (index > 0)
            {
                write_char(' ');
            }
            write_fmt(F_ALERT_HOTKEY, 'm', LABEL_MESSAGES.c_str());
        }
        write_fmt(F_CURSOR_POS, 1, 1);
    }
}

void CompactDisplay::display_counts() const
{
    if (enable_term_size)
    {
        write_fmt(F_CURSOR_POS, static_cast<int> (term_y - 1), 1);
    }
    write_fmt(F_RES_COUNT, static_cast<unsigned long long> (resources_map.get_size()));
    if (problem_count > 0)
    {
        write_fmt(F_PRB_COUNT, static_cast<unsigned long long> (problem_count));
    }
}

void CompactDisplay::prepare_flags()
{
    problem_alert = false;
    problem_count = 0;
    ResourcesMap::ValuesIterator res_iter(resources_map);
    size_t res_count = res_iter.get_size();
    for (size_t res_index = 0; res_index < res_count; ++res_index)
    {
        DrbdResource& res = *(res_iter.next());
        if (res.update_state_flags() != StateFlags::state::NORM)
        {
            problem_alert = true;
            ++problem_count;
        }
    }
}

bool CompactDisplay::list_resources()
{
    bool resources_listed {false};

    // Reset columns tracking
    reset_positions();

    ResourcesMap::ValuesIterator res_iter(resources_map);
    size_t res_count = res_iter.get_size();
    for (size_t res_index = 0; res_index < res_count; ++res_index)
    {
        DrbdResource& res = *(res_iter.next());

        bool marked = res.has_mark_state();
        // If the problem display is active, show only resources that
        // are marked for having warnings or alerts
        if (!dsp_problems_active || marked)
        {
            resources_listed = true;

            // Setup view of the "RES:" label
            const char* f_res = F_RES_NORM;
            if (res.has_alert_state())
            {
                f_res = F_ALERT;
            }
            else
            if (res.has_warn_state())
            {
                f_res = F_WARN;
            }

            // Setup view of the sub-object warning mark
            const char* f_mark = F_RES_NORM;
            const char* mark_icon = mark_off;
            if (res.has_mark_state())
            {
                f_mark = F_MARK;
                mark_icon = mark_on;
            }

            // Setup view of the resource's role
            const char* f_role = F_SECONDARY;
            const char* role_icon = sec_icon;
            if (res.has_role_alert())
            {
                f_role = F_ALERT;
                role_icon = " ";
            }
            else
            if (res.get_role() == DrbdRole::resource_role::PRIMARY)
            {
                f_role = F_PRIMARY;
                role_icon = pri_icon;
            }

            next_line();
            // Marker (1) + "RES:" (4) + RES_NAME_WIDTH + " " (1) + role icon (1) + ROLE_WIDTH
            if (next_column(6 + RES_NAME_WIDTH + ROLE_WIDTH))
            {
                write_fmt(
                    "%s%s%sRES:%s%-*s%s %s%s%-*s%s",
                    f_mark, mark_icon, f_res, F_RES_NAME, RES_NAME_WIDTH, res.get_name().c_str(), F_RESET,
                    f_role, role_icon, ROLE_WIDTH, res.get_role_label(), F_RESET
                );
            }

            increase_indent();
            list_volumes(res);
            list_connections(res);
            decrease_indent();
        }
    }

    return resources_listed;
}

void CompactDisplay::list_connections(DrbdResource& res)
{
    // The connections list always starts on a new line
    next_line();

    // Short-display all connections that have a good state
    {
        ConnectionsMap::ValuesIterator conn_iter = res.connections_iterator();
        size_t conn_count = conn_iter.get_size();
        for (size_t conn_index = 0; conn_index < conn_count; ++conn_index)
        {
            DrbdConnection& conn = *(conn_iter.next());

            if (!conn.has_mark_state())
            {
                const char* f_conn = F_CONN_NORM;

                // Setup role icon & 'Primary' role highlighting format
                const char* f_role = F_CONN_NORM;
                const char* role_icon = sec_icon;
                if (conn.get_role() == DrbdRole::resource_role::PRIMARY)
                {
                    f_role = F_CONN_PRI_FG;
                    role_icon = pri_icon;
                }

                const std::string& conn_name = conn.get_name();

                // Mark (1) + connection icon (1) + role icon (1) + name length
                if (next_column(3 + conn_name.length()))
                {
                    write_fmt(
                        "%s%s%s%s%s%s%s",
                        f_conn, mark_off, conn_good, f_role, role_icon, conn_name.c_str(), F_RESET
                    );
                }
            }
        }
    }

    {
        ConnectionsMap::ValuesIterator conn_iter = res.connections_iterator();
        size_t conn_count = conn_iter.get_size();
        for (size_t conn_index = 0; conn_index < conn_count; ++conn_index)
        {
            DrbdConnection& conn = *(conn_iter.next());

            if (conn.has_mark_state())
            {
                // Setup connection view format
                const char* f_conn = F_CONN_NORM;
                if (conn.has_alert_state())
                {
                    f_conn = F_ALERT;
                }
                else
                if (conn.has_warn_state())
                {
                    f_conn = F_WARN;
                }

                // Setup connection state view format
                const char* f_conn_state = F_NORM;
                const char* conn_icon = conn_good;
                if (conn.has_connection_alert())
                {
                    f_conn_state = F_ALERT;
                    conn_icon = conn_bad;
                }

                // Setup role state view format
                const char* f_role = F_SECONDARY;
                const char* role_icon = sec_icon;
                if (conn.has_role_alert())
                {
                    f_role = F_ALERT;
                    role_icon = " ";
                }
                else
                if (conn.get_role() == DrbdRole::resource_role::PRIMARY)
                {
                    f_role = F_PRIMARY;
                    role_icon = pri_icon;
                }

                next_line();
                // Mark (1) + connection icon (1) + role icon (1) + CONN_NAME_WIDTH +
                // " " (1) + CONN_STATE_WIDTH + " " (1) + role icon (1) + ROLE_WIDTH
                if (next_column(6 + CONN_NAME_WIDTH + CONN_STATE_WIDTH + ROLE_WIDTH))
                {
                    write_fmt(
                        "%s%s%s%s%s%-*s%s %s%-*s%s %s%s%-*s%s",
                        F_MARK, mark_on, f_conn, conn_icon, role_icon, CONN_NAME_WIDTH,
                        conn.get_name().c_str(), F_RESET, f_conn_state, CONN_STATE_WIDTH,
                        conn.get_connection_state_label(), F_RESET, f_role, role_icon,
                        ROLE_WIDTH, conn.get_role_label(), F_RESET
                    );
                }

                increase_indent();
                list_peer_volumes(conn);
                decrease_indent();
            }
        }
    }
}

void CompactDisplay::list_volumes(DrbdResource& res)
{
    // Short-display all volumes that have a good state
    {
        VolumesMap::ValuesIterator vol_iter = res.volumes_iterator();
        size_t vol_count = vol_iter.get_size();
        for (size_t vol_index = 0; vol_index < vol_count; ++vol_index)
        {
            DrbdVolume& vol = *(vol_iter.next());

            if (!vol.has_warn_state())
            {
                show_volume(vol, false, false);
            }
        }
    }

    // Long-display all volumes that have a faulty state
    {
        VolumesMap::ValuesIterator vol_iter = res.volumes_iterator();
        size_t vol_count = vol_iter.get_size();
        for (size_t vol_index = 0; vol_index < vol_count; ++vol_index)
        {
            DrbdVolume& vol = *(vol_iter.next());

            if (vol.has_warn_state())
            {
                show_volume(vol, false, true);
            }
        }
    }
}

void CompactDisplay::list_peer_volumes(DrbdConnection& conn)
{
    VolumesMap::ValuesIterator peer_vol_iter = conn.volumes_iterator();
    size_t peer_vol_count = peer_vol_iter.get_size();
    for (size_t peer_vol_index = 0; peer_vol_index < peer_vol_count; ++peer_vol_index)
    {
        DrbdVolume& peer_vol = *(peer_vol_iter.next());

        if (peer_vol.has_warn_state())
        {
            show_volume(peer_vol, true, true);
        }
    }
}

void CompactDisplay::show_volume(DrbdVolume& vol, bool peer_volume, bool long_format)
{
    if (long_format)
    {
        // Long format view for volumes that have a faulty state

        // Set disk view format
        const char* f_disk = F_NORM;
        if (vol.has_disk_alert())
        {
            f_disk = F_ALERT;
        }

        // Set replication view format
        const char* f_repl = F_NORM;
        if (vol.has_replication_alert())
        {
            f_repl = F_ALERT;
        }
        else
        if (vol.has_replication_warning())
        {
            f_repl = F_WARN;
        }

        bool show_replication = peer_volume;
        if (peer_volume)
        {
            // Hide the 'Established' replication state
            if (vol.get_replication_state() == DrbdVolume::repl_state::ESTABLISHED)
            {
                show_replication = false;
            }
        }

        next_line();

        // Disk icon (1) + VOL_NR_WIDTH + " " (1) + DISK_STATE_WIDTH
        uint16_t vol_entry_width = 2 + VOL_NR_WIDTH + DISK_STATE_WIDTH;

        if (!peer_volume)
        {
            // Local volume, add in minor number fields
            // ":" (1) + MINOR_NR_WIDTH
            vol_entry_width += 1 + MINOR_NR_WIDTH;
        }

        if (show_replication)
        {
            // Add in replication state fields
            // " " (1) + REPL_STATE_WIDTH
            vol_entry_width += 1 + REPL_STATE_WIDTH;
        }

        bool show = next_column(vol_entry_width);

        if (show)
        {
            write_fmt(
                "%s%s%*ld",
                F_ALERT, disk_bad, VOL_NR_WIDTH, static_cast<long> (vol.get_volume_nr())
            );
        }

        // Hide the minor number of peer volumes, as it is always unknown
        if (!peer_volume && show)
        {
            // Display minor number
            write_fmt(":%s%*ld", F_VOL_MINOR, MINOR_NR_WIDTH, static_cast<long> (vol.get_minor_nr()));
        }

        // Display disk state
        if (show)
        {
            write_fmt(" %s %-*s%s", f_disk, DISK_STATE_WIDTH, vol.get_disk_state_label(), F_RESET);
        }

        if (show_replication && show)
        {
            // Display replication state
            write_fmt(
                " %s%-*s%s", f_repl, REPL_STATE_WIDTH,
                vol.get_replication_state_label(), F_RESET
            );
        }
    }
    else
    {
        // Short format view of volumes that have a good state
        const char* f_vol = F_VOL_NORM;
        if (vol.get_disk_state() == DrbdVolume::disk_state::DISKLESS)
        {
            f_vol = F_VOL_CLIENT;
        }

        // Disk icon (1) + VOL_NR_WIDTH + ":" (1) + MINOR_NR_WIDTH
        if (next_column(2 + VOL_NR_WIDTH + MINOR_NR_WIDTH))
        {
            write_fmt(
                "%s%s%s%s%*ld:%s%*ld%s",
                F_NORM, disk_good, F_RESET,
                f_vol, VOL_NR_WIDTH, static_cast<long> (vol.get_volume_nr()),
                F_VOL_MINOR, MINOR_NR_WIDTH, static_cast<long> (vol.get_minor_nr()), F_RESET
            );
        }
    }
}

void CompactDisplay::set_terminal_size(uint16_t size_x, uint16_t size_y)
{
    if (size_x >= MIN_SIZE_X)
    {
        if (size_x <= MAX_SIZE_X)
        {
            term_x = size_x;
        }
        else
        {
            term_x = MAX_SIZE_X;
        }
    }
    else
    {
        term_x = MIN_SIZE_X;
    }

    if (size_y >= MIN_SIZE_Y)
    {
        if (size_y <= MAX_SIZE_Y)
        {
            term_y = size_y;
        }
        else
        {
            term_y = MAX_SIZE_Y;
        }
    }
    else
    {
        term_y = MIN_SIZE_Y;
    }
}

void CompactDisplay::increase_indent()
{
    ++indent_level;
}

void CompactDisplay::decrease_indent()
{
    if (indent_level >= 1)
    {
        --indent_level;
    }
}

void CompactDisplay::reset_indent()
{
    indent_level = 0;
}

void CompactDisplay::reset_positions()
{
    reset_indent();
    current_x = 0;
    current_y = 0;
}

void CompactDisplay::indent()
{
    if (!(enable_term_size && term_y > MIN_SIZE_Y) ||
        (current_y >= page_start && current_y <= page_end))
    {
        for (uint16_t counter = 0; counter < indent_level; ++counter)
        {
            write_text(indent_buffer);
        }
    }
    current_x += INDENT_STEP_SIZE * indent_level;
}

bool CompactDisplay::next_column(uint16_t length)
{
    bool display_flag = false;
    if (enable_term_size && term_y > MIN_SIZE_Y)
    {
        display_flag = current_y >= page_start && current_y <= page_end;

        // If this column is at the start of a new line,
        // print the indent
        if (current_x == 0)
        {
            indent();
            current_x += length;
        }
        else
        {
            // Check whether the column fits in at the end
            // of the current line
            uint16_t end_x = current_x + length + 1;
            if (end_x < term_x)
            {
                if (display_flag)
                {
                    write_char(' ');
                }
                current_x = end_x;
            }
            else
            {
                next_line();
                display_flag = current_y >= page_start && current_y <= page_end;
                indent();
                current_x += length;
            }
        }
    }
    else
    {
        display_flag = true;
        if (current_x == 0)
        {
            indent();
            current_x += length;
        }
        else
        {
            // No terminal size restrictions,
            // allow an infinite number of columns
            write_char(' ');
        }
    }
    return display_flag;
}

void CompactDisplay::next_line()
{
    if (current_x > 0)
    {
        if (!(enable_term_size && term_y > MIN_SIZE_Y) ||
            (current_y >= page_start && current_y <= page_end))
        {
            write_char('\n');
        }
        current_x = 0;
        ++current_y;
    }
}

void CompactDisplay::set_utf8(bool enable)
{
    enable_utf8 = enable;
    if (enable_utf8)
    {
        pri_icon  = UTF8_PRIMARY;
        sec_icon  = UTF8_SECONDARY;
        conn_good = UTF8_CONN_GOOD;
        conn_bad  = UTF8_CONN_BAD;
        disk_good = UTF8_DISK_GOOD;
        disk_bad  = UTF8_DISK_BAD;
        mark_off  = UTF8_MARK_OFF;
        mark_on   = UTF8_MARK_ON;
    }
    else
    {
        pri_icon  = ASCII_PRIMARY;
        sec_icon  = ASCII_SECONDARY;
        conn_good = ASCII_CONN_GOOD;
        conn_bad  = ASCII_CONN_BAD;
        disk_good = ASCII_DISK_GOOD;
        disk_bad  = ASCII_DISK_BAD;
        mark_off  = ASCII_MARK_OFF;
        mark_on   = ASCII_MARK_ON;
    }
}

// @throws std::bad_alloc
void CompactDisplay::announce_options(Configurator& collector)
{
    Configurable& owner = dynamic_cast<Configurable&> (*this);
    collector.add_config_option(owner, OPT_NO_HEADER);
    collector.add_config_option(owner, OPT_NO_HOTKEYS);
    collector.add_config_option(owner, OPT_ASCII);
}

void CompactDisplay::options_help() noexcept
{
    std::fputs("DrbdMon display configuration options:\n", stderr);
    std::fputs("  --ascii          Use only ASCII characters (no Unicode)\n", stderr);
    std::fputs("  --no-header      Do not display the DrbdMon header line\n", stderr);
    std::fputs("  --no-hotkeys     Do not display the hotkeys line\n", stderr);
    std::fputc('\n', stderr);
    std::fflush(stderr);
}

// @throws std::bad_alloc
void CompactDisplay::set_flag(std::string& key)
{
    if (key == OPT_NO_HEADER.key)
    {
        show_header = false;
    }
    else
    if (key == OPT_NO_HOTKEYS.key)
    {
        show_hotkeys = false;
    }
    else
    if (key == OPT_ASCII.key)
    {
        set_utf8(false);
    }
}

// @throws std::bad_alloc
void CompactDisplay::set_option(std::string& key, std::string& value)
{
    // no-op; the CompactDisplay instance does not have any options
    // with configurable values at this time
}

void CompactDisplay::key_pressed(const char key)
{
    switch (key)
    {
        case '>':
            ++page;
            status_display();
            break;
        case '<':
            --page;
            status_display();
            break;
        case 'm':
            if (dsp_msg_active)
            {
                dsp_msg_active = false;
            }
            else
            if (log.has_entries())
            {
                dsp_msg_active = true;
            }
            status_display();
            break;
        case 'p':
            if (dsp_problems_active)
            {
                dsp_problems_active = false;
            }
            else
            {
                dsp_problems_active = true;
            }
            // fall-through
        case '1':
            page = 0;
            status_display();
            break;
        default:
            // no-op
            break;
    }
}

/**
 * Writes a single character to the output_fd file descriptor
 *
 * @param ch The character to write
 */
void CompactDisplay::write_char(const char ch) const noexcept
{
    // Repeat temporarily failing write() calls until the byte has been written
    uint32_t loop_guard {0};
    while (write(output_fd, static_cast<const void*> (&ch), 1) != 1)
    {
        if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
        {
            break;
        }

        if (loop_guard < MAX_YIELD_LOOP)
        {
            // Attempt to yield to other processes before retrying
            static_cast<void> (sched_yield());
            ++loop_guard;
        }
        else
        {
            // If yielding to other processes did not lead to any progress,
            // suspend for a while
            static_cast<void> (nanosleep(&write_retry_delay, nullptr));
        }
    }
}

/**
 * Writes a text string to the output_fd file descriptor
 *
 * @param text The text string to write
 */
void CompactDisplay::write_text(const char* text) const noexcept
{
    size_t length = std::strlen(text);
    write_buffer(text, length);
}

/**
 * Formats a text string and writes the result to the output_fd file descriptor
 *
 * @param format Format string
 * @param ... Arguments for the format string
 */
void CompactDisplay::write_fmt(const char* format, ...) const noexcept
{
    va_list vars;
    va_start(vars, format);
    size_t safe_length = 0;
    {
        size_t unsafe_length = vsnprintf(output_buffer, OUTPUT_BUFFER_SIZE, format, vars);
        safe_length = unsafe_length < OUTPUT_BUFFER_SIZE ? unsafe_length : OUTPUT_BUFFER_SIZE;
    }
    va_end(vars);
    write_buffer(output_buffer, safe_length);
}

/**
 * Writes buffered data to the output_fd file descriptor
 *
 * Write attempts that fail temporarily or are only partially successful are retried until the
 * all the buffered data has been written.
 *
 * @param buffer The buffered data to write
 * @param length Length of the buffered data in the (possibly larger) buffer
 */
void CompactDisplay::write_buffer(const char* buffer, size_t length) const noexcept
{
    uint32_t loop_guard {0};
    ssize_t written {0};
    while (length > 0)
    {
        // Repeat temporarily failing write() calls until the entire contents of the buffer have been written
        written = write(output_fd, static_cast<const void*> (buffer), length);
        if (written > 0)
        {
            length -= written;
        }
        else
        if (written == -1 && (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR))
        {
            break;
        }

        if (written <= 0)
        {
            if (loop_guard < MAX_YIELD_LOOP)
            {
                // Attempt to yield to other processes before retrying
                static_cast<void> (sched_yield());
                ++loop_guard;
            }
            else
            {
                // If yielding to other processes did not lead to any progress,
                // suspend for a while
                static_cast<void> (nanosleep(&write_retry_delay, nullptr));
            }
        }
    }
}
