/*
 * $Id: FilterImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
 *
 * Copyright (c) 2000 Gatespace AB. All Rights Reserved.
 * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.osgi.impl.bundle.obr.resource;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import aQute.bnd.annotation.ProviderType;

@ProviderType
public class FilterImpl {
	final char		WILDCARD	= 65535;

	final int		EQ			= 0;
	final int		LE			= 1;
	final int		GE			= 2;
	final int		APPROX		= 3;
	final int		LESS		= 4;
	final int		GREATER		= 5;
	final int		SUBSET		= 6;
	final int		SUPERSET	= 7;

	private String	filter;

	abstract class Query {
		static final String	GARBAGE		= "Trailing garbage";
		static final String	MALFORMED	= "Malformed query";
		static final String	EMPTY		= "Empty list";
		static final String	SUBEXPR		= "No subexpression";
		static final String	OPERATOR	= "Undefined operator";
		static final String	TRUNCATED	= "Truncated expression";
		static final String	EQUALITY	= "Only equality supported";

		private String		tail;

		boolean match() throws IllegalArgumentException {
			tail = filter;
			boolean val = doQuery();
			if (tail.length() > 0) {
                error(GARBAGE);
            }
			return val;
		}

		private boolean doQuery() throws IllegalArgumentException {
			if ((tail.length() < 3) || !prefix("(")) {
                error(MALFORMED);
            }
			boolean val;

			switch (tail.charAt(0)) {
				case '&' :
					val = doAnd();
					break;
				case '|' :
					val = doOr();
					break;
				case '!' :
					val = doNot();
					break;
				default :
					val = doSimple();
					break;
			}

			if (!prefix(")")) {
                error(MALFORMED);
            }
			return val;
		}

		private boolean doAnd() throws IllegalArgumentException {
			tail = tail.substring(1);
			boolean val = true;
			if (!tail.startsWith("(")) {
                error(EMPTY);
            }
			do {
				if (!doQuery()) {
                    val = false;
                }
			} while (tail.startsWith("("));
			return val;
		}

		private boolean doOr() throws IllegalArgumentException {
			tail = tail.substring(1);
			boolean val = false;
			if (!tail.startsWith("(")) {
                error(EMPTY);
            }
			do {
				if (doQuery()) {
                    val = true;
                }
			} while (tail.startsWith("("));
			return val;
		}

		private boolean doNot() throws IllegalArgumentException {
			tail = tail.substring(1);
			if (!tail.startsWith("(")) {
                error(SUBEXPR);
            }
			return !doQuery();
		}

		private boolean doSimple() throws IllegalArgumentException {
			int op = 0;
			Object attr = getAttr();

			if (prefix("=")) {
                op = EQ;
            }
            else if (prefix("<=")) {
                op = LE;
            }
            else if (prefix(">=")) {
                op = GE;
            }
            else if (prefix("~=")) {
                op = APPROX;
            }
            else if (prefix("*>")) {
                op = SUPERSET;
            }
            else if (prefix("<*")) {
                op = SUBSET;
            }
            else if (prefix("<")) {
                op = LESS;
            }
            else if (prefix(">")) {
                op = GREATER;
            }
            else {
                error(OPERATOR);
            }

			return compare(attr, op, getValue());
		}

		private boolean prefix(String pre) {
			if (!tail.startsWith(pre)) {
                return false;
            }
			tail = tail.substring(pre.length());
			return true;
		}

		private Object getAttr() {
			int len = tail.length();
			int ix = 0;
			label: for (; ix < len; ix++) {
				switch (tail.charAt(ix)) {
					case '(' :
					case ')' :
					case '<' :
					case '>' :
					case '=' :
					case '~' :
					case '*' :
					case '}' :
					case '{' :
					case '\\' :
						break label;
				}
			}
			String attr = tail.substring(0, ix).toLowerCase();
			tail = tail.substring(ix);
			return getProp(attr);
		}

		abstract Object getProp(String key);

		private String getValue() {
			StringBuffer sb = new StringBuffer();
			int len = tail.length();
			int ix = 0;
			label: for (; ix < len; ix++) {
				char c = tail.charAt(ix);
				switch (c) {
					case '(' :
					case ')' :
						break label;
					case '*' :
						sb.append(WILDCARD);
						break;
					case '\\' :
						if (ix == len - 1) {
                            break label;
                        }
						sb.append(tail.charAt(++ix));
						break;
					default :
						sb.append(c);
						break;
				}
			}
			tail = tail.substring(ix);
			return sb.toString();
		}

		private void error(String m) throws IllegalArgumentException {
			throw new IllegalArgumentException(m + " " + tail);
		}

		private boolean compare(Object obj, int op, String s) {
			if (obj == null) {
				// No value is ok for a subset
				if (op == SUBSET) {
                    return true;
                }

				// No value is ok for a superset when the value is
				// empty
				if (op == SUPERSET) {
					return s.trim().length() == 0;
				}

				return false;
			}
			try {
				Class numClass = obj.getClass();
				if (numClass == String.class) {
					return compareString((String) obj, op, s);
				}
				else if (numClass == Character.class) {
					return compareString(obj.toString(), op, s);
				}
				else if (numClass == Long.class) {
					return compareSign(op, Long.valueOf(s)
							.compareTo((Long) obj));
				}
				else if (numClass == Integer.class) {
					return compareSign(op, Integer.valueOf(s).compareTo(
							(Integer) obj));
				}
				else if (numClass == Short.class) {
					return compareSign(op, Short.valueOf(s).compareTo(
							(Short) obj));
				}
				else if (numClass == Byte.class) {
					return compareSign(op, Byte.valueOf(s)
							.compareTo((Byte) obj));
				}
				else if (numClass == Double.class) {
					return compareSign(op, Double.valueOf(s).compareTo(
							(Double) obj));
				}
				else if (numClass == Float.class) {
					return compareSign(op, Float.valueOf(s).compareTo(
							(Float) obj));
				}
				else if (numClass == Boolean.class) {
					if (op != EQ) {
                        return false;
                    }
					int a = Boolean.valueOf(s).booleanValue() ? 1 : 0;
					int b = ((Boolean) obj).booleanValue() ? 1 : 0;
					return compareSign(op, a - b);
				}
				else if (numClass == BigInteger.class) {
					return compareSign(op, new BigInteger(s)
							.compareTo((BigInteger) obj));
				}
				else if (obj instanceof Collection) {
					if ((op == SUBSET) || (op == SUPERSET)) {
						StringSet set = new StringSet(s);
						if (op == SUBSET) {
                            return set.containsAll((Collection) obj);
                        }
                        else {
                            return ((Collection) obj).containsAll(set);
                        }
					}

					for (Iterator i = ((Collection) obj).iterator(); i
							.hasNext();) {
						Object element = i.next();
						if (compare(element, op, s)) {
                            return true;
                        }
					}
				}
				else if (numClass.isArray()) {
					int len = Array.getLength(obj);
					for (int i = 0; i < len; i++) {
                        if (compare(Array.get(obj, i), op, s)) {
                            return true;
                        }
                    }
				}
				else {
					try {
						if ((op == SUPERSET) || (op == SUBSET)) {
							StringSet set = new StringSet(s);
							if (op == SUPERSET) {
                                return set.contains(obj);
                            }
                            else {
                                return (set.size() == 0)
										|| ((set.size() == 1) && set.iterator()
												.next().equals(obj));
                            }
						}
						else {
							Constructor constructor = numClass
									.getConstructor(new Class[] {String.class});
							Object instance = constructor
									.newInstance(new Object[] {s});
							switch (op) {
								case EQ :
									return obj.equals(instance);
								case LESS :
									return ((Comparable) obj)
											.compareTo(instance) < 0;
								case GREATER :
									return ((Comparable) obj)
											.compareTo(instance) > 0;
								case LE :
									return ((Comparable) obj)
											.compareTo(instance) <= 0;
								case GE :
									return ((Comparable) obj)
											.compareTo(instance) >= 0;
							}
						}
					}
					catch (Exception e) {
						e.printStackTrace();
						// Ignore
					}
				}
			}
			catch (Exception e) {
			}
			return false;
		}
	}

	class DictQuery extends Query {
		private Map	dict;

		DictQuery(Map dict) {
			this.dict = dict;
		}

		@Override
        Object getProp(String key) {
			return dict.get(key);
		}
	}

	public FilterImpl(String filter) throws IllegalArgumentException {
		// NYI: Normalize the filter string?
		this.filter = filter;
		if ((filter == null) || (filter.length() == 0)) {
            throw new IllegalArgumentException("Null query");
        }
	}

	public boolean match(Map dict) {
		try {
			return new DictQuery(dict).match();
		}
		catch (IllegalArgumentException e) {
			return false;
		}
	}

	@Override
    public String toString() {
		return filter;
	}

	@Override
    public boolean equals(Object obj) {
		return (obj != null) && (obj instanceof FilterImpl)
				&& filter.equals(((FilterImpl) obj).filter);
	}

	@Override
    public int hashCode() {
		return filter.hashCode();
	}

	boolean compareString(String s1, int op, String s2) {
		switch (op) {
			case EQ :
				return patSubstr(s1, s2);
			case APPROX :
				return patSubstr(fixupString(s1), fixupString(s2));
			default :
				return compareSign(op, s2.compareTo(s1));
		}
	}

	boolean compareSign(int op, int cmp) {
		switch (op) {
			case LE :
				return cmp >= 0;
			case GE :
				return cmp <= 0;
			case EQ :
				return cmp == 0;
			default : /* APPROX */
				return cmp == 0;
		}
	}

	String fixupString(String s) {
		StringBuffer sb = new StringBuffer();
		int len = s.length();
		boolean isStart = true;
		boolean isWhite = false;
		for (int i = 0; i < len; i++) {
			char c = s.charAt(i);
			if (Character.isWhitespace(c)) {
				isWhite = true;
			}
			else {
				if (!isStart && isWhite) {
                    sb.append(' ');
                }
				if (Character.isUpperCase(c)) {
                    c = Character.toLowerCase(c);
                }
				sb.append(c);
				isStart = false;
				isWhite = false;
			}
		}
		return sb.toString();
	}

	boolean patSubstr(String s, String pat) {
		if (s == null) {
            return false;
        }
		if (pat.length() == 0) {
            return s.length() == 0;
        }
		if (pat.charAt(0) == WILDCARD) {
			pat = pat.substring(1);
			for (;;) {
				if (patSubstr(s, pat)) {
                    return true;
                }
				if (s.length() == 0) {
                    return false;
                }
				s = s.substring(1);
			}
		}
		else {
			if ((s.length() == 0) || (s.charAt(0) != pat.charAt(0))) {
                return false;
            }
			return patSubstr(s.substring(1), pat.substring(1));
		}
	}
}
