// Copyright 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "../math/box_utility.ih"

#include "ValueRangesShared.h"

inline uniform ValueRanges make_ValueRanges_full()
{
  uniform ValueRanges valueRanges;

  valueRanges.numRanges          = 0;
  valueRanges.ranges             = NULL;
  valueRanges.rangesMinMax.lower = -inf;
  valueRanges.rangesMinMax.upper = inf;

  return valueRanges;
}

inline uniform bool valueRangesOverlap(const uniform ValueRanges &valueRanges,
                                       const uniform box1f &r)
{
  if (valueRanges.numRanges == 0) {
    return true;
  }

  if (overlaps1f(valueRanges.rangesMinMax, r)) {
    if (overlapsAny1f(r, valueRanges.numRanges, valueRanges.ranges)) {
      return true;
    }
  }

  return false;
}

inline varying bool valueRangesOverlap(const uniform ValueRanges &valueRanges,
                                       const varying box1f &r)
{
  if (valueRanges.numRanges == 0) {
    return true;
  }

  if (overlaps1f(valueRanges.rangesMinMax, r)) {
    if (overlapsAny1f(r, valueRanges.numRanges, valueRanges.ranges)) {
      return true;
    }
  }

  return false;
}

inline void ValueRanges_computeMinMax(uniform ValueRanges &valueRanges)
{
  valueRanges.rangesMinMax = make_box1f(inf, -inf);

  foreach (i = 0 ... valueRanges.numRanges) {
    valueRanges.rangesMinMax.lower =
        min(valueRanges.rangesMinMax.lower,
            reduce_min(valueRanges.ranges[i].lower));
    valueRanges.rangesMinMax.upper =
        max(valueRanges.rangesMinMax.upper,
            reduce_max(valueRanges.ranges[i].upper));
  }
}

inline void ValueRanges_Constructor(uniform ValueRanges &valueRanges,
                                    uniform int numRanges,
                                    const box1f *uniform ranges)
{
  ValueRanges_computeMinMax(valueRanges);
}

inline void ValueRanges_Constructor(uniform ValueRanges &valueRanges,
                                    uniform int numValues,
                                    const float *uniform values)
{
  valueRanges.numRanges = numValues;

  foreach (i = 0 ... numValues) {
    valueRanges.ranges[i].lower = values[i];
    valueRanges.ranges[i].upper = values[i];
  }

  ValueRanges_computeMinMax(valueRanges);
}

inline void ValueRanges_Destructor(uniform ValueRanges &valueRanges)
{
  valueRanges.ranges = NULL;
}
