private void updateNeighbourCounterAndStatusOnGridCell(
      CellShape gridCell[][], int row, int column, CellStatus newCellStatus) {

    // a) update neighbour counter of adyacent cells

    CellShape cellNeighbour = null;
    for (int neighbourRow = row - 1; neighbourRow <= row + 1; neighbourRow++) {
      for (int neighbourColumn = column - 1; neighbourColumn <= column + 1; neighbourColumn++) {

        if (!isCaseIncreasingSameCellLookingForNeighbours(
                neighbourRow, neighbourColumn, row, column)
            && !isOutOfGrid(neighbourRow, neighbourColumn)) {
          cellNeighbour = gridCell[neighbourRow][neighbourColumn];

          cellNeighbour.neighboursNumber =
              (newCellStatus == CellStatus.LIVE)
                  ? cellNeighbour.neighboursNumber + 1
                  : cellNeighbour.neighboursNumber - 1;
        }
      }
    }

    // b) update new cell status

    gridCell[row][column].status = newCellStatus;
  }
    @Override
    protected Object clone() throws CloneNotSupportedException {

      CellShape cellCloned = new CellShape(this.status);
      cellCloned.neighboursNumber = this.neighboursNumber;

      return cellCloned;
    }
  @Override
  protected void onDraw(Canvas canvas) {

    // draw all separator lines
    Paint lineSeparator = new Paint();
    lineSeparator.setColor(Color.WHITE);

    // draw all alive cells
    for (int row = 0; row < rowsTotal; row++) {
      for (int column = 0; column < columnsTotal; column++) {

        CellShape cell = gridCell[row][column];

        if (cell.status == CellStatus.LIVE) {

          canvas.save();
          canvas.translate(column * widthFactor, row * heightFactor);

          cell.draw(canvas);

          canvas.restore();
        }

        if (DEBUG_MODE) {

          canvas.save();
          canvas.translate(column * widthFactor, row * heightFactor);

          canvas.drawText(
              new Integer(cell.neighboursNumber).toString(),
              widthFactor / 2,
              heightFactor - 10,
              lineSeparator);

          canvas.restore();
        }

        // TODO: only paint column separator once
        canvas.drawLine(
            widthFactor * column, 0, widthFactor * column, heightFactor * rowsTotal, lineSeparator);
      }

      canvas.drawLine(
          0, heightFactor * row, widthFactor * columnsTotal, heightFactor * row, lineSeparator);
    }
  }
  public void executeNextGeneration() {

    boolean hasCellChanged = false;
    CellShape[][] updatedGridCell = cloneGrid(gridCell);

    for (int row = 0; row < rowsTotal; row++) {
      for (int column = 0; column < columnsTotal; column++) {

        CellShape cell = gridCell[row][column];
        hasCellChanged = false;

        if (cell.status == CellStatus.LIVE) {

          if (cell.neighboursNumber < 2 || cell.neighboursNumber > 3) {

            cell.status = CellStatus.DEAD;
            hasCellChanged = true;
          }
        } else { // is a dead cell

          if (cell.neighboursNumber == 3) {

            cell.status = CellStatus.LIVE;
            hasCellChanged = true;
          }
        }

        if (hasCellChanged) {
          updateNeighbourCounterAndStatusOnGridCell(updatedGridCell, row, column, cell.status);
        }
      }
    }

    gridCell = updatedGridCell;

    invalidate();
  }