/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "config.h"

#include "common/clipboard.h"
#include "terminal/buffer.h"
#include "terminal/display.h"
#include "terminal/select.h"
#include "terminal/terminal.h"
#include "terminal/types.h"

#include <guacamole/client.h>
#include <guacamole/socket.h>
#include <guacamole/unicode.h>

#include <stdbool.h>

/**
 * Returns the coordinates for the currently-selected range of text within the
 * given terminal, normalized such that the start coordinate is before the end
 * coordinate and the end coordinate takes into account character width. If no
 * text is currently selected, the behavior of this function is undefined.
 *
 * @param terminal
 *     The guac_terminal instance whose selected text coordinates should be
 *     retrieved in normalized form.
 *
 * @param start_row
 *     A pointer to an int which should receive the row number of the first
 *     character of text selected within the terminal, where the first
 *     (top-most) row in the terminal is row 0. Rows within the scrollback
 *     buffer (above the top-most row of the terminal) will be negative.
 *
 * @param start_col
 *     A pointer to an int which should receive the column number of the first
 *     character of text selected within terminal, where 0 is the first
 *     (left-most) column within the row.
 *
 * @param end_row
 *     A pointer to an int which should receive the row number of the last
 *     character of text selected within the terminal, where the first
 *     (top-most) row in the terminal is row 0. Rows within the scrollback
 *     buffer (above the top-most row of the terminal) will be negative.
 *
 * @param end_col
 *     A pointer to an int which should receive the column number of the first
 *     character of text selected within terminal, taking into account the
 *     width of that character, where 0 is the first (left-most) column within
 *     the row.
 */
static void guac_terminal_select_normalized_range(guac_terminal* terminal,
        int* start_row, int* start_col, int* end_row, int* end_col) {

    /* Pass through start/end coordinates if they are already in the expected
     * order, adjusting only for final character width */
    if (terminal->selection_start_row < terminal->selection_end_row
        || (terminal->selection_start_row == terminal->selection_end_row
            && terminal->selection_start_column < terminal->selection_end_column)) {

        *start_row = terminal->selection_start_row;
        *start_col = terminal->selection_start_column;
        *end_row   = terminal->selection_end_row;
        *end_col   = terminal->selection_end_column + terminal->selection_end_width - 1;

    }

    /* Coordinates must otherwise be swapped in addition to adjusting for
     * final character width */
    else {
        *end_row   = terminal->selection_start_row;
        *end_col   = terminal->selection_start_column + terminal->selection_start_width - 1;
        *start_row = terminal->selection_end_row;
        *start_col = terminal->selection_end_column;
    }

}

void guac_terminal_select_redraw(guac_terminal* terminal) {

    /* Update the selected region of the display if text is currently
     * selected */
    if (terminal->text_selected) {

        int start_row = terminal->selection_start_row + terminal->scroll_offset;
        int start_column = terminal->selection_start_column;

        int end_row = terminal->selection_end_row + terminal->scroll_offset;
        int end_column = terminal->selection_end_column;

        /* Update start/end columns to include character width */
        if (start_row > end_row || (start_row == end_row && start_column > end_column))
            start_column += terminal->selection_start_width - 1;
        else
            end_column += terminal->selection_end_width - 1;

        guac_terminal_display_select(terminal->display, start_row, start_column, end_row, end_column);

    }

    /* Clear the display selection if no text is currently selected */
    else
        guac_terminal_display_clear_select(terminal->display);

}

/**
 * Locates the beginning of the character at the given row and column, updating
 * the column to the starting column of that character. The width, if available,
 * is returned. If the character has no defined width, 1 is returned.
 *
 * @param terminal
 *     The guac_terminal in which the character should be located.
 *
 * @param row
 *     The row number of the desired character, where the first (top-most) row
 *     in the terminal is row 0. Rows within the scrollback buffer (above the
 *     top-most row of the terminal) will be negative.
 *
 * @param column
 *     A pointer to an int containing the column number of the desired
 *     character, where 0 is the first (left-most) column within the row. If
 *     the character is a multi-column character, the value of this int will be
 *     adjusted as necessary such that it contains the column number of the
 *     first column containing the character.
 *
 * @return
 *     The width of the specified character, in columns, or 1 if the character
 *     has no defined width.
 */
