// LAF Gfx Library
// Copyright (C) 2020  Igara Studio S.A.
// Copyright (C) 2001-2018  David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#ifndef GFX_SIZE_H_INCLUDED
#define GFX_SIZE_H_INCLUDED
#pragma once

#include <algorithm>

namespace gfx {

template<typename T>
class PointT;

// A 2D size.
template<typename T>
class SizeT {
public:
  T w, h;

  SizeT() : w(0), h(0) {}

  SizeT(const T& w, const T& h) : w(w), h(h) {}

  SizeT(const SizeT& size) : w(size.w), h(size.h) {}

  template<typename U>
  explicit SizeT(const SizeT<U>& size) : w(static_cast<T>(size.w))
                                       , h(static_cast<T>(size.h))
  {
  }

  explicit SizeT(const PointT<T>& point) : w(point.x), h(point.y) {}

  SizeT createUnion(const SizeT& sz) const { return SizeT(std::max(w, sz.w), std::max(h, sz.h)); }

  SizeT createIntersection(const SizeT& sz) const
  {
    return SizeT(std::min(w, sz.w), std::min(h, sz.h));
  }

  SizeT& operator=(const SizeT& sz)
  {
    w = sz.w;
    h = sz.h;
    return *this;
  }

  const SizeT& operator+=(const SizeT& sz)
  {
    w += sz.w;
    h += sz.h;
    return *this;
  }

  const SizeT& operator-=(const SizeT& sz)
  {
    w -= sz.w;
    h -= sz.h;
    return *this;
  }

  const SizeT& operator+=(const T& value)
  {
    w += value;
    h += value;
    return *this;
  }

  const SizeT& operator-=(const T& value)
  {
    w -= value;
    h -= value;
    return *this;
  }

  const SizeT& operator*=(const T& value)
  {
    w *= value;
    h *= value;
    return *this;
  }

  const SizeT& operator/=(const T& value)
  {
    w /= value;
    h /= value;
    return *this;
  }

  const SizeT& operator|=(const SizeT& sz) { return *this = createUnion(sz); }

  const SizeT& operator&=(const SizeT& sz) { return *this = createIntersection(sz); }

  SizeT operator+(const SizeT& sz) const { return SizeT(w + sz.w, h + sz.h); }

  SizeT operator-(const SizeT& sz) const { return SizeT(w - sz.w, h - sz.h); }

  SizeT operator+(const T& value) const { return SizeT(w + value, h + value); }

  SizeT operator-(const T& value) const { return SizeT(w - value, h - value); }

  SizeT operator*(const T& value) const { return SizeT(w * value, h * value); }

  SizeT operator/(const T& value) const { return SizeT(w / value, h / value); }

  SizeT operator-() const { return SizeT(-w, -h); }

  bool operator==(const SizeT& sz) const { return w == sz.w && h == sz.h; }

  bool operator!=(const SizeT& sz) const { return w != sz.w || h != sz.h; }
};

typedef SizeT<int> Size;
typedef SizeT<double> SizeF;

} // namespace gfx

#ifdef _DEBUG
  #include "gfx/size_io.h"
#endif

#endif
