/*
 * 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 "guac_rect.h"

void guac_common_rect_init(guac_common_rect* rect, int x, int y, int width, int height) {
    rect->x      = x;
    rect->y      = y;
    rect->width  = width;
    rect->height = height;
}

void guac_common_rect_extend(guac_common_rect* rect, const guac_common_rect* min) {

    /* Calculate extents of existing dirty rect */
    int left   = rect->x;
    int top    = rect->y;
    int right  = left + rect->width;
    int bottom = top  + rect->height;

    /* Calculate missing extents of given new rect */
    int min_left   = min->x;
    int min_top    = min->y;
    int min_right  = min_left + min->width;
    int min_bottom = min_top  + min->height;

    /* Update minimums */
    if (min_left   < left)   left   = min_left;
    if (min_top    < top)    top    = min_top;
    if (min_right  > right)  right  = min_right;
    if (min_bottom > bottom) bottom = min_bottom;

    /* Commit rect */
    guac_common_rect_init(rect, left, top, right - left, bottom - top);

}

void guac_common_rect_constrain(guac_common_rect* rect, const guac_common_rect* max) {

    /* Calculate extents of existing dirty rect */
    int left   = rect->x;
    int top    = rect->y;
    int right  = left + rect->width;
    int bottom = top  + rect->height;

    /* Calculate missing extents of given new rect */
    int max_left   = max->x;
    int max_top    = max->y;
    int max_right  = max_left + max->width;
    int max_bottom = max_top  + max->height;

    /* Update maximums */
    if (max_left   > left)   left   = max_left;
    if (max_top    > top)    top    = max_top;
    if (max_right  < right)  right  = max_right;
    if (max_bottom < bottom) bottom = max_bottom;

    /* Commit rect */
    guac_common_rect_init(rect, left, top, right - left, bottom - top);

}

int guac_common_rect_expand_to_grid(int cell_size, guac_common_rect* rect,
                                    const guac_common_rect* max_rect) {

    /* Invalid cell_size received */
    if (cell_size <= 0)
        return -1;

    /* Nothing to do */
    if (cell_size == 1)
        return 0;

    /* Calculate how much the rectangle must be adjusted to fit within the
     * given cell size. */
    int dw = cell_size - rect->width % cell_size;
    int dh = cell_size - rect->height % cell_size;

    int dx = dw / 2;
    int dy = dh / 2;

    /* Set initial extents of adjusted rectangle. */
    int top = rect->y - dy;
    int left = rect->x - dx;
    int bottom = top + rect->height + dh;
    int right = left + rect->width + dw;

    /* The max rectangle */
    int max_left   = max_rect->x;
    int max_top    = max_rect->y;
    int max_right  = max_left + max_rect->width;
    int max_bottom = max_top  + max_rect->height;

    /* If the adjusted rectangle has sides beyond the max rectangle, or is larger
     * in any direction; shift or adjust the rectangle while trying to fit in
     * the grid */

    /* Adjust left/right */
    if (right > max_right) {

        /* shift to left */
        dw = right - max_right;
        right -= dw;
        left -= dw;

        /* clamp left if too far */
        if (left < max_left) {
            left = max_left;
        }
    }
    else if (left < max_left) {

        /* shift to right */
        dw = max_left - left;
        left += dw;
        right += dw;

        /* clamp right if too far */
        if (right > max_right) {
            right = max_right;
        }
    }

    /* Adjust top/bottom */
    if (bottom > max_bottom) {

        /* shift up */
        dh = bottom - max_bottom;
        bottom -= dh;
        top -= dh;

        /* clamp top if too far */
        if (top < max_top) {
            top = max_top;
        }
    }
    else if (top < max_top) {

        /* shift down */
        dh = max_top - top;
        top += dh;
        bottom += dh;

        /* clamp bottom if too far */
        if (bottom > max_bottom) {
            bottom = max_bottom;
        }
    }

    /* Commit rect */
    guac_common_rect_init(rect, left, top, right - left, bottom - top);

    return 0;

}

int guac_common_rect_intersects(const guac_common_rect* rect,
                                const guac_common_rect* other) {

    /* Empty (no intersection) */
    if (other->x + other->width < rect->x || rect->x + rect->width < other->x ||
        other->y + other->height < rect->y || rect->y + rect->height < other->y) {
        return 0;
    }
    /* Complete */
    else if (other->x <= rect->x && (other->x + other->width) >= (rect->x + rect->width) &&
        other->y <= rect->y && (other->y + other->height) >= (rect->y + rect->height)) {
        return 2;
    }
    /* Partial intersection */
    return 1;

}

int guac_common_rect_clip_and_split(guac_common_rect* rect,
        const guac_common_rect* hole, guac_common_rect* split_rect) {

    /* Only continue if the rectangles intersects */
    if (!guac_common_rect_intersects(rect, hole))
        return 0;

    int top, left, bottom, right;

    /* Clip and split top */
    if (rect->y < hole->y) {
        top = rect->y;
        left = rect->x;
        bottom = hole->y;
        right = rect->x + rect->width;
        guac_common_rect_init(split_rect, left, top, right - left, bottom - top);

        /* Re-initialize original rect */
        top = hole->y;
        bottom = rect->y + rect->height;
        guac_common_rect_init(rect, left, top, right - left, bottom - top);

        return 1;
    }

    /* Clip and split left */
    else if (rect->x < hole->x) {
        top = rect->y;
        left = rect->x;
        bottom = rect->y + rect->height;
        right = hole->x;
        guac_common_rect_init(split_rect, left, top, right - left, bottom - top);

        /* Re-initialize original rect */
        left = hole->x;
        right = rect->x + rect->width;
        guac_common_rect_init(rect, left, top, right - left, bottom - top);

        return 1;
    }

    /* Clip and split bottom */
    else if (rect->y + rect->height > hole->y + hole->height) {
        top = hole->y + hole->height;
        left = rect->x;
        bottom = rect->y + rect->height;
        right = rect->x + rect->width;
        guac_common_rect_init(split_rect, left, top, right - left, bottom - top);

        /* Re-initialize original rect */
        top = rect->y;
        bottom = hole->y + hole->height;
        guac_common_rect_init(rect, left, top, right - left, bottom - top);

        return 1;
    }

    /* Clip and split right */
    else if (rect->x + rect->width > hole->x + hole->width) {
        top = rect->y;
        left = hole->x + hole->width;
        bottom = rect->y + rect->height;
        right = rect->x + rect->width;
        guac_common_rect_init(split_rect, left, top, right - left, bottom - top);

        /* Re-initialize original rect */
        left = rect->x;
        right = hole->x + hole->width;
        guac_common_rect_init(rect, left, top, right - left, bottom - top);

        return 1;
    }

    return 0;
}