static int guac_terminal_find_char(guac_terminal* terminal,
        int row, int* column) {

    int start_column = *column;

    guac_terminal_buffer_row* buffer_row = guac_terminal_buffer_get_row(terminal->buffer, row, 0);
    if (start_column < buffer_row->length) {

        /* Find beginning of character */
        guac_terminal_char* start_char = &(buffer_row->characters[start_column]);
        while (start_column > 0 && start_char->value == GUAC_CHAR_CONTINUATION) {
            start_char--;
            start_column--;
        }

        /* Use width, if available */
        if (start_char->value != GUAC_CHAR_CONTINUATION) {
            *column = start_column;
            return start_char->width;
        }

    }

    /* Default to one column wide */
    return 1;

}

void guac_terminal_select_start(guac_terminal* terminal, int row, int column) {

    int width = guac_terminal_find_char(terminal, row, &column);

    terminal->selection_start_row =
    terminal->selection_end_row   = row;

    terminal->selection_start_column =
    terminal->selection_end_column   = column;

    terminal->selection_start_width =
    terminal->selection_end_width   = width;

    terminal->text_selected = false;
    terminal->selection_committed = false;
    guac_terminal_notify(terminal);

}

void guac_terminal_select_update(guac_terminal* terminal, int row, int column) {

    /* Only update if selection has changed */
    if (row != terminal->selection_end_row
        || column <  terminal->selection_end_column
        || column >= terminal->selection_end_column + terminal->selection_end_width) {

        int width = guac_terminal_find_char(terminal, row, &column);

        terminal->selection_end_row = row;
        terminal->selection_end_column = column;
        terminal->selection_end_width = width;
        terminal->text_selected = true;

        guac_terminal_notify(terminal);

    }

}

void guac_terminal_select_resume(guac_terminal* terminal, int row, int column) {

    int selection_start_row;
    int selection_start_column;
    int selection_end_row;
    int selection_end_column;

    /* No need to test coordinates if no text is selected at all */
    if (!terminal->text_selected)
        return;

    /* Use normalized coordinates for sake of simple comparison */
    guac_terminal_select_normalized_range(terminal,
            &selection_start_row, &selection_start_column,
            &selection_end_row, &selection_end_column);

    /* Prefer to expand from start, such that attempting to resume a selection
     * within the existing selection preserves the top-most portion of the
     * selection */
    if (row > selection_start_row ||
            (row == selection_start_row && column > selection_start_column)) {
        terminal->selection_start_row = selection_start_row;
        terminal->selection_start_column = selection_start_column;
    }

    /* Expand from bottom-most portion of selection if doing otherwise would
     * reduce the size of the selection */
    else {
        terminal->selection_start_row = selection_end_row;
        terminal->selection_start_column = selection_end_column;
    }

    /* Selection is again in-progress */
    terminal->selection_committed = false;

    /* Update selection to contain given character */
    guac_terminal_select_update(terminal, row, column);

}

/**
 * Appends the text within the given subsection of a terminal row to the
 * clipboard. The provided coordinates are considered inclusiveley (the
 * characters at the start and end column are included in the copied
 * text). Any out-of-bounds coordinates will be automatically clipped within
 * the bounds of the given row.
 *
 * @param terminal
 *     The guac_terminal instance associated with the buffer containing the
 *     text being copied and the clipboard receiving the copied text.
 *
 * @param row
 *     The row number of the text within the terminal to be copied into the
 *     clipboard, where the first (top-most) row in the terminal is row 0. Rows
 *     within the scrollback buffer (above the top-most row of the terminal)
 *     will be negative.
 *
 * @param start
 *     The first column of the text to be copied from the given row into the
 *     clipboard associated with the given terminal, where 0 is the first
 *     (left-most) column within the row.
 *
 * @param end
 *     The last column of the text to be copied from the given row into the
 *     clipboard associated with the given terminal, where 0 is the first
 *     (left-most) column within the row, or a negative value to denote that
 *     the last column in the row should be used.
 */
