/**
  *
  * Furniture Moving problem in choco v2.
  *
  * Problem from Marriott & Stuckey: 'Programming with constraints', page  112f
  *
  * Feature: testing cumulative.
  *
  * Other models of this problem:
  *   Choco (version 1): http://www.hakank.org/constraints/FurnitureMoving.java
  *   MiniZinc: http://www.hakank.org/minizinc/furniture_moving.mzn
  *   JaCoP: http://www.hakank.org/JaCoP/FurnitureMoving.java
  *
  *
  * choco model by Hakan Kjellerstrand (hakank@bonetmail.com)
  * Also see http://www.hakank.org/choco/

  */
import static choco.Choco.*;
import choco.cp.model.CPModel;
import choco.cp.solver.CPSolver;
import choco.cp.solver.constraints.*;
import choco.cp.solver.*;
import choco.kernel.model.variables.integer.*;
import choco.kernel.*;
import choco.kernel.solver.*;
import choco.kernel.model.*;
import choco.kernel.model.variables.*;
import choco.kernel.model.constraints.*;
import choco.kernel.model.variables.set.*;
import choco.cp.solver.search.integer.varselector.*;
import choco.cp.solver.search.integer.valiterator.*;
import choco.cp.solver.search.integer.valselector.*;
import choco.cp.solver.search.integer.branching.*;

import choco.kernel.model.variables.scheduling.TaskVariable;

import java.io.*;
import java.util.*;
import java.text.*;

public class FurnitureMoving {

    public static void main(String args[]) {

        Model m = new CPModel();
        Solver s = new CPSolver();

        // int NumPersons = 3;
        int NumPersons = 4;
        // IntegerVariable numPersons = makeIntVar("numPersons", 0, 10);        

        IntegerVariable Sp = makeIntVar("Sp", 0, 60); // Piano
        IntegerVariable Sc = makeIntVar("Sc", 0, 60); // Chair 
        IntegerVariable Sb = makeIntVar("Sb", 0, 60); // Bed
        IntegerVariable St = makeIntVar("St", 0, 60); // Table
        IntegerVariable SumStartTimes = makeIntVar("SumStartTimes", 0, 1000);

        IntegerVariable[] starts = {Sp,Sc,Sb,St};

        IntegerVariable SpEnd = makeIntVar("SpEnd", 0, 60);
        IntegerVariable ScEnd = makeIntVar("ScEnd", 0, 60);
        IntegerVariable SbEnd = makeIntVar("SbEnd", 0, 60);
        IntegerVariable StEnd = makeIntVar("StEnd", 0, 60);
        IntegerVariable[] ends = {SpEnd, ScEnd, SbEnd, StEnd};


        IntegerVariable[] durations = new IntegerVariable[4];
        int durationsInts[] = {30,10,15,15};
        for (int i = 0; i<durationsInts.length; i++) {
            // durations[i] = makeConstantVar("durations" + i, durationsInts[i]);
            durations[i] = makeIntVar("durations" + i, durationsInts[i], durationsInts[i]);
        }

        int[] _heights = {3,1,3,2};
        IntegerVariable[] heights = new IntegerVariable[_heights.length];
        for(int i = 0; i < _heights.length; i++) {
            heights[i] = makeIntVar("h"+i, _heights[i], _heights[i]);
        }

        //m.addConstraint(cumulative(starts, ends, durations, heights, NumPersons, "")); // This don't work!

        // Create TaskVariables
        // This is from  choco-kernel/src/main/java/choco/Choco.java
        TaskVariable[] t = new TaskVariable[starts.length];
        for(int i = 0; i < starts.length; i++){
            t[i] = makeTaskVar("", starts[i], ends[i], durations[i]);
        }

        m.addConstraint(cumulative(null, t, constantArray(_heights), constant(NumPersons))); // This works
        // m.addConstraint(cumulative(null, t, heights, constant(NumPersons))); // This works also (heigts as variables)

        m.addConstraint(eq(sum(starts), SumStartTimes));

        s.read(m);
        s.minimize(s.getVar(SumStartTimes), true);
        // s.solve(false);

        System.out.println(s.pretty());
        System.out.println("nbSol: " + s.getNbSolutions());

        if (s.isFeasible()) {

            do {
                System.out.println("\nSolution:");
                
                System.out.println("Piano: " + s.getVar(Sp).getVal()  + " - " + s.getVar(SpEnd).getVal() + "(" + heights[0] + " pers) " + 
                                   " Chair: " + s.getVar(Sc).getVal() + " - " + s.getVar(ScEnd).getVal() + "(" + heights[1] + " pers) " + 
                                   " Bed: " + s.getVar(Sb).getVal() + " - " + s.getVar(SbEnd).getVal() + "(" + heights[2] + " pers) " + 
                                   " Table: " + s.getVar(St).getVal() + " - " + s.getVar(StEnd).getVal() + "(" + heights[3] + " pers)"
                                   );
                System.out.println("SumStartTimes: " + s.getVar(SumStartTimes).getVal());

            } while (s.nextSolution() == Boolean.TRUE);

            
        } else {
            System.out.println("Problem is not feasible!");
        }


    } // end main

} // end class
