# This class represents the minefield
from Mine import *
import random

class MineField:

    # Initialse the mine fild using a probability of min generation
    #  and a minimum numbe of mines 
    def __init__(self, size, prob, minM):
        self.mineProb = prob
        self.gridSize = size
        self.minMines = minM
        self.numMines = 0
        self.mines = []
        self.initMines()
        
    # Minefield are geneated randomly but rejected if the minimum 
    #  number not reached
    def initMines(self):
        numM = 0
        while numM < self.minMines:
            self.mines = []
            numM = 0
            for x in range(0, self.gridSize):
                row = []
                for y in range(0, self.gridSize):
                    mine = Mine()
                    if random.random() > self.mineProb:
                        mine.plant()
                        numM += 1
                    row.append(mine)
                self.mines.append(row)
            self.numMines = numM

    # Display the header
    def showHeader(self):
        line = "    "
        col = 0
        while col < self.gridSize:
            line = line + str(col) + " "
            col += 1
        print(line)
        print("   ", "--" * self.gridSize)

    # Display the minefield during the game
    def showField(self):
        self.showHeader()
        row = 0
        for ms in self.mines:
            line = " " + str(row) + ": "
            for m in ms:
               line = line + m.showState() + " "
            print(line)
            row = row + 1
    
    # Display the minefield at the end of the game
    def revealField(self):
        self.showHeader()
        row = 0
        for ms in self.mines:
            line = " " + str(row) + ": "
            for m in ms:
               line = line + m.revealState() + " "
            print(line)
            row = row + 1

    # Get the mine at the given location (unchecked)   
    def getMine(self, row, col):
        return self.mines[row][col]

    # Count nuumber of neighbouing mines and
    #   continue recursively if zero
    # Return number of loctions cleared
    def scoreNeighboursAndClear(self, row, col):
        c = self.scoreNeighbours(row, col)
        extra = 0
        if c == 0:
            rcms = self.getNeighbours(row, col)
            for (r,c,m) in rcms:
                if not m.getClear():
                    m.clear()
                    extra += 1
                    extra += self.scoreNeighboursAndClear(r,c)
        return extra
        
    # NOT USED. Count nuumber of neighbouing mines but
    #   do not recurse
    def scoreNeighbours(self, row, col):
        rcms = self.getNeighbours(row, col)
        count = 0
        for (r,c,m) in rcms:
            if m.getPlant():
                count += 1
        self.mines[row][col].setCount(count)
        return count

    # Get a list of neiighbouing cells
    def getNeighbours(self, r, c):
        ns = []
        self.getCell(ns, c-1, r-1)
        self.getCell(ns, c-1, r)
        self.getCell(ns, c-1, r+1)
        self.getCell(ns, c, r-1)
        self.getCell(ns, c, r+1)
        self.getCell(ns, c+1, r-1)
        self.getCell(ns, c+1, r)
        self.getCell(ns, c+1, r+1)
        return ns

    # Add a cell to the list if the cell exists
    def getCell(self, ns, c, r):
        if r < 0 or r >= self.gridSize:
            return
        if c < 0 or c >= self.gridSize:
            return
        ns.append((r,c,self.mines[r][c]))