static void guac_terminal_clipboard_append_row(guac_terminal* terminal,
        int row, int start, int end) {

    char buffer[1024];
    int i = start;

    guac_terminal_buffer_row* buffer_row =
        guac_terminal_buffer_get_row(terminal->buffer, row, 0);

    /* If selection is entirely outside the bounds of the row, then there is
     * nothing to append */
    if (start < 0 || start > buffer_row->length - 1)
        return;

    /* Clip given range to actual bounds of row */
    if (end < 0 || end > buffer_row->length - 1)
        end = buffer_row->length - 1;

    /* Repeatedly convert chunks of terminal buffer rows until entire specified
     * region has been appended to clipboard */
    while (i <= end) {

        int remaining = sizeof(buffer);
        char* current = buffer;

        /* Convert as many codepoints within the given range as possible */
        for (i = start; i <= end; i++) {

            int codepoint = buffer_row->characters[i].value;

            /* Ignore null (blank) characters */
            if (codepoint == 0 || codepoint == GUAC_CHAR_CONTINUATION)
                continue;

            /* Encode current codepoint as UTF-8 */
            int bytes = guac_utf8_write(codepoint, current, remaining);
            if (bytes == 0)
                break;

            current += bytes;
            remaining -= bytes;

        }

        /* Append converted buffer to clipboard */
        guac_common_clipboard_append(terminal->clipboard, buffer, current - buffer);

    }

}

void guac_terminal_select_end(guac_terminal* terminal) {

    guac_client* client = terminal->client;
    guac_socket* socket = client->socket;

    /* If no text is selected, nothing to do */
    if (!terminal->text_selected)
        return;

    /* Selection is now committed */
    terminal->selection_committed = true;

    /* Reset current clipboard contents */
    guac_common_clipboard_reset(terminal->clipboard, "text/plain");

    int start_row, start_col;
    int end_row, end_col;

    /* Ensure proper ordering of start and end coords */
    guac_terminal_select_normalized_range(terminal,
            &start_row, &start_col, &end_row, &end_col);

    /* If only one row, simply copy */
    if (end_row == start_row)
        guac_terminal_clipboard_append_row(terminal, start_row, start_col, end_col);

    /* Otherwise, copy multiple rows */
    else {

        /* Store first row */
        guac_terminal_clipboard_append_row(terminal, start_row, start_col, -1);

        /* Store all middle rows */
        for (int row = start_row + 1; row < end_row; row++) {
            guac_common_clipboard_append(terminal->clipboard, "\n", 1);
            guac_terminal_clipboard_append_row(terminal, row, 0, -1);
        }

        /* Store last row */
        guac_common_clipboard_append(terminal->clipboard, "\n", 1);
        guac_terminal_clipboard_append_row(terminal, end_row, 0, end_col);

    }

    /* Send data */
    if (!terminal->disable_copy) {
        guac_common_clipboard_send(terminal->clipboard, client);
        guac_socket_flush(socket);
    }

    guac_terminal_notify(terminal);

}

bool guac_terminal_select_contains(guac_terminal* terminal,
        int start_row, int start_column, int end_row, int end_column) {

    int selection_start_row;
    int selection_start_column;
    int selection_end_row;
    int selection_end_column;

    /* No need to test coordinates if no text is selected at all */
    if (!terminal->text_selected)
        return false;

    /* Use normalized coordinates for sake of simple comparison */
    guac_terminal_select_normalized_range(terminal,
            &selection_start_row, &selection_start_column,
            &selection_end_row, &selection_end_column);

    /* If test range starts after highlight ends, does not intersect */
    if (start_row > selection_end_row)
        return false;

    if (start_row == selection_end_row && start_column > selection_end_column)
        return false;

    /* If test range ends before highlight starts, does not intersect */
    if (end_row < selection_start_row)
        return false;

    if (end_row == selection_start_row && end_column < selection_start_column)
        return false;

    /* Otherwise, does intersect */
    return true;

}

void guac_terminal_select_touch(guac_terminal* terminal,
        int start_row, int start_column, int end_row, int end_column) {

    /* Only clear selection if selection is committed */
    if (!terminal->selection_committed)
        return;

    /* Clear selection if it contains any characters within the given region */
    if (guac_terminal_select_contains(terminal, start_row, start_column,
                end_row, end_column)) {

        /* Text is no longer selected */
        terminal->text_selected = false;
        terminal->selection_committed = false;
        guac_terminal_notify(terminal);

    }

}

