/*
*Copyright(c)2016, Jeffrey Lee
*Allrightsreserved.
*
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met: 
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdio.h>

#include "raw.h"
#include "pixtrans.h"
#include "proto.h"

int raw_num_rects(vncserv *serv, const area *rect)
{
  return 1;
}

bool raw_send(vncserv *serv, send_rect_state *state, raw_temp_buffer *temp)
{
  if (vncserv_get_tx_space(serv) < RAW_BUFFER_SIZE + sizeof(rect_header))
  {
    return false;
  }

  /* Write rect header if this is the first call */
  if (state->x == -1)
  {
    rect_header rect;
    rect.x = Swap16IfLE(state->rect.x);
    rect.y = Swap16IfLE(state->rect.y);
    rect.w = Swap16IfLE(state->rect.w);
    rect.h = Swap16IfLE(state->rect.h);
    rect.enc = Swap32IfLE(RAW_ENCODING);
    vncserv_write(serv, &rect, sizeof(rect));

    state->x = state->rect.x;
    state->y = state->rect.y;
  }

  int max_pixels = RAW_BUFFER_SIZE / (serv->clientformat.bits_per_pixel >> 3);
  int max_rows = max_pixels / state->rect.w;
  int send_pixels;

  if (!max_rows)
  {
    /* Really wide rectangle, send a partial row at a time */
    int row_pixels = (state->rect.w + state->rect.x) - state->x;
    send_pixels = (row_pixels < max_pixels) ? row_pixels : max_pixels;
    pixtrans_do_it(serv, state->x, state->y, send_pixels, 1, temp->buf);
    state->x += send_pixels;
    if (state->x == state->rect.x + state->rect.w)
    {
      state->x = state->rect.x;
      state->y++;
    }
  }
  else
  {
    /* Send groups of full rows */
    int remaining = (state->rect.h + state->rect.y) - state->y;
    if (remaining < max_rows)
    {
      max_rows = remaining;
    }
    pixtrans_do_it(serv, state->x, state->y, state->rect.w, max_rows, temp->buf);
    state->y += max_rows;
    send_pixels = max_rows * state->rect.w;
  }

  if (state->y == state->rect.y + state->rect.h)
  {
    state->x = state->rect.x + state->rect.w;
  }

  vncserv_write(serv, temp->buf, send_pixels * (serv->clientformat.bits_per_pixel >> 3));

  return true;
}
