/*
  This file is part of the BJP package.

  BJP package is free software: you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as published by the
  Free Software Foundation, either version 3 of the License, or (at your
  option) any later version.

  BJP package is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with BJP package.  If not, see <http://www.gnu.org/licenses/>.
 */
package dataset.feature;

import java.util.Arrays;
import java.util.BitSet;
import java.util.List;

/**
 * This class represents a mixed feature (i.e., a conjunction over both true and
 * false variables).
 */

public class MixedFeature extends Feature {
    private final BitSet[] val;

    public MixedFeature(int n) {
	super(n);
	this.val = new BitSet[n];
    }

    public MixedFeature(MixedFeature f) {
	super(f.getLength());
	this.val = Arrays.<BitSet>copyOf(f.val, f.getLength());
    }

    public void addVal(int var, Integer val) {
	if (val == null) {
	    this.rmVar(var);
	    this.val[var] = null;
	    return;
	}

	this.addVar(var);

	if (this.val[var] == null) {
	    this.val[var] = new BitSet(this.getLength());
	} else {
	    this.val[var].clear();
	}

	this.val[var].set(val);
    }

    public Integer getVal(int var) {
	if (this.val[var] != null)
	    return this.val[var].nextSetBit(0);

	return null;
    }

    public int getLength() {
	int count = 0;

	for (int i = 0; i < val.length; i++)
	    if (val[i] != null) count++;

	return count;
    }

    public MixedFeature clone() {
	return new MixedFeature(this);
    }

    public int hashCode() {
	return this.getVar().hashCode() + Arrays.deepHashCode(this.val.clone());
    }

    public boolean equals(Object object) {
	if (object instanceof MixedFeature) {
	    MixedFeature f = (MixedFeature) object;

	    return this.getVar().equals(f.getVar()) && Arrays.deepEquals(this.val, f.val);
	}
	else {
	    return false;
	}
    }

    public String toString() {
	StringBuilder stringBuilder = new StringBuilder();


	for(int i=this.getVar().nextSetBit(0); i>=0; i=this.getVar().nextSetBit(i+1)) {
	    stringBuilder.append("+v" + i + "_" + getVal(i) + " ");
	}

	return stringBuilder.toString().trim();
    }

    public static void main(String[] args) {

	Feature f = new MixedFeature(3);
	f.addVal(0, 1);
	// f.addVal(1, 2);
	f.addVal(2, 0);

	System.out.println(f);
	System.out.println(f.getLength());
	System.out.println(f.hashCode());

	f.addVal(1, 2);

	System.out.println(f);
	System.out.println(f.getLength());
	System.out.println(f.hashCode());

	f.addVal(1, null);

	System.out.println(f);
	System.out.println(f.getLength());
	System.out.println(f.hashCode());
    }

	@Override
	public boolean isSatisfied(Feature otherFeature) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public BitSet getValues() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setValues(BitSet values) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Feature getSubset(BitSet variables) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Feature getSubset(List<Integer> blanketOfX) {
		// TODO Auto-generated method stub
		return null;
	}
}