/*
 * Copyright (c) OSGi Alliance (2017). 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.util.converter;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * A custom converter wraps another converter by adding rules and/or error
 * handlers.
 *
 * @author $Id$
 */
class CustomConverterImpl implements InternalConverter {
	private final InternalConverter					delegate;
	final Map<Type,List<ConverterFunction>>	typeRules;
	final List<ConverterFunction>			allRules;
	final List<ConverterFunction>			errorHandlers;

	CustomConverterImpl(InternalConverter converter,
			Map<Type,List<ConverterFunction>> rules,
			List<ConverterFunction> catchAllRules,
			List<ConverterFunction> errHandlers) {
		delegate = converter;
		typeRules = rules;
		allRules = catchAllRules;
		errorHandlers = errHandlers;
	}

	@Override
	public InternalConverting convert(Object obj) {
		InternalConverting converting = delegate.convert(obj);
		converting.setConverter(this);
		return new ConvertingWrapper(obj, converting);
	}

	@Override
	public Functioning function() {
		return new FunctioningImpl(this);
	}

	@Override
	public ConverterBuilder newConverterBuilder() {
		return new ConverterBuilderImpl(this);
	}

	private class ConvertingWrapper implements InternalConverting {
		private final InternalConverting	del;
		private final Object				object;
		private volatile Object				defaultValue;
		private volatile boolean			hasDefault;

		ConvertingWrapper(Object obj, InternalConverting c) {
			object = obj;
			del = c;
		}

		@Override
		public Converting view() {
			del.view();
			return this;
		}

		@Override
		public Converting defaultValue(Object defVal) {
			del.defaultValue(defVal);
			defaultValue = defVal;
			hasDefault = true;
			return this;
		}

		@Override
		public Converting keysIgnoreCase() {
			del.keysIgnoreCase();
			return this;
		}

		@Override
		public void setConverter(Converter c) {
			del.setConverter(c);
		}

		@Override
		public Converting sourceAs(Class< ? > type) {
			del.sourceAs(type);
			return this;
		}

		@Override
		public Converting sourceAsBean() {
			del.sourceAsBean();
			return this;
		}

		@Override
		public Converting sourceAsDTO() {
			del.sourceAsDTO();
			return this;
		}

		@Override
		public Converting targetAs(Class< ? > cls) {
			del.targetAs(cls);
			return this;
		}

		@Override
		public Converting targetAsBean() {
			del.targetAsBean();
			return this;
		}

		@Override
		public Converting targetAsDTO() {
			del.targetAsDTO();
			return this;
		}

		@SuppressWarnings("unchecked")
		@Override
		public <T> T to(Class<T> cls) {
			Type type = cls;
			return (T) to(type);
		}

		@SuppressWarnings("unchecked")
		@Override
		public <T> T to(TypeReference<T> ref) {
			return (T) to(ref.getType());
		}

		@SuppressWarnings("unchecked")
		@Override
		public Object to(Type type) {
			List<ConverterFunction> tr = typeRules.get(Util.baseType(type));
			if (tr == null)
				tr = Collections.emptyList();
			List<ConverterFunction> converters = new ArrayList<>(
					tr.size() + allRules.size());
			converters.addAll(tr);
			converters.addAll(allRules);

			try {
				if (object != null) {
					for (ConverterFunction cf : converters) {
						try {
							Object res = cf.apply(object, type);
							if (res != ConverterFunction.CANNOT_HANDLE) {
								return res;
							}
						} catch (Exception ex) {
							if (hasDefault)
								return defaultValue;
							else
								throw new ConversionException("Cannot convert "
										+ object + " to " + type, ex);
						}
					}
				}

				return del.to(type);
			} catch (Exception ex) {
				for (ConverterFunction eh : errorHandlers) {
					try {
						Object handled = eh.apply(object, type);
						if (handled != ConverterFunction.CANNOT_HANDLE)
							return handled;
					} catch (RuntimeException re) {
						throw re;
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				}

				// No error handler, throw the original exception
				throw ex;
			}
		}

		@Override
		public String toString() {
			return to(String.class);
		}
	}
}
