// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 com.cloud.consoleproxy.util;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

public class TileTracker {
    
    // 2 dimension tile status snapshot, a true value means the corresponding tile has been invalidated
    private boolean[][] snapshot;
    
    private int tileWidth = 0;
    private int tileHeight = 0;
    private int trackWidth = 0;
    private int trackHeight = 0;
    
    public TileTracker() {
    }

    public int getTileWidth() {
        return tileWidth;
    }

    public void setTileWidth(int tileWidth) {
        this.tileWidth = tileWidth;
    }

    public int getTileHeight() {
        return tileHeight;
    }

    public void setTileHeight(int tileHeight) {
        this.tileHeight = tileHeight;
    }

    public int getTrackWidth() {
        return trackWidth;
    }

    public void setTrackWidth(int trackWidth) {
        this.trackWidth = trackWidth;
    }

    public int getTrackHeight() {
        return trackHeight;
    }

    public void setTrackHeight(int trackHeight) {
        this.trackHeight = trackHeight;
    }
    
    public void initTracking(int tileWidth, int tileHeight, int trackWidth, int trackHeight) {
        assert(tileWidth > 0);
        assert(tileHeight > 0);
        assert(trackWidth > 0);
        assert(trackHeight > 0);
        assert(tileWidth <= trackWidth);
        assert(tileHeight <= trackHeight);
        
        this.tileWidth = tileWidth;
        this.tileHeight = tileHeight;
        this.trackWidth = trackWidth;
        this.trackHeight = trackHeight;
        
        int cols = getTileCols();
        int rows = getTileRows();
        snapshot = new boolean[rows][cols];
        for(int i = 0; i < rows; i++)
            for(int j = 0; j < cols; j++)
                snapshot[i][j] = false;
    }
    
    public synchronized void resize(int trackWidth, int trackHeight) {
        assert(tileWidth > 0);
        assert(tileHeight > 0);
        assert(trackWidth > 0);
        assert(trackHeight > 0);
        
        this.trackWidth = trackWidth;
        this.trackHeight = trackHeight;
        
        int cols = getTileCols();
        int rows = getTileRows();
        snapshot = new boolean[rows][cols];
        for(int i = 0; i < rows; i++)
            for(int j = 0; j < cols; j++)
                snapshot[i][j] = true;
    }
    
    public void invalidate(Rectangle rect) {
        setTileFlag(rect, true);
    }
    
    public void validate(Rectangle rect) {
        setTileFlag(rect, false);
    }

    public List<TileInfo> scan(boolean init) {
        List<TileInfo> l = new ArrayList<TileInfo>();
        
        synchronized(this) {
            for(int i = 0; i < getTileRows(); i++) {
                for(int j = 0; j < getTileCols(); j++) {
                    if(init || snapshot[i][j]) {
                        Rectangle rect = new Rectangle();
                        rect.y = i*tileHeight;
                        rect.x = j*tileWidth;
                        rect.width = Math.min(trackWidth - rect.x, tileWidth);
                        rect.height = Math.min(trackHeight - rect.y, tileHeight);
                        
                        l.add(new TileInfo(i, j, rect));
                        snapshot[i][j] = false;
                    }
                }
            }
            
            return l;
        }    
    }
    
    public boolean hasFullCoverage() {
        synchronized(this) {
            for(int i = 0; i < getTileRows(); i++) {
                for(int j = 0; j < getTileCols(); j++) {
                    if(!snapshot[i][j])
                        return false;
                }
            }
        }    
        return true;
    }

    
    
    public void initCoverageTest() {
        synchronized(this) {
            for(int i = 0; i < getTileRows(); i++) {
                for(int j = 0; j < getTileCols(); j++) {
                    snapshot[i][j] = false;
                }
            }
        }    
    }
    
    // listener will be called while holding the object lock, use it
    // with care to avoid deadlock condition being formed
    public synchronized void scan(int nStartRow, int nStartCol, ITileScanListener listener) {
        assert(listener != null);
        
        int cols = getTileCols();
        int rows = getTileRows();
        
        nStartRow = nStartRow % rows;
        nStartCol = nStartCol % cols;
        
        int nPos = nStartRow*cols + nStartCol;
        int nUnits = rows*cols;
        int nStartPos = nPos;
        int nRow;
        int nCol;
        do {
            nRow = nPos / cols;
            nCol = nPos % cols;
            
            if(snapshot[nRow][nCol]) {
                int nEndCol = nCol;
                for(; nEndCol < cols && snapshot[nRow][nEndCol]; nEndCol++) {
                    snapshot[nRow][nEndCol] = false;
                }
                
                Rectangle rect = new Rectangle();
                rect.y = nRow*tileHeight;
                rect.height = tileHeight;
                rect.x = nCol*tileWidth;
                rect.width = (nEndCol - nCol)*tileWidth;
                
                if(!listener.onTileChange(rect, nRow, nEndCol))
                    break;
            }
            
            nPos = (nPos + 1) % nUnits;
        } while(nPos != nStartPos);
    }
    
    public void capture(ITileScanListener listener) {
        assert(listener != null);
        
        int cols = getTileCols();
        int rows = getTileRows();
        
        RegionClassifier classifier = new RegionClassifier();
        int left, top, right, bottom;
        
        synchronized(this) {
            for(int i = 0; i < rows; i++) {
                top = i*tileHeight;
                bottom = Math.min(top + tileHeight, trackHeight); 
                for(int j = 0; j < cols; j++) {
                    left = j*tileWidth;
                    right = Math.min(left + tileWidth, trackWidth);
                    
                    if(snapshot[i][j]) {
                        snapshot[i][j] = false;
                        classifier.add(new Rectangle(left, top, right - left, bottom - top));
                    }
                }
            }
        }
        listener.onRegionChange(classifier.getRegionList());
    }
    
    private synchronized void setTileFlag(Rectangle rect, boolean flag) {
        int nStartTileRow;
        int nStartTileCol;
        int nEndTileRow;
        int nEndTileCol;
        
        int cols = getTileCols();
        int rows = getTileRows();
        
        if(rect != null) {
            nStartTileRow = Math.min(getTileYPos(rect.y), rows - 1);
            nStartTileCol = Math.min(getTileXPos(rect.x), cols - 1);
            nEndTileRow = Math.min(getTileYPos(rect.y + rect.height - 1), rows -1);
            nEndTileCol = Math.min(getTileXPos(rect.x + rect.width - 1), cols -1);
        } else {
            nStartTileRow = 0;
            nStartTileCol = 0;
            nEndTileRow = rows - 1;
            nEndTileCol = cols - 1;
        }
        
        for(int i = nStartTileRow; i <= nEndTileRow; i++)
            for(int j = nStartTileCol; j <= nEndTileCol; j++)
                snapshot[i][j] = flag;
    }
    
    private int getTileRows() {
        return (trackHeight + tileHeight - 1) / tileHeight;
    }
    
    private int getTileCols() {
        return (trackWidth + tileWidth - 1) / tileWidth;
    }
    
    private int getTileXPos(int x) {
        return x / tileWidth;
    }
    
    public int getTileYPos(int y) {
        return y / tileHeight;
    }
}
