/*
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package dk.ekot.eternii;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.image.BufferedImage;

/**
 * Opens a windows showing an {@link EBoard} and tracks changes.
 */
public class BoardVisualiser implements EBoard.Observer {
    private static final Logger log = LoggerFactory.getLogger(BoardVisualiser.class);

    private final EBoard board;
    private final EPieces pieces;
    private final JComponent boardDisplayComponent;
    private final BufferedImage boardImage;
    private final int edgeWidth;
    private final int edgeHeight;
    private final boolean onlyUpdateOnBetter;

    private int best = 0;

    public BoardVisualiser(EBoard board) {
        this(board, false);
    }

    public BoardVisualiser(EBoard board, boolean onlyUpdateOnBetter) {
        this.board = board;
        this.onlyUpdateOnBetter = onlyUpdateOnBetter;
        pieces = board.getPieces();

        BufferedImage edge0 = pieces.getEdgeImage(0);
        edgeWidth = edge0.getWidth();
        edgeHeight = edge0.getHeight();
        boardImage = new BufferedImage(edgeWidth*board.getWidth(), edgeHeight*board.getHeight(), BufferedImage.TYPE_INT_RGB);
        invalidateAll();
        boardDisplayComponent = BaseGraphics.displayImage(boardImage);
        board.registerObserver(this);
    }

    private void invalidateAll() {
        for (int y = 0 ; y < board.getHeight() ; y++) {
            for (int x = 0 ; x < board.getWidth() ; x++) {
                updateTile(x, y);
            }
        }
    }

    @Override
    public void boardChanged(int x, int y) {
        if (onlyUpdateOnBetter) {
            if (board.getFilledCount() > best) {
                best = board.getFilledCount();
                invalidateAll();
            }
            return;
        }

        updateTile(x, y);
    }

    private void updateTile(int x, int y) {
        BufferedImage tile = pieces.getBlank();
        int piece = board.getPiece(x, y);
        if (piece != -1) {
            int rotation = board.getRotation(x, y);
            tile = pieces.getPieceImage(piece, rotation);
        }
        boardImage.getGraphics().drawImage(tile, x * edgeWidth, y * edgeHeight, null);
        if (boardDisplayComponent != null) {
            boardDisplayComponent.repaint(100L, x*edgeHeight, y*edgeHeight, edgeWidth, edgeHeight);
        }
    }
}

@@ -925,24 +925,96 @@
 er.class);%0A%0A
+    public static final int UPDATE_INTERVAL = 100; // Every 100 ms%0A    %0A
     private 
@@ -1275,16 +1275,57 @@
 nBetter;
+%0A    private boolean needsUpdate = false;
 %0A%0A    pr
@@ -1971,43 +1971,816 @@
 e);%0A
-        board.registerObserver(this
+%0A        Thread t = new Thread(() -%3E %7B%0A            while (true) %7B%0A                invalidateConditionally();%0A                try %7B%0A                    Thread.sleep(UPDATE_INTERVAL);%0A                %7D catch (InterruptedException e) %7B%0A                    log.debug(%22Interrupted while sleeping%22);%0A                %7D%0A            %7D%0A        %7D, %22BoardVisualizer%22);%0A        t.setDaemon(true);%0A        t.start();%0A        board.registerObserver(this);%0A    %7D%0A%0A    private void invalidateConditionally() %7B%0A        if (!needsUpdate) %7B%0A            return;%0A        %7D%0A        if (onlyUpdateOnBetter) %7B%0A            if (board.getFilledCount() %3E best) %7B%0A                best = board.getFilledCount();%0A                invalidateAll();%0A            %7D%0A            return;%0A        %7D%0A        invalidateAll();%0A        //updateTile(x, y
 );%0A 
@@ -3071,232 +3071,26 @@
     
-if (onlyUpdateOnBetter) %7B%0A            if (board.getFilledCount() %3E best) %7B%0A                best = board.getFilledCount();%0A                invalidateAll();%0A            %7D%0A            return;%0A        %7D%0A%0A        updateTile(x, y)
+needsUpdate = true
 ;%0A  
@@ -3623,10 +3623,11 @@
 %7D%0A    %7D%0A
+%0A
 %7D%0A

Switch visualiser to use its own thread and periodic updated