// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
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;
	}
}
