/*
 * 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.felix.dm.lambda.impl;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;

import org.apache.felix.dm.BundleDependency;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.lambda.BundleDependencyBuilder;
import org.apache.felix.dm.lambda.callbacks.CbBundle;
import org.apache.felix.dm.lambda.callbacks.CbBundleComponent;
import org.apache.felix.dm.lambda.callbacks.InstanceCbBundle;
import org.apache.felix.dm.lambda.callbacks.InstanceCbBundleComponent;
import org.osgi.framework.Bundle;

@SuppressWarnings("unchecked")
public class BundleDependencyBuilderImpl implements BundleDependencyBuilder {
	private String m_added;
	private String m_changed;
	private String m_removed;
	private Object m_instance;
	private boolean m_autoConfig = true;
	private boolean m_autoConfigInvoked = false;
	private boolean m_required = true;
	private Bundle m_bundle;
	private String m_filter;
	private int m_stateMask = -1;
	private boolean m_propagate;
	private Object m_propagateInstance;
	private String m_propagateMethod;
	private Function<Bundle, Dictionary<?, ?>> m_propagateCallback;
	private final Component m_component;
    
    enum Cb {
        ADD,        
        CHG,        
        REM
    };

	private final Map<Cb, List<MethodRef<Object>>> m_refs = new HashMap<>();

    @FunctionalInterface
    interface MethodRef<I> {
        public void accept(I instance, Component c, Bundle bundle);
    }

	/**
	 * Class used to call a supplier that returns Propagated properties
	 */
	private class Propagate {
		@SuppressWarnings("unused")
		Dictionary<?, ?> propagate(Bundle bundle) {
			return m_propagateCallback.apply(bundle);
		}
	}

    public BundleDependencyBuilderImpl (Component component) {
        m_component = component;
    }

    @Override
    public BundleDependencyBuilder autoConfig(boolean autoConfig) {
        m_autoConfig = autoConfig;
        m_autoConfigInvoked = true;
        return this;
    }

    @Override
    public BundleDependencyBuilder autoConfig() {
        autoConfig(true);
        return this;
    }

    @Override
    public BundleDependencyBuilder required(boolean required) {
        m_required = required;
        return this;
    }

    @Override
    public BundleDependencyBuilder required() {
        required(true);
        return this;
    }

    @Override
    public BundleDependencyBuilder bundle(Bundle bundle) {
        m_bundle = bundle;
        return this;
    }

    @Override
    public BundleDependencyBuilder filter(String filter) throws IllegalArgumentException {
        m_filter = filter;
        return this;
    }

    @Override
    public BundleDependencyBuilder mask(int mask) {
        m_stateMask = mask;
        return this;
    }

    @Override
    public BundleDependencyBuilder propagate(boolean propagate) {
        m_propagate = propagate;
        return this;
    }

    @Override
    public BundleDependencyBuilder propagate() {
        propagate(true);
        return this;
    }

    @Override
    public BundleDependencyBuilder propagate(Object instance, String method) {
        if (m_propagateCallback != null || m_propagate) throw new IllegalStateException("Propagate callback already set.");
        Objects.nonNull(method);
        Objects.nonNull(instance);
        m_propagateInstance = instance;
        m_propagateMethod = method;
        return this;
    }

    @Override
    public BundleDependencyBuilder propagate(Function<Bundle, Dictionary<?, ?>> instance) {
        if (m_propagateInstance != null || m_propagate) throw new IllegalStateException("Propagate callback already set.");
        m_propagateCallback = instance;
        return this;
    }
    
    @Override
    public BundleDependencyBuilder callbackInstance(Object callbackInstance) {
        m_instance = callbackInstance;
        return this;
    }

    @Override
    public BundleDependencyBuilder add(String add) {
        callbacks(add, null, null);
        return this;
    }
    
    @Override
    public BundleDependencyBuilder change(String change) {
        callbacks(null, change, null);
        return this;
    }
    
    @Override
    public BundleDependencyBuilder remove(String remove) {
        callbacks(null, null, remove);
        return this;
    }
            
    private BundleDependencyBuilder callbacks(String added, String changed, String removed) {
        requiresNoMethodRefs();
        m_added = added != null ? added : m_added;
        m_changed = changed != null ? changed : m_changed;
        m_removed = removed != null ? removed : m_removed;
        if (! m_autoConfigInvoked) m_autoConfig = false;
        return this;
    }

    @Override
    public <T> BundleDependencyBuilder add(CbBundle<T> add) {
        return callbacks(add, null, null);
    }
    
    @Override
    public <T> BundleDependencyBuilder change(CbBundle<T> change) {
        return callbacks(null, change, null);
    }
    
    @Override
    public <T> BundleDependencyBuilder remove(CbBundle<T> remove) {
        return callbacks(null, null, remove);
    }
    
    private <T> BundleDependencyBuilder callbacks(CbBundle<T> add, CbBundle<T> change, CbBundle<T> remove) {
        if (add != null) {
            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, component, bundle) -> add.accept ((T) inst, bundle));
        }
        if (change != null) {
            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, component, bundle) -> change.accept ((T) inst, bundle));
        }
        if (remove != null) {
            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, component, bundle) -> remove.accept ((T) inst, bundle));
        }
        return this;
    }

    @Override
    public <T> BundleDependencyBuilder add(CbBundleComponent<T> add) {
        return callbacks(add, null, null);
    }
    
    @Override
    public <T> BundleDependencyBuilder change(CbBundleComponent<T> change) {
        return callbacks(null, change, null);
    }
    
    @Override
    public <T> BundleDependencyBuilder remove(CbBundleComponent<T> remove) {
        return callbacks(null, null, remove);
    }
    
    private <T> BundleDependencyBuilder callbacks(CbBundleComponent<T> add, CbBundleComponent<T> change, CbBundleComponent<T> remove) {
        if (add != null) {
            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, component, bundle) -> add.accept ((T) inst, bundle, component));
        }
        if (change != null) {
            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, component, bundle) -> change.accept ((T) inst, bundle, component));
        }
        if (remove != null) {
            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, component, bundle) -> remove.accept ((T) inst, bundle, component));
        }
        return this;  
    }
    
    @Override
    public BundleDependencyBuilder add(InstanceCbBundle add) {
        return callbacks(add, null, null);
    }
    
    @Override
    public BundleDependencyBuilder change(InstanceCbBundle change) {
        return callbacks(null, change, null);
    }
    
    @Override
    public BundleDependencyBuilder remove(InstanceCbBundle remove) {
        return callbacks(null, null, remove);
    }
    
    private BundleDependencyBuilder callbacks(InstanceCbBundle add, InstanceCbBundle change, InstanceCbBundle remove) {
        if (add != null) setInstanceCallbackRef(Cb.ADD, (inst, component, bundle) -> add.accept(bundle));
        if (change != null) setInstanceCallbackRef(Cb.CHG, (inst, component, bundle) -> change.accept(bundle));
        if (remove != null) setInstanceCallbackRef(Cb.REM, (inst, component, bundle) -> remove.accept(bundle));
        return this;
    }

    @Override
    public BundleDependencyBuilder add(InstanceCbBundleComponent add) {
        return callbacks(add, null, null);
    }
    
    @Override
    public BundleDependencyBuilder change(InstanceCbBundleComponent add) {
        return callbacks(add, null, null);
    }

    @Override
    public BundleDependencyBuilder remove(InstanceCbBundleComponent remove) {
        return callbacks(null, null, remove);
    }
    
    private BundleDependencyBuilder callbacks(InstanceCbBundleComponent add, InstanceCbBundleComponent change, InstanceCbBundleComponent remove) {
        if (add != null) setInstanceCallbackRef(Cb.ADD, (inst, component, bundle) -> add.accept(bundle, component));
        if (change != null) setInstanceCallbackRef(Cb.CHG, (inst, component, bundle) -> change.accept(bundle, component));
        if (remove != null) setInstanceCallbackRef(Cb.REM, (inst, component, bundle) -> remove.accept(bundle, component));
        return this;
    }

	@Override
	public BundleDependency build() {
        DependencyManager dm = m_component.getDependencyManager();

        BundleDependency dep = dm.createBundleDependency();
        dep.setRequired(m_required);
        
        if (m_filter != null) {
        	dep.setFilter(m_filter);
        }
        
        if (m_bundle != null) {
        	dep.setBundle(m_bundle);
        }
        
        if (m_stateMask != -1) {
        	dep.setStateMask(m_stateMask);
        }
        
        if (m_propagate) {
            dep.setPropagate(true);
        } else if (m_propagateInstance != null) {
            dep.setPropagate(m_propagateInstance, m_propagateMethod);
        } else if (m_propagateCallback != null) {
        	dep.setPropagate(new Propagate(), "propagate");
        }
        
        if (m_added != null || m_changed != null || m_removed != null) {
            dep.setCallbacks(m_instance, m_added, m_changed, m_removed);
        } else if (m_refs.size() > 0) {
            Object cb = createCallbackInstance();
            dep.setCallbacks(cb, "add", "change", "remove");
        } 
        
        dep.setAutoConfig(m_autoConfig);
        return dep;
	}

	private <T> BundleDependencyBuilder setInstanceCallbackRef(Cb cbType, MethodRef<T> ref) {
		requiresNoStringCallbacks();
		if (! m_autoConfigInvoked) m_autoConfig = false;
		List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
		list.add((instance, component, bundle) -> ref.accept(null, component, bundle));
		return this;
	}
	
	private <T> BundleDependencyBuilder setComponentCallbackRef(Cb cbType, Class<T> type, MethodRef<T> ref) {
	    requiresNoStringCallbacks();
		if (! m_autoConfigInvoked) m_autoConfig = false;
		List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
		list.add((instance, component, bundle) -> {
            Object componentImpl = Stream.of(component.getInstances())
                .filter(impl -> Helpers.getClass(impl).equals(type))
                .findFirst()
                .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));           
            ref.accept((T) componentImpl, component, bundle);
		});
		return this;
	}
	    
	@SuppressWarnings("unused")
	private Object createCallbackInstance() {
		Object cb = null;

		cb = new Object() {
			void add(Component c, Bundle bundle) {
				invokeMethodRefs(Cb.ADD, c, bundle);
			}

			void change(Component c, Bundle bundle) {
				invokeMethodRefs(Cb.CHG, c, bundle);
			}

			void remove(Component c, Bundle bundle) {
				invokeMethodRefs(Cb.REM, c, bundle);
			}
		};

		return cb;
	}

	private void invokeMethodRefs(Cb cbType, Component c, Bundle bundle) {
		m_refs.computeIfPresent(cbType, (k, mrefs) -> {
			mrefs.forEach(mref -> mref.accept(null, c, bundle));
			return mrefs;
		});
	}
	
	private void requiresNoStringCallbacks() {
		if (m_added != null || m_changed != null || m_removed != null) {
			throw new IllegalStateException("can't mix method references and string callbacks.");
		}
	}
	
	private void requiresNoMethodRefs() {
		if (m_refs.size() > 0) {
			throw new IllegalStateException("can't mix method references and string callbacks.");
		}
	}
}
