/// <summary>
		/// Write the provided square to the provided output.
		/// </summary>
		/// <param name="square">The square to write</param>
		/// <param name="output">The output to write into</param>
		/// <exception cref="ArgumentNullException">In case the square or the output is null.</exception>
		public void WriteSquare(Square square, TextWriter output)
		{
			if (square == null) throw new ArgumentNullException(nameof(square));
			if (output == null) throw new ArgumentNullException(nameof(output));

			output.WriteLine("Square:");
			for (int i = 0; i < square.Size; i++)
			{
				for (int j = 0; j < square.Size; j++)
				{
					output.Write($"{square.Values[i][j]} ");
				}
				output.WriteLine();
			}
		}
		/// <summary>
		/// Reads the square size and values from the provided input.
		/// </summary>
		/// <param name="input">Where to read the values from</param>
		/// <param name="output">Optional; where to write messages to</param>
		/// <returns>The constructed square.</returns>
		/// <exception cref="ArgumentNullException">Thrown if the input is null.</exception>
		public Square ReadSquare(TextReader input, TextWriter output)
		{
			if (input == null) throw new ArgumentNullException(nameof(input));

			int size = _integerInputReader.ReadInteger(input, "Square size (greater than zero) :", output);

			var square = new Square(size);
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					square.Values[i][j] = _integerInputReader.ReadInteger(input, $"Square value [{i}, {j}]: ", output);
				}
			}

			return square;
		}
		/// <summary>
		/// Verifies if the provided square matches the magic number.
		/// </summary>
		/// <param name="square">The square to check</param>
		/// <returns>True, if the square is magic; otherwise false.</returns>
		/// <exception cref="ArgumentNullException">If the square is null.</exception>
		public bool IsMagicSquare(Square square)
		{
			if (square == null) throw new ArgumentNullException(nameof(square));

			int mainDiagSum = 0;
			int antiDiagSum = 0;
			for (int i = 0; i < square.Size; i++)
			{
				int rowSum = 0;
				int colSum = 0;
				for (int j = 0; j < square.Size; j++)
				{
					// sum the current row
					rowSum += square.Values[i][j];
					// sum the current column
					colSum += square.Values[j][i];

					// sum the main diagonal values (when the two indicies are equal)
					if (i == j)
						mainDiagSum += square.Values[i][j];

					// sum the anti diagonal values (when the two indicis add up to size - 1)
					if ((i + j) == (square.Size - 1))
						antiDiagSum += square.Values[i][j];
				}

				// after each row/column summing is complete verify if the magic value is obtained; otherwise do an early stop
				if (rowSum != _magicNumber || colSum != _magicNumber)
					return false;
			}

			// after passing through the whole square (with magic sum on rows and colums) verify the two diagonal sums
			if (mainDiagSum != _magicNumber || antiDiagSum != _magicNumber)
				return false;

			return true;
		}