#include "num.h"
#include <utility>

Num::Num(int value, int modulo) : value(value), modulo(modulo) {
  if (this->modulo != 0)
    this->value %= this->modulo;
}

Num &Num::operator=(const Num &other) {
  Num tmp = other;
  // the are much better way is
  //create member f that is wrapper calling copy & swap
  // but now we doing shit
  std::swap(this->modulo, tmp.modulo);
  std::swap(this->value, tmp.value);
  return *this;
}

Num Num::operator+(const Num &other) {
  Num obj = *this;
  return obj += other;
}

Num Num::operator-(const Num &other) {
  Num obj = *this;
  return obj -= other;
}

Num Num::operator*(const Num &other) {
  Num obj = *this;
  return obj *= other;
}

Num Num::operator+(int num) {
  Num obj = *this;
  return obj += num;
}

Num Num::operator-(int num) {
  Num obj = *this;
  return obj -= num;
}

Num Num::operator*(int num) {
  Num obj = *this;
  return obj *= num;
}

Num &Num::operator+=(const Num &other) {
  int64_t buf = this->value;
  buf += other.value;
  buf %= modulo;
  this->value = buf;
  return *this;
}

Num &Num::operator-=(const Num &other) {
  int num = (this->value - other.value) % this->modulo;
  if (num < 0)
    num = (this->modulo + num) % this->modulo;
  this->value = num;
  return *this;
}

Num &Num::operator*=(const Num &other) {
  int64_t buf = this->value;
  buf *= other.value;
  buf %= modulo;
  this->value = buf;
  return *this;
}

Num &Num::operator+=(int num) {
  *this += Num(num, 0);
  return *this;
}

Num &Num::operator-=(int num) {
  *this -= Num(num, 0);
  return *this;
}

Num &Num::operator*=(int num) {
  return *this *= Num(num, 0);
}