#ifndef BATTLESHIP_BOARD_H
#define BATTLESHIP_BOARD_H

#include <ostream>
#include <utility>
#include <stdint.h>

#include "Cell.h"
#include "Ship.h"

namespace Battleship{

class Board{
public:
    //just making up points.
    //typedef std::pair<unsigned int, unsigned int> Point;

    Board(int rows, int cols, int* r_sums, int* c_sums, Cell* constraints = NULL);
    Board(const Board& other);
    Board& operator=(Board other);
    friend void swap(Board& first, Board& second);

    void destroyBoard();
    ~Board();

    Ship* computeCompletedShips();

    void printBoard(std::ostream& out) const;

    void setChildBoard(bool childBoard = true) { this->childBoard = childBoard; };

    Cell* getCellList() const { return cellList; };

    int getRowSpaceLeft(int row) const;
    int getColSpaceLeft(int col) const;

    bool isFilled() const;

    int getLargestLeft() const;

    int getRows() const { return *rows; };
    int getCols() const { return *cols; };

    //returns true if placement worked
    //Arguments are location to attempt placement, then direction
    //(if horizontal is true, it'll move left if it's false, it'll move down)
    //(In other words, the origin is the top left)
    //Then the newBoard argument is populated with a board instance to use for the next attempts!
    bool tryPlace(int x, int y, uint8_t ship, bool horizontal, Board*& newBoard);

private:
    inline bool checkLegality(int start, uint8_t size, int row_col, bool horizontal) const;
    inline char checkCell(int x, int y) const;

    //Private constructor for creating children boards
    Board(const Board& parent, int start, uint8_t size, int row_col, bool horizontal);
    //While I could just use char directly, I'm going to use cell instead since
    //it's easier to keep track of what needs to be deleted with it (each cell is also
    //part of a linked list).
    Cell*** state;
    Cell* cellList;
    Cell* extraCells;
    //Yes, even these are dynamic in attempt to reduce memory impact
    int *rows, *cols, *constraints;
    //Rows and column cells occupied and sums
    int *r_occupied, *c_occupied, *r_sums, *c_sums;
    bool childBoard, destroyed;
};

void swap(Board& first, Board& second);

};

#endif // BATTLESHIP_BOARD_H
