#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "areas.h"

#define min(x,y)  ((x) < (y)) ? (x) : (y)
#define max(x,y)  ((x) > (y)) ? (x) : (y)


void areas_intersection(const area *a1, const area* a2, area *out) {
  area out2;
  if (!areas_intersect(a1, a2)) {
    reset_area(out);
    return;
  }
  out2.x = max(a1->x, a2->x);
  out2.y = max(a1->y, a2->y);
  out2.w = min(a1->x+a1->w, a2->x+a2->w) - out2.x;
  out2.h = min(a1->y+a1->h, a2->y+a2->h) - out2.y;
  copy_area(out, &out2);
}

void areas_union(const area *a1, const area* a2, area *out) {
  int x0, y0, x1, y1;

  if (area_is_empty(a1)) {
    copy_area(out, a2);
    return;
  }
  if (area_is_empty(a2)) {
    copy_area(out, a1);
    return;
  }
  x0 = min(a1->x, a2->x);
  y0 = min(a1->y, a2->y);
  x1 = max(a1->x+a1->w, a2->x+a2->w);
  y1 = max(a1->y+a1->h, a2->y+a2->h);
  out->x = x0;
  out->y = y0;
  out->w = x1-x0;
  out->h = y1-y0;
}

int areas_intersect(const area *a1, const area* a2) {
  if (area_is_empty(a1))       return 0;
  if (area_is_empty(a2))       return 0;
  if (a1->x > a2->x+a2->w)     return 0;
  if (a1->y > a2->y+a2->h)     return 0;
  if (a2->x > a1->x+a1->w)     return 0;
  if (a2->y > a1->y+a1->h)     return 0;
  return 1;
}

int area_encloses(const area *a1, const area* a2) {
  if (a2->x >= a1->x             &&
      a2->y >= a1->y             &&
      a2->x+a2->w <= a1->x+a1->w &&
      a2->y+a2->h <= a1->y+a1->h)  return 1;
  return 0;
}
