package edu.neu.ccs.evergreen.ir;
/**
 * 
 */

/**
 * @author mohsen
 *
 */
public class CustomCounter {
    private int noOfDigits;
    private int start;
    private int end;
    private int[] digits;
    /**
     * Create a counter with the specified number of digits
     * where each digit can take values in the range (start,end)
     * @param noOfDigits
     * @param start
     * @param end
     */
    public CustomCounter(int noOfDigits, int start, int end) {
        this.noOfDigits = noOfDigits;
        this.start = start;
        this.end = end;
        digits = new int[noOfDigits];
        restart();
    } 
    public int[] next(){
        for(int i=0;i<digits.length;i++){
            digits[i]++;
            if(digits[i]>end){
                digits[i] = start;
            }else{
                break;
            }
        }
        return getPermutation();
    }
    public boolean hasNext(){
        for(int digit: digits){
            if(digit!=end) return true;
        }
        return false;
    }
    public void restart(){
        for(int i=0;i<digits.length;i++){
            digits[i] = start;
        }       
    }
    
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        for(int i=digits.length-1;i>-1;i--){
            sb.append(digits[i]);
        }       
        return sb.toString();
    }
    
    public boolean isPermutation(){
        for (int i = 0; i < digits.length; i++) {
            for (int j = i+1; j < digits.length; j++) {
                if(digits[i]==digits[j]) return false;
            }
        }
        return true;
    }
    public int[] nextPermutation(){
        do{
            next();
        }
        while(hasNext()&&(!isPermutation()));
        return getPermutation();
    }
    public boolean hasNextPermutation(){
        if(hasNext()==false) return false;
        boolean returnVal = false;
        int[] tmp = new int[digits.length];
        for (int i = 0; i < digits.length; i++) {
            tmp[i] = digits[i];
        }
        nextPermutation();
        returnVal = isPermutation();
        for (int i = 0; i < digits.length; i++) {
            digits[i] = tmp[i];
        }
        return returnVal;
    }
    public boolean isDistinctPermutation(){
        for (int i = 0; i < digits.length; i++) {
            for (int j = i+1; j < digits.length; j++) {
                if(digits[i]<=digits[j]) return false;
            }
        }
        return true;
    }
    public int[] nextDistinctPermutation(){
        do{
            next();
        }
        while(hasNext()&&(!isDistinctPermutation()));
        return getPermutation();
    }
    public boolean hasNextDistinctPermutation(){
        if(hasNext()==false) return false;
        boolean returnVal = false;
        int[] tmp = new int[digits.length];
        for (int i = 0; i < digits.length; i++) {
            tmp[i] = digits[i];
        }
        nextDistinctPermutation();
        returnVal = isDistinctPermutation();
        for (int i = 0; i < digits.length; i++) {
            digits[i] = tmp[i];
        }
        return returnVal;
    }

    public int[] filter(int[] filter){
        int count=0;
        for(int i:filter){
            if(i==1)count++;
        }
        int[] tmp = new int[count];
        count=0;
        for(int i=0;i<digits.length;i++){
            if(filter[i]==1) tmp[count++]=digits[i];
        }
        return tmp;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        CustomCounter p = new CustomCounter(noOfDigits,start,end);
        for (int i = 0; i < digits.length; i++) {
            p.digits[i]=digits[i];
        }
        return p;
    }
    /**
     * @return a copy of the internally stored permutation
     */
    public int[] getPermutation(){
        int[] digitsCopy = new int[noOfDigits];
        for (int i = 0; i < digits.length; i++) {
            digitsCopy[i] = digits[i];
        }
        return digitsCopy; 
    }
    
    public static void main(String[] args){
        //Truth Table of length 5
        CustomCounter c = new CustomCounter(5,0,1);
        while(c.hasNext()){
            c.next();
            System.out.println(c);
        }
        System.out.println("============");
        //
        c = new CustomCounter(2,1,5);
        while(c.hasNextPermutation()){
            c.nextPermutation();
            System.out.println(c);
        }
        System.out.println("============");
        //
        c = new CustomCounter(2,1,5);
        while(c.hasNextDistinctPermutation()){
            c.nextDistinctPermutation();
            System.out.println(c);
        }       
        System.out.println("============");
        int[] f1={0,0};
        int[] f2={1,1};
        int[] x = c.filter(f1);
        int[] y = c.filter(f2);
        for (int i = 0; i < x.length; i++) {
            System.out.println("x["+i+"]"+x[i]);
        }
        for (int i = 0; i < y.length; i++) {
            System.out.println("y["+i+"]"+y[i]);
        }
    }

}