/*
 * 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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;

import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.lambda.BundleAdapterBuilder;
import org.apache.felix.dm.lambda.ComponentBuilder;
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;

public class BundleAdapterBuilderImpl implements AdapterBase<BundleAdapterBuilder>, BundleAdapterBuilder {
    private Consumer<ComponentBuilder<?>> m_compBuilder = (compBuilder -> {});
    protected final Map<Cb, List<MethodRef<Object>>> m_refs = new HashMap<>();
    private DependencyManager m_dm;
    private boolean m_autoAdd;
    private String m_filter;
    private int m_stateMask = -1;
    private boolean m_propagate;
    private Object m_callbackInstance;
    private String m_add;
    private String m_change;
    private String m_remove;

    enum Cb {
        ADD,        
        CHG,        
        REM
    };

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

    public BundleAdapterBuilderImpl(DependencyManager dm) {
        m_dm = dm;
    }
    
    public void andThenBuild(Consumer<ComponentBuilder<?>> builder) {
        m_compBuilder = m_compBuilder.andThen(builder);
    }

    @Override
    public BundleAdapterBuilderImpl autoAdd(boolean autoAdd) {
        m_autoAdd = autoAdd;
        return this;
    }
        
    public boolean isAutoAdd() {
        return m_autoAdd;
    }

    public BundleAdapterBuilder mask(int mask) {
        m_stateMask = mask;
        return this;
    }
    
    public BundleAdapterBuilder filter(String filter) {
        m_filter = filter;
        return this;
    }

    public BundleAdapterBuilder propagate(boolean propagate) {
        m_propagate = propagate;
        return this;
    }
    
    public BundleAdapterBuilder propagate() {
        m_propagate = true;
        return this;
    }

    public BundleAdapterBuilder add(String callback) {
        return callbacks(callback, null, null);
    }
    
    public BundleAdapterBuilder change(String callback) {
        return callbacks(null, callback, null);
    }
    
    public BundleAdapterBuilder remove(String callback) {
        return callbacks(null, null, callback);
    }
    
    public BundleAdapterBuilder callbackInstance(Object callbackInstance) {
        m_callbackInstance = callbackInstance;
        return this;
    }
    
    private BundleAdapterBuilder callbacks(String add, String change, String remove) {
        checkHasNoMethodRefs();
        m_add = add != null ? add : m_add;
        m_change = change != null ? change : m_change;
        m_remove = remove != null ? remove : m_remove;
        return this;
    }
    
    public <T> BundleAdapterBuilder add(CbBundle<T> add) {
        return callbacks(add, (CbBundle<T>) null, (CbBundle<T>) null);
    }

    public <T> BundleAdapterBuilder change(CbBundle<T> change) {
        return callbacks(null, change, null);
    }

    public <T> BundleAdapterBuilder remove(CbBundle<T> remove) {
        return callbacks(null, null, remove);
    }

    private <T> BundleAdapterBuilder callbacks(CbBundle<T> add, CbBundle<T> change, CbBundle<T> remove) {
        if (add != null) {
            Class<T> type = Helpers.getLambdaArgType(add, 0);
            setComponentCallbackRef(Cb.ADD, type, (instance, component, bundle) -> { add.accept((T) instance, bundle); });
        }
        if (change != null) {
            Class<T> type = Helpers.getLambdaArgType(change, 0);
            setComponentCallbackRef(Cb.CHG, type, (instance, component, bundle) -> { change.accept((T) instance, bundle); });
        }
        if (remove != null) {
            Class<T> type = Helpers.getLambdaArgType(remove, 0);
            setComponentCallbackRef(Cb.REM, type, (instance, component, bundle) -> { remove.accept((T) instance, bundle); });
        }
        return this;
    }
    
    public BundleAdapterBuilder add(InstanceCbBundle add) {
        return callbacks(add, null, null);
    }
    
    public BundleAdapterBuilder change(InstanceCbBundle change) {
        return callbacks(null, change, null);
    }

    public BundleAdapterBuilder remove(InstanceCbBundle remove) {
        return callbacks(null, null, remove);
    }

    public BundleAdapterBuilder callbacks(InstanceCbBundle add, InstanceCbBundle change, InstanceCbBundle remove) {
        if (add != null) setInstanceCallbackRef(Cb.ADD, (instance, component, bundle) -> { add.accept(bundle); });
        if (change != null) setInstanceCallbackRef(Cb.CHG, (instance, component, bundle) -> { change.accept(bundle); });
        if (remove != null) setInstanceCallbackRef(Cb.REM, (instance, component, bundle) -> { remove.accept(bundle); });
        return this;
    }
    
    public <T> BundleAdapterBuilder add(CbBundleComponent<T> add) {
        return callbacks(add, null, null);
    }
    
    public <T> BundleAdapterBuilder change(CbBundleComponent<T> change) {
        return callbacks(null, change, null);
    }
    
    public <T> BundleAdapterBuilder remove(CbBundleComponent<T> remove) {
        return callbacks(null, null, remove);
    }
    
    public <T> BundleAdapterBuilder callbacks(CbBundleComponent<T> add, CbBundleComponent<T> change, CbBundleComponent<T> remove) {
        if (add != null) {
            Class<T> type = Helpers.getLambdaArgType(add, 0);
            return setComponentCallbackRef(Cb.ADD, type, (instance, component, bundle) -> { add.accept((T) instance, bundle, component); });
        }
        if (change != null) {
            Class<T> type = Helpers.getLambdaArgType(change, 0);
            return setComponentCallbackRef(Cb.CHG, type, (instance, component, bundle) -> { change.accept((T) instance, bundle, component); });
        }
        if (remove != null) {
            Class<T> type = Helpers.getLambdaArgType(remove, 0);
            return setComponentCallbackRef(Cb.ADD, type, (instance, component, bundle) -> { remove.accept((T) instance, bundle, component); });
        }
        return this;
    }
    
    public BundleAdapterBuilder add(InstanceCbBundleComponent add) {
        return callbacks(add, null, null);
    }
    
    public BundleAdapterBuilder change(InstanceCbBundleComponent change) {
        return callbacks(null, change, null);
    }
    
    public BundleAdapterBuilder remove(InstanceCbBundleComponent remove) {
        return callbacks(null, null, remove);
    }
    
    public BundleAdapterBuilder callbacks(InstanceCbBundleComponent add, InstanceCbBundleComponent change, InstanceCbBundleComponent remove) {
        if (add != null) setInstanceCallbackRef(Cb.ADD, (instance, component, bundle) -> { add.accept(bundle, component); });
        if (change != null) setInstanceCallbackRef(Cb.CHG, (instance, component, bundle) -> { change.accept(bundle, component); });
        if (remove != null) setInstanceCallbackRef(Cb.REM, (instance, component, bundle) -> { remove.accept(bundle, component); });
        return this;
    }

    @Override
    public Component build() { 
        Component c = null;
        
        if (m_refs.size() > 0) {
            @SuppressWarnings("unused")
            Object wrapCallback = new Object() {
                public void add(Component comp, Bundle bundle) {
                    invokeMethodRefs(Cb.ADD, comp, bundle);
                }
                
                public void change(Component comp, Bundle bundle) {
                    invokeMethodRefs(Cb.CHG, comp, bundle);
                }

                public void remove(Component comp, Bundle bundle) {
                    invokeMethodRefs(Cb.REM, comp, bundle);
                }
            };
            c = m_dm.createBundleAdapterService(m_stateMask, m_filter, m_propagate, wrapCallback, "add", "change", "remove");
        } else {
            c = m_dm.createBundleAdapterService(m_stateMask, m_filter, m_propagate, m_callbackInstance, m_add, m_change, m_remove);
        }
        ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false);
        m_compBuilder.accept (cb);
        return cb.build();        
    }
    
    private <U> BundleAdapterBuilder setInstanceCallbackRef(Cb cbType, MethodRef<U> ref) {
        checkHasNoReflectionCallbacks();
        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
        list.add((instance, component, bundle) -> ref.accept(null, component, bundle));
        return this;
    }
    
    @SuppressWarnings("unchecked")
    private <U> BundleAdapterBuilder setComponentCallbackRef(Cb cbType, Class<U> type, MethodRef<U> ref) {
        checkHasNoReflectionCallbacks();
        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>());
        list.add((instance, component, bundle) -> {
            Object componentImpl = Stream.of(component.getInstances())
                .filter(impl -> type.isAssignableFrom(Helpers.getClass(impl)))
                .findFirst()
                .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes."));           
            ref.accept((U) componentImpl, component, bundle);
        });
        return this;
    }
    
    private void invokeMethodRefs(Cb cbType, Component comp, Bundle bundle) {
        m_refs.computeIfPresent(cbType, (k, mrefs) -> {
            mrefs.forEach(mref -> mref.accept(null, comp, bundle));
            return mrefs;
         });
     }

    private void checkHasNoMethodRefs() {
        if (m_refs.size() > 0) {
            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
        }
    }
    
    private void checkHasNoReflectionCallbacks() {
        if (m_add != null || m_change != null || m_remove != null) {
            throw new IllegalStateException("Can't mix method references with reflection based callbacks");
        }
    }
}
