// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "pdf/range_set.h"

#include <algorithm>
#include <sstream>
#include <vector>

namespace chrome_pdf {

namespace {

gfx::Range FixDirection(const gfx::Range& range) {
  if (!range.IsValid() || !range.is_reversed())
    return range;
  return gfx::Range(range.end() + 1, range.start() + 1);
}

}  // namespace

RangeSet::RangeSet() {}

RangeSet::RangeSet(const gfx::Range& range) {
  Union(range);
}

RangeSet::RangeSet(const RangeSet& range_set) : ranges_(range_set.ranges_) {}

RangeSet::RangeSet(RangeSet&& range_set)
    : ranges_(std::move(range_set.ranges_)) {}

RangeSet& RangeSet::operator=(const RangeSet& other) {
  ranges_ = other.ranges_;
  return *this;
}

RangeSet::~RangeSet() {}

bool RangeSet::operator==(const RangeSet& other) const {
  return other.ranges_ == ranges_;
}

bool RangeSet::operator!=(const RangeSet& other) const {
  return other.ranges_ != ranges_;
}

void RangeSet::Union(const gfx::Range& range) {
  if (range.is_empty())
    return;
  gfx::Range fixed_range = FixDirection(range);
  if (IsEmpty()) {
    ranges_.insert(fixed_range);
    return;
  }

  auto start = ranges_.upper_bound(fixed_range);
  if (start != ranges_.begin())
    --start;  // start now points to the key equal or lower than offset.
  if (start->end() < fixed_range.start())
    ++start;  // start element is entirely before current range, skip it.

  auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
  if (start == end) {  // No ranges to merge.
    ranges_.insert(fixed_range);
    return;
  }

  --end;

  int new_start = std::min<size_t>(start->start(), fixed_range.start());
  int new_end = std::max(end->end(), fixed_range.end());

  ranges_.erase(start, ++end);
  ranges_.insert(gfx::Range(new_start, new_end));
}

void RangeSet::Union(const RangeSet& range_set) {
  if (&range_set == this)
    return;
  for (const auto& it : range_set.ranges()) {
    Union(it);
  }
}

bool RangeSet::Contains(uint32_t point) const {
  return Contains(gfx::Range(point, point + 1));
}

bool RangeSet::Contains(const gfx::Range& range) const {
  if (range.is_empty())
    return false;
  const gfx::Range fixed_range = FixDirection(range);
  auto it = ranges().upper_bound(fixed_range);
  if (it == ranges().begin())
    return false;  // No ranges includes range.start().

  --it;  // Now it starts equal or before range.start().
  return it->end() >= fixed_range.end();
}

bool RangeSet::Contains(const RangeSet& range_set) const {
  for (const auto& it : range_set.ranges()) {
    if (!Contains(it))
      return false;
  }
  return true;
}

bool RangeSet::Intersects(const gfx::Range& range) const {
  if (IsEmpty() || range.is_empty())
    return false;
  const gfx::Range fixed_range = FixDirection(range);
  auto start = ranges_.upper_bound(fixed_range);
  if (start != ranges_.begin()) {
    --start;
  }
  // start now points to the key equal or lower than range.start().
  if (start->end() < range.start()) {
    // start element is entirely before current range, skip it.
    ++start;
  }
  auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
  for (auto it = start; it != end; ++it) {
    if (fixed_range.end() > it->start() && fixed_range.start() < it->end())
      return true;
  }
  return false;
}

bool RangeSet::Intersects(const RangeSet& range_set) const {
  for (const auto& it : range_set.ranges()) {
    if (Intersects(it))
      return true;
  }
  return false;
}

void RangeSet::Intersect(const gfx::Range& range) {
  Intersect(RangeSet(range));
}

void RangeSet::Intersect(const RangeSet& range_set) {
  if (IsEmpty())
    return;
  RangesContainer new_ranges;
  for (const auto& range : range_set.ranges()) {
    auto start = ranges_.upper_bound(range);
    if (start != ranges_.begin())
      --start;  // start now points to the key equal or lower than
                // range.start().
    if (start->end() < range.start())
      ++start;  // start element is entirely before current range, skip it.
    auto end = ranges_.upper_bound(gfx::Range(range.end()));
    if (start == end) {  // No data in the current range available.
      continue;
    }
    for (auto it = start; it != end; ++it) {
      const gfx::Range new_range = range.Intersect(*it);
      if (!new_range.is_empty()) {
        new_ranges.insert(new_range);
      }
    }
  }
  new_ranges.swap(ranges_);
}

void RangeSet::Subtract(const gfx::Range& range) {
  if (range.is_empty() || IsEmpty())
    return;
  const gfx::Range fixed_range = FixDirection(range);
  auto start = ranges_.upper_bound(fixed_range);
  if (start != ranges_.begin())
    --start;  // start now points to the key equal or lower than
              // range.start().
  if (start->end() < fixed_range.start())
    ++start;  // start element is entirely before current range, skip it.
  auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
  if (start == end) {  // No data in the current range available.
    return;
  }
  std::vector<gfx::Range> new_ranges;
  for (auto it = start; it != end; ++it) {
    const gfx::Range left(it->start(),
                          std::min(it->end(), fixed_range.start()));
    const gfx::Range right(std::max(it->start(), fixed_range.end()), it->end());
    if (!left.is_empty() && !left.is_reversed()) {
      new_ranges.push_back(left);
    }
    if (!right.is_empty() && !right.is_reversed() && right != left) {
      new_ranges.push_back(right);
    }
  }
  ranges_.erase(start, end);
  for (const auto& it : new_ranges) {
    ranges_.insert(it);
  }
}

void RangeSet::Subtract(const RangeSet& range_set) {
  if (&range_set == this) {
    ranges_.clear();
    return;
  }
  for (const auto& range : range_set.ranges()) {
    Subtract(range);
  }
}

void RangeSet::Xor(const gfx::Range& range) {
  Xor(RangeSet(range));
}

void RangeSet::Xor(const RangeSet& range_set) {
  RangeSet tmp = *this;
  tmp.Intersect(range_set);
  Union(range_set);
  Subtract(tmp);
}

bool RangeSet::IsEmpty() const {
  return ranges().empty();
}

void RangeSet::Clear() {
  ranges_.clear();
}

gfx::Range RangeSet::First() const {
  return *ranges().begin();
}

gfx::Range RangeSet::Last() const {
  return *ranges().rbegin();
}

std::string RangeSet::ToString() const {
  std::stringstream ss;
  ss << "{";
  for (const auto& it : ranges()) {
    ss << "[" << it.start() << "," << it.end() << ")";
  }
  ss << "}";
  return ss.str();
}

}  // namespace chrome_pdf

std::ostream& operator<<(std::ostream& os,
                         const chrome_pdf::RangeSet& range_set) {
  return (os << range_set.ToString());
}
