// 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;
	}
}
