/* 
 * Copyright 2012 by AVM GmbH <info@avm.de>
 *
 * This software contains free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License ("License") as 
 * published by the Free Software Foundation  (version 3 of the License). 
 * This software 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 copy of the 
 * License you received along with this software for more details.
 */

package de.avm.android.tr064;

public class Tr064Capabilities
{
	public enum Capability
	{
		HTTPS,
		SSO,
		CALLLIST,
		PHONEBOOK,
		WLAN_CONF, WLAN_CONF_SPECIFIC,
		VOIP_CONF, VOIP_CONF_ID,
		TAM,
		SID_FOR_URLS,
		WAN_PPP_CONNECTION,
		MY_FRITZ
	}
	
	public static final Tr064Capabilities EMPTY;
	public static final Tr064Capabilities ALL;
	
	private static final int FLAGS_SIZE;
	private boolean[] mFlags;
	
	static
	{
		FLAGS_SIZE = Capability.values().length;
		EMPTY = new Tr064Capabilities(false);
		ALL = new Tr064Capabilities(true);
	}
	
	/**
	 * Creates instance with no capability info
	 */
	public Tr064Capabilities()
	{
		this(false);
	}
	
	private Tr064Capabilities(boolean initOfAllFlags)
	{
		mFlags = new boolean[FLAGS_SIZE];
		for(int ii = 0; ii < FLAGS_SIZE; ii++) mFlags[ii] = initOfAllFlags;
	}
	
	/**
	 * Creates instance containing one capability
	 * 
	 * @param capability
	 * 		the one capability
	 */
	public Tr064Capabilities(Capability capability)
	{
		int cap = capability.ordinal();
		mFlags = new boolean[FLAGS_SIZE];
		for(int ii = 0; ii < FLAGS_SIZE; ii++) mFlags[ii] = (ii == cap);
	}
	
	/**
	 * Adds all capabitity info from capabilities
	 *  
	 * @param capabilities
	 * 		source info
	 */
	public void add(Tr064Capabilities capabilities)
	{
		verifyWritable();
		for(int ii = 0; ii < FLAGS_SIZE; ii++)
			if (capabilities.mFlags[ii]) mFlags[ii] = true; 
	}
	
	/**
	 * Adds a capabitity
	 *  
	 * @param capability
	 * 		capability to add
	 */
	public void add(Capability capability)
	{
		verifyWritable();
		mFlags[capability.ordinal()] = true; 
	}
	
	private void verifyWritable()
	{
		if (this == EMPTY)
			throw new IllegalStateException("Tr064Capabilities.EMPTY is read only.");
		if (this == ALL)
			throw new IllegalStateException("Tr064Capabilities.ALL is read only.");
	}
	
	/**
	 * Tests this for one capability
	 * 
	 * @param capability
	 * 		the capability to test for
	 * @return
	 * 		true if containing the capability
	 */
	public boolean has(Capability capability)
	{
		return mFlags[capability.ordinal()];
	}
	
	/**
	 * Tests this for multiple capabilities
	 * 
	 * @param capabilities
	 * 		has capabilities to test for
	 * @return
	 * 		true if containing all capabilities
	 */
	public boolean has(Tr064Capabilities capabilities)
	{
		for(int ii = 0; ii < FLAGS_SIZE; ii++)
			if (capabilities.mFlags[ii] && !mFlags[ii])
				return false;
		return true;
	}

	@Override
	public String toString()
	{
		StringBuilder result = new StringBuilder();

		Capability[] values = Capability.values();
		for(Capability capability : values)
			if (mFlags[capability.ordinal()])
			{
				if (result.length() > 0) result.append(",");
				result.append(capability.toString());
			}
		
		return result.toString();
	}

	@Override
	public boolean equals(Object object)
	{
		if (this == object) return true;
		if (!(object instanceof Tr064Capabilities)) return false;

		Tr064Capabilities capabilities = (Tr064Capabilities)object;
		for(int ii = 0; ii < FLAGS_SIZE; ii++)
			if (capabilities.mFlags[ii] != mFlags[ii])
				return false;
		return true;
	}
	 	
	@Override
	public int hashCode()
	{
		throw new UnsupportedOperationException();
	}
}
