// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you 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.apache.juneau.pojotools;

import static org.apache.juneau.internal.StringUtils.*;

import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.*;

/**
 * Designed to provide paging on POJOs consisting of arrays and collections.
 *
 * <p>
 * Allows you to quickly return subsets of arrays and collections based on position/limit arguments.
 */
@SuppressWarnings({"rawtypes"})
public final class PojoSearcher implements PojoTool<SearchArgs> {

	/**
	 * Default reusable searcher.
	 */
	public static final PojoSearcher DEFAULT = new PojoSearcher();

	final MatcherFactory[] factories;

	/**
	 * Constructor.
	 *
	 * @param factories The matcher factories to use.
	 */
	public PojoSearcher(MatcherFactory...factories) {
		this.factories = factories;
	}

	/**
	 * Constructor.
	 */
	public PojoSearcher() {
		this(NumberMatcherFactory.DEFAULT, TimeMatcherFactory.DEFAULT, StringMatcherFactory.DEFAULT);
	}

	@Override /* PojoTool */
	public Object run(BeanSession session, Object input, SearchArgs args) {

		ClassMeta<?> type = session.getClassMetaForObject(input);
		Map<String,String> search = args.getSearch();

		if (search.isEmpty() || type == null || ! type.isCollectionOrArray())
			return input;

		List<Object> l = null;
		RowMatcher rowMatcher = new RowMatcher(session, search);

		if (type.isCollection()) {
			Collection c = (Collection)input;
			l = new ArrayList<>(c.size());
			for (Object o : c) {
				if (rowMatcher.matches(o))
					l.add(o);
			}

		} else /* isArray */ {
			int size = Array.getLength(input);
			l = new ArrayList<>(size);
			for (int i = 0; i < size; i++) {
				Object o = Array.get(input, i);
				if (rowMatcher.matches(o))
					l.add(o);
			}
		}

		return l;
	}

	//====================================================================================================
	// MapMatcher
	//====================================================================================================
	/*
	 * Matches on a Map only if all specified entry matchers match.
	 */
	private class RowMatcher {

		Map<String,ColumnMatcher> entryMatchers = new HashMap<>();
		BeanSession bs;

		RowMatcher(BeanSession bs, Map query) {
			this.bs = bs;
			for (Map.Entry e : (Set<Map.Entry>)query.entrySet())
				entryMatchers.put(stringify(e.getKey()), new ColumnMatcher(bs, stringify(e.getValue())));
		}

		boolean matches(Object o) {
			if (o == null)
				return false;
			ClassMeta<?> cm = bs.getClassMetaForObject(o);
			if (cm.isMapOrBean()) {
				Map m = cm.isMap() ? (Map)o : bs.toBeanMap(o);
				for (Map.Entry<String,ColumnMatcher> e : entryMatchers.entrySet()) {
					String key = e.getKey();
					Object val = null;
					if (m instanceof BeanMap) {
						val = ((BeanMap)m).getRaw(key);
					} else {
						val = m.get(key);
					}
					if (! e.getValue().matches(val))
						return false;
				}
				return true;
			}
			if (cm.isCollection()) {
				for (Object o2 : (Collection)o)
					if (! matches(o2))
						return false;
				return true;
			}
			if (cm.isArray()) {
				for (int i = 0; i < Array.getLength(o); i++)
					if (! matches(Array.get(o, i)))
						return false;
				return true;
			}
			return false;
		}
	}

	//====================================================================================================
	// ObjectMatcher
	//====================================================================================================
	/*
	 * Matcher that uses the correct matcher based on object type.
	 * Used for objects when we can't determine the object type beforehand.
	 */
	private class ColumnMatcher {

		String searchPattern;
		Matcher[] matchers;
		BeanSession bs;

		ColumnMatcher(BeanSession bs, String searchPattern) {
			this.bs = bs;
			this.searchPattern = searchPattern;
			this.matchers = new Matcher[factories.length];
		}

		boolean matches(Object o) {
			ClassMeta<?> cm = bs.getClassMetaForObject(o);
			if (cm == null)
				return false;
			if (cm.isCollection()) {
				for (Object o2 : (Collection)o)
					if (matches(o2))
						return true;
				return false;
			}
			if (cm.isArray()) {
				for (int i = 0; i < Array.getLength(o); i++)
					if (matches(Array.get(o, i)))
						return true;
				return false;
			}
			for (int i = 0; i < factories.length; i++) {
				if (factories[i].canMatch(cm)) {
					if (matchers[i] == null)
						matchers[i] = factories[i].create(searchPattern);
					return matchers[i].matches(cm, o);
				}
			}
			return false;
		}
	}
}