// BEGIN LICENSE BLOCK
// Version: CMPL 1.1
//
// The contents of this file are subject to the Cisco-style Mozilla Public
// License Version 1.1 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License
// at www.eclipse-clp.org/license.
// 
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
// the License for the specific language governing rights and limitations
// under the License. 
// 
// The Original Code is  CPViz Constraint Visualization System
// The Initial Developer of the Original Code is  Helmut Simonis
// Portions created by the Initial Developer are
// Copyright (C) 2009-2010 Helmut Simonis
// 
// Contributor(s): 	Helmut Simonis, 4C, Univerity College Cork, Cork
//			
// 
// END LICENSE BLOCK
// ----------------------------------------------------------------------
package ie.ucc.cccc.viz;

import java.io.PrintWriter;

/**
 * Visualizer for the cumulative constraint as a profile. 
 * @author hsimonis
 *
 */
public class VisualizerCumulative extends VisualizerLayout {

	public VisualizerCumulative(VisualContext context){
		super(context);
	}
	
	@Override
	void draw(PrintWriter out, VisualState visualState) {
		Tuple[] task = visualState.argumentTupleArray("tasks");
		FullDomain limit = visualState.argumentDomain("limit");
		FullDomain end = visualState.argumentDomain("end");
		
		int n = task.length;
		setHeight(limit.getMax());
		int w =0;
		for(int i=1;i<n;i++) {
			int startMax = task[i].getField("start").getMax();
			int durMax = task[i].getField("dur").getMax();
			w = Math.max(w,startMax+durMax);
		}
		setWidth(w);
		standardGrid(out);
		
		
		int[] profile = CumulativeProfile.computeProfile(task,width());
		for(int i=0;i <width();i++){
			openRectSVG(out,posX(i),posY(0),1,profile[i],Colors.UNASSIGNED_COLOR,0.8);
		}
		drawLimit(out,limit);
		drawEnd(out,end);		
	}
	
	@Override
	public InvariantType invariant(PrintWriter out, VisualState visualState) {
		Tuple[] task = visualState.argumentTupleArray("tasks");
		FullDomain limit = visualState.argumentDomain("limit");
		FullDomain end = visualState.argumentDomain("end");
		
		int n = task.length;
		int w =0;
		int volume = 0;
		int minStart = task[1].getField("start").getMin();
		for(int i=1;i<n;i++) {
			int startMax = task[i].getField("start").getMax();
			int startMin = task[i].getField("start").getMin();
			int durMax = task[i].getField("dur").getMax();
			int durMin = task[i].getField("dur").getMin();
			int resMin = task[i].getField("res").getMin();
			w = Math.max(w,startMax+durMax);
			volume += durMin*resMin;
			minStart = Math.min(minStart, startMin);
		}		
		int[] profile = CumulativeProfile.computeProfile(task,w);
		InvariantType overall = InvariantType.TRUE;
		for(int i=0;i <w;i++){
			if (profile[i] > limit.getMax()) {
				overall = overall.update(InvariantType.INCONSISTENT);
			}
			if (profile[i] > limit.getMin()) {
				overall= overall.update(InvariantType.MISSING_PROPAGATION);
			}
		}
		if (end != null){
			if (end.getMax() < minStart+Math.ceil(volume/limit.getMax())) {
				overall = overall.update(InvariantType.INCONSISTENT);				
			}
			if (end.getMin() < minStart+Math.ceil(volume/limit.getMax())) {
				overall = overall.update(InvariantType.MISSING_PROPAGATION);				
			}
		}
		return overall;			
	}


}
